diff --git a/frontend/src/Components/Error/ErrorBoundaryError.tsx b/frontend/src/Components/Error/ErrorBoundaryError.tsx index 42510e5c3..14bd8a87f 100644 --- a/frontend/src/Components/Error/ErrorBoundaryError.tsx +++ b/frontend/src/Components/Error/ErrorBoundaryError.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import StackTrace from 'stacktrace-js'; +import translate from 'Utilities/String/translate'; import styles from './ErrorBoundaryError.css'; interface ErrorBoundaryErrorProps { @@ -18,7 +19,7 @@ function ErrorBoundaryError(props: ErrorBoundaryErrorProps) { className = styles.container, messageClassName = styles.message, detailsClassName = styles.details, - message = 'There was an error loading this content', + message = translate('ErrorLoadingContent'), error, info, } = props; diff --git a/frontend/src/Components/FileBrowser/FileBrowserModalContent.js b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js index f285ed529..56b364b56 100644 --- a/frontend/src/Components/FileBrowser/FileBrowserModalContent.js +++ b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js @@ -3,7 +3,6 @@ import React, { Component } from 'react'; import Alert from 'Components/Alert'; import PathInput from 'Components/Form/PathInput'; import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import ModalBody from 'Components/Modal/ModalBody'; import ModalContent from 'Components/Modal/ModalContent'; @@ -14,6 +13,7 @@ import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; import { kinds, scrollDirections } from 'Helpers/Props'; import translate from 'Utilities/String/translate'; +import InlineMarkdown from '../Markdown/InlineMarkdown'; import FileBrowserRow from './FileBrowserRow'; import styles from './FileBrowserModalContent.css'; @@ -104,7 +104,7 @@ class FileBrowserModalContent extends Component { onModalClose={onModalClose} > - File Browser + {translate('FileBrowser')} - Mapped network drives are not available when running as a Windows Service, see the FAQ for more information. + } { !!error && -
Error loading contents
+
{translate('ErrorLoadingContents')}
} { @@ -151,7 +151,7 @@ class FileBrowserModalContent extends Component { emptyParent && @@ -212,13 +212,13 @@ class FileBrowserModalContent extends Component { diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js index 6b5846594..9492f4577 100644 --- a/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import TagInputTag from 'Components/Form/TagInputTag'; import { kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './FilterBuilderRowValueTag.css'; function FilterBuilderRowValueTag(props) { @@ -18,7 +19,7 @@ function FilterBuilderRowValueTag(props) { props.isLastTag ? null :
- or + {translate('or')}
} diff --git a/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js index dab67a645..3464300f1 100644 --- a/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js +++ b/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js @@ -1,11 +1,32 @@ import React from 'react'; +import translate from 'Utilities/String/translate'; import FilterBuilderRowValue from './FilterBuilderRowValue'; const seriesStatusList = [ - { id: 'continuing', name: 'Continuing' }, - { id: 'upcoming', name: 'Upcoming' }, - { id: 'ended', name: 'Ended' }, - { id: 'deleted', name: 'Deleted' } + { + id: 'continuing', + get name() { + 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) { diff --git a/frontend/src/Components/Filter/Builder/SeriesTypeFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/SeriesTypeFilterBuilderRowValue.js index 263c9e9da..2e62e558d 100644 --- a/frontend/src/Components/Filter/Builder/SeriesTypeFilterBuilderRowValue.js +++ b/frontend/src/Components/Filter/Builder/SeriesTypeFilterBuilderRowValue.js @@ -1,10 +1,26 @@ import React from 'react'; +import translate from 'Utilities/String/translate'; import FilterBuilderRowValue from './FilterBuilderRowValue'; const seriesTypeList = [ - { id: 'anime', name: 'Anime' }, - { id: 'daily', name: 'Daily' }, - { id: 'standard', name: 'Standard' } + { + id: 'anime', + get name() { + return translate('Anime'); + } + }, + { + id: 'daily', + get name() { + return translate('Daily'); + } + }, + { + id: 'standard', + get name() { + return translate('Standard'); + } + } ]; function SeriesTypeFilterBuilderRowValue(props) { diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFilter.js b/frontend/src/Components/Filter/CustomFilters/CustomFilter.js index e87d088b3..7407f729a 100644 --- a/frontend/src/Components/Filter/CustomFilters/CustomFilter.js +++ b/frontend/src/Components/Filter/CustomFilters/CustomFilter.js @@ -3,6 +3,7 @@ import React, { Component } from 'react'; import IconButton from 'Components/Link/IconButton'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './CustomFilter.css'; class CustomFilter extends Component { @@ -89,7 +90,7 @@ class CustomFilter extends Component { /> - Custom Filters + {translate('CustomFilters')} @@ -49,7 +50,7 @@ function CustomFiltersModalContent(props) {
@@ -58,7 +59,7 @@ function CustomFiltersModalContent(props) { diff --git a/frontend/src/Components/Form/DownloadClientSelectInputConnector.js b/frontend/src/Components/Form/DownloadClientSelectInputConnector.js index c89016869..f0ebf534b 100644 --- a/frontend/src/Components/Form/DownloadClientSelectInputConnector.js +++ b/frontend/src/Components/Form/DownloadClientSelectInputConnector.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { fetchDownloadClients } from 'Store/Actions/settingsActions'; import sortByName from 'Utilities/Array/sortByName'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInput from './EnhancedSelectInput'; function createMapStateToProps() { @@ -32,7 +33,7 @@ function createMapStateToProps() { if (includeAny) { values.unshift({ key: 0, - value: '(Any)' + value: `(${translate('Any')})` }); } diff --git a/frontend/src/Components/Form/FormInputGroup.js b/frontend/src/Components/Form/FormInputGroup.js index 805b97217..6f3155f5b 100644 --- a/frontend/src/Components/Form/FormInputGroup.js +++ b/frontend/src/Components/Form/FormInputGroup.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import Link from 'Components/Link/Link'; import { inputTypes, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import AutoCompleteInput from './AutoCompleteInput'; import CaptchaInputConnector from './CaptchaInputConnector'; import CheckInput from './CheckInput'; @@ -215,7 +216,7 @@ function FormInputGroup(props) { - More Info + {translate('MoreInfo')} } diff --git a/frontend/src/Components/Form/IndexerSelectInputConnector.js b/frontend/src/Components/Form/IndexerSelectInputConnector.js index cd58270eb..91c31198f 100644 --- a/frontend/src/Components/Form/IndexerSelectInputConnector.js +++ b/frontend/src/Components/Form/IndexerSelectInputConnector.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { fetchIndexers } from 'Store/Actions/settingsActions'; import sortByName from 'Utilities/Array/sortByName'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInput from './EnhancedSelectInput'; function createMapStateToProps() { @@ -29,7 +30,7 @@ function createMapStateToProps() { if (includeAny) { values.unshift({ key: 0, - value: '(Any)' + value: `(${translate('Any')})` }); } diff --git a/frontend/src/Components/Form/MonitorEpisodesSelectInput.js b/frontend/src/Components/Form/MonitorEpisodesSelectInput.js index f26693e64..9b80cc587 100644 --- a/frontend/src/Components/Form/MonitorEpisodesSelectInput.js +++ b/frontend/src/Components/Form/MonitorEpisodesSelectInput.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import monitorOptions from 'Utilities/Series/monitorOptions'; +import translate from 'Utilities/String/translate'; import SelectInput from './SelectInput'; function MonitorEpisodesSelectInput(props) { @@ -15,7 +16,9 @@ function MonitorEpisodesSelectInput(props) { if (includeNoChange) { values.unshift({ key: 'noChange', - value: 'No Change', + get value() { + return translate('NoChange'); + }, disabled: true }); } @@ -23,7 +26,9 @@ function MonitorEpisodesSelectInput(props) { if (includeMixed) { values.unshift({ key: 'mixed', - value: '(Mixed)', + get value() { + return `(${translate('Mixed')})`; + }, disabled: true }); } diff --git a/frontend/src/Components/Form/QualityProfileSelectInputConnector.js b/frontend/src/Components/Form/QualityProfileSelectInputConnector.js index 2304a0d67..cc8ffbdb8 100644 --- a/frontend/src/Components/Form/QualityProfileSelectInputConnector.js +++ b/frontend/src/Components/Form/QualityProfileSelectInputConnector.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; import sortByName from 'Utilities/Array/sortByName'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInput from './EnhancedSelectInput'; function createMapStateToProps() { @@ -24,7 +25,9 @@ function createMapStateToProps() { if (includeNoChange) { values.unshift({ key: 'noChange', - value: 'No Change', + get value() { + return translate('NoChange'); + }, disabled: includeNoChangeDisabled }); } @@ -32,7 +35,9 @@ function createMapStateToProps() { if (includeMixed) { values.unshift({ key: 'mixed', - value: '(Mixed)', + get value() { + return `(${translate('Mixed')})`; + }, disabled: true }); } diff --git a/frontend/src/Components/Form/RootFolderSelectInputConnector.js b/frontend/src/Components/Form/RootFolderSelectInputConnector.js index 11a00841c..dc5930417 100644 --- a/frontend/src/Components/Form/RootFolderSelectInputConnector.js +++ b/frontend/src/Components/Form/RootFolderSelectInputConnector.js @@ -3,6 +3,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { addRootFolder } from 'Store/Actions/rootFolderActions'; +import translate from 'Utilities/String/translate'; import RootFolderSelectInput from './RootFolderSelectInput'; const ADD_NEW_KEY = 'addNew'; @@ -27,7 +28,9 @@ function createMapStateToProps() { if (includeNoChange) { values.unshift({ key: 'noChange', - value: 'No Change', + get value() { + return translate('NoChange'); + }, isDisabled: includeNoChangeDisabled, isMissing: false }); @@ -53,7 +56,7 @@ function createMapStateToProps() { values.push({ key: ADD_NEW_KEY, - value: 'Add a new path' + value: translate('AddANewPath') }); return { diff --git a/frontend/src/Components/Form/RootFolderSelectInputOption.js b/frontend/src/Components/Form/RootFolderSelectInputOption.js index 3197ba875..daac82f34 100644 --- a/frontend/src/Components/Form/RootFolderSelectInputOption.js +++ b/frontend/src/Components/Form/RootFolderSelectInputOption.js @@ -2,6 +2,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInputOption from './EnhancedSelectInputOption'; import styles from './RootFolderSelectInputOption.css'; @@ -47,14 +48,14 @@ function RootFolderSelectInputOption(props) { freeSpace == null ? null :
- {formatBytes(freeSpace)} Free + {translate('RootFolderSelectFreeSpace', { freeSpace: formatBytes(freeSpace) })}
} { isMissing ?
- Missing + {translate('Missing')}
: null } diff --git a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js b/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js index 69b1453f3..1c3a4fc9d 100644 --- a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js +++ b/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue'; import styles from './RootFolderSelectInputSelectedValue.css'; @@ -39,7 +40,7 @@ function RootFolderSelectInputSelectedValue(props) { { freeSpace != null && includeFreeSpace &&
- {formatBytes(freeSpace)} Free + {translate('RootFolderSelectFreeSpace', { freeSpace: formatBytes(freeSpace) })}
} diff --git a/frontend/src/Components/Form/SeriesTypeSelectInput.tsx b/frontend/src/Components/Form/SeriesTypeSelectInput.tsx index d996e5b34..72f0ed9ac 100644 --- a/frontend/src/Components/Form/SeriesTypeSelectInput.tsx +++ b/frontend/src/Components/Form/SeriesTypeSelectInput.tsx @@ -1,5 +1,6 @@ import React from 'react'; import * as seriesTypes from 'Utilities/Series/seriesTypes'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInput from './EnhancedSelectInput'; import SeriesTypeSelectInputOption from './SeriesTypeSelectInputOption'; import SeriesTypeSelectInputSelectedValue from './SeriesTypeSelectInputSelectedValue'; @@ -21,17 +22,23 @@ const seriesTypeOptions: ISeriesTypeOption[] = [ { key: seriesTypes.STANDARD, value: 'Standard', - format: 'Season and episode numbers (S01E05)', + get format() { + return translate('StandardTypeFormat', { format: 'S01E05' }); + }, }, { key: seriesTypes.DAILY, value: 'Daily / Date', - format: 'Date (2020-05-25)', + get format() { + return translate('DailyTypeFormat', { format: '2020-05-25' }); + }, }, { key: seriesTypes.ANIME, 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) { values.unshift({ key: 'noChange', - value: 'No Change', + value: translate('NoChange'), disabled: includeNoChangeDisabled, }); } @@ -55,7 +62,7 @@ function SeriesTypeSelectInput(props: SeriesTypeSelectInputProps) { if (includeMixed) { values.unshift({ key: 'mixed', - value: '(Mixed)', + value: `(${translate('Mixed')})`, disabled: true, }); } diff --git a/frontend/src/Components/Form/UMaskInput.js b/frontend/src/Components/Form/UMaskInput.js index 22f51c8fc..adec30c93 100644 --- a/frontend/src/Components/Form/UMaskInput.js +++ b/frontend/src/Components/Form/UMaskInput.js @@ -1,33 +1,44 @@ /* eslint-disable no-bitwise */ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import translate from 'Utilities/String/translate'; import EnhancedSelectInput from './EnhancedSelectInput'; import styles from './UMaskInput.css'; const umaskOptions = [ { key: '755', - value: '755 - Owner write, Everyone else read', + get value() { + return translate('Umask755Description', { octal: '755' }); + }, hint: 'drwxr-xr-x' }, { key: '775', - value: '775 - Owner & Group write, Other read', + get value() { + return translate('Umask775Description', { octal: '775' }); + }, hint: 'drwxrwxr-x' }, { key: '770', - value: '770 - Owner & Group write', + get value() { + return translate('Umask770Description', { octal: '770' }); + }, hint: 'drwxrwx---' }, { key: '750', - value: '750 - Owner write, Group read', + get value() { + return translate('Umask750Description', { octal: '750' }); + }, hint: 'drwxr-x---' }, { key: '777', - value: '777 - Everyone write', + get value() { + return translate('Umask777Description', { octal: '777' }); + }, hint: 'drwxrwxrwx' } ]; @@ -101,16 +112,16 @@ class UMaskInput extends Component {
- +
{umask}
- +
{folder}
d{formatPermissions(folderNum)}
- +
{file}
{formatPermissions(fileNum)}
diff --git a/frontend/src/Components/Link/IconButton.js b/frontend/src/Components/Link/IconButton.js index 6f5e56d0e..fffbe13e0 100644 --- a/frontend/src/Components/Link/IconButton.js +++ b/frontend/src/Components/Link/IconButton.js @@ -2,6 +2,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import Icon from 'Components/Icon'; +import translate from 'Utilities/String/translate'; import Link from './Link'; import styles from './IconButton.css'; @@ -23,7 +24,7 @@ function IconButton(props) { className, isDisabled && styles.isDisabled )} - aria-label="Table Options Button" + aria-label={translate('TableOptionsButton')} isDisabled={isDisabled} {...otherProps} > diff --git a/frontend/src/Components/Menu/FilterMenu.js b/frontend/src/Components/Menu/FilterMenu.js index 2ed1235ee..c36c4ae3b 100644 --- a/frontend/src/Components/Menu/FilterMenu.js +++ b/frontend/src/Components/Menu/FilterMenu.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import FilterMenuContent from './FilterMenuContent'; import Menu from './Menu'; import ToolbarMenuButton from './ToolbarMenuButton'; @@ -58,7 +59,7 @@ class FilterMenu extends Component { diff --git a/frontend/src/Components/Menu/FilterMenuContent.js b/frontend/src/Components/Menu/FilterMenuContent.js index 5d978c9ca..516fbb648 100644 --- a/frontend/src/Components/Menu/FilterMenuContent.js +++ b/frontend/src/Components/Menu/FilterMenuContent.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import translate from 'Utilities/String/translate'; import FilterMenuItem from './FilterMenuItem'; import MenuContent from './MenuContent'; import MenuItem from './MenuItem'; @@ -61,7 +62,7 @@ class FilterMenuContent extends Component { { showCustomFilters && - Custom Filters + {translate('CustomFilters')} } diff --git a/frontend/src/Components/Menu/Menu.js b/frontend/src/Components/Menu/Menu.js index 7e5e0b672..8f0b2996c 100644 --- a/frontend/src/Components/Menu/Menu.js +++ b/frontend/src/Components/Menu/Menu.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import { Manager, Popper, Reference } from 'react-popper'; import Portal from 'Components/Portal'; import { align } from 'Helpers/Props'; -import getUniqueElememtId from 'Utilities/getUniqueElementId'; +import getUniqueElementId from 'Utilities/getUniqueElementId'; import styles from './Menu.css'; const sharedPopperOptions = { @@ -38,8 +38,8 @@ class Menu extends Component { super(props, context); this._scheduleUpdate = null; - this._menuButtonId = getUniqueElememtId(); - this._menuContentId = getUniqueElememtId(); + this._menuButtonId = getUniqueElementId(); + this._menuContentId = getUniqueElementId(); this.state = { isMenuOpen: false, diff --git a/frontend/src/Components/Menu/SortMenu.js b/frontend/src/Components/Menu/SortMenu.js index ec068fdf9..10a8e162f 100644 --- a/frontend/src/Components/Menu/SortMenu.js +++ b/frontend/src/Components/Menu/SortMenu.js @@ -3,6 +3,7 @@ import React from 'react'; import Menu from 'Components/Menu/Menu'; import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; import { align, icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; function SortMenu(props) { const { @@ -19,7 +20,7 @@ function SortMenu(props) { > {children} diff --git a/frontend/src/Components/Menu/ViewMenu.js b/frontend/src/Components/Menu/ViewMenu.js index 7eb505b8f..a7e56a8c5 100644 --- a/frontend/src/Components/Menu/ViewMenu.js +++ b/frontend/src/Components/Menu/ViewMenu.js @@ -3,6 +3,7 @@ import React from 'react'; import Menu from 'Components/Menu/Menu'; import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; import { align, icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; function ViewMenu(props) { const { @@ -17,7 +18,7 @@ function ViewMenu(props) { > {children} diff --git a/frontend/src/Components/MetadataAttribution.js b/frontend/src/Components/MetadataAttribution.js index 3188a8281..b32eea696 100644 --- a/frontend/src/Components/MetadataAttribution.js +++ b/frontend/src/Components/MetadataAttribution.js @@ -1,5 +1,6 @@ import React from 'react'; import Link from 'Components/Link/Link'; +import translate from 'Utilities/String/translate'; import styles from './MetadataAttribution.css'; export default function MetadataAttribution() { @@ -9,7 +10,7 @@ export default function MetadataAttribution() { className={styles.attribution} to="/settings/metadatasource" > - Metadata is provided by TheTVDB + {translate('MetadataProvidedBy', { provider: 'TheTVDB' })}
); diff --git a/frontend/src/Components/Modal/ModalError.js b/frontend/src/Components/Modal/ModalError.js index d38767ea4..56b26a1d2 100644 --- a/frontend/src/Components/Modal/ModalError.js +++ b/frontend/src/Components/Modal/ModalError.js @@ -6,6 +6,7 @@ import ModalBody from 'Components/Modal/ModalBody'; import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; +import translate from 'Utilities/String/translate'; import styles from './ModalError.css'; function ModalError(props) { @@ -17,7 +18,7 @@ function ModalError(props) { return ( - Error + {translate('Error')} @@ -25,7 +26,7 @@ function ModalError(props) { messageClassName={styles.message} detailsClassName={styles.details} {...otherProps} - message='There was an error loading this item' + message={translate('ErrorLoadingItem')} /> @@ -33,7 +34,7 @@ function ModalError(props) { diff --git a/frontend/src/Components/MonitorToggleButton.js b/frontend/src/Components/MonitorToggleButton.js index 4230a35a9..cb92e43ba 100644 --- a/frontend/src/Components/MonitorToggleButton.js +++ b/frontend/src/Components/MonitorToggleButton.js @@ -3,18 +3,19 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './MonitorToggleButton.css'; function getTooltip(monitored, isDisabled) { if (isDisabled) { - return 'Cannot toggle monitored state when series is unmonitored'; + return translate('ToggleMonitoredSeriesUnmonitored '); } if (monitored) { - return 'Monitored, click to unmonitor'; + return translate('ToggleMonitoredToUnmonitored'); } - return 'Unmonitored, click to monitor'; + return translate('ToggleUnmonitoredToMonitored'); } class MonitorToggleButton extends Component { diff --git a/frontend/src/Components/NotFound.js b/frontend/src/Components/NotFound.js index 7043da46f..da4221200 100644 --- a/frontend/src/Components/NotFound.js +++ b/frontend/src/Components/NotFound.js @@ -1,9 +1,12 @@ import PropTypes from 'prop-types'; import React from 'react'; import PageContent from 'Components/Page/PageContent'; +import translate from 'Utilities/String/translate'; import styles from './NotFound.css'; -function NotFound({ message }) { +function NotFound(props) { + const { message = translate('DefaultNotFoundMessage') } = props; + return (
@@ -21,11 +24,7 @@ function NotFound({ message }) { } NotFound.propTypes = { - message: PropTypes.string.isRequired -}; - -NotFound.defaultProps = { - message: 'You must be lost, nothing to see here.' + message: PropTypes.string }; export default NotFound; diff --git a/frontend/src/Components/Page/ErrorPage.js b/frontend/src/Components/Page/ErrorPage.js index 214c9dcc9..f76522454 100644 --- a/frontend/src/Components/Page/ErrorPage.js +++ b/frontend/src/Components/Page/ErrorPage.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; +import translate from 'Utilities/String/translate'; import styles from './ErrorPage.css'; function ErrorPage(props) { @@ -16,24 +17,24 @@ function ErrorPage(props) { systemStatusError } = props; - let errorMessage = 'Failed to load Sonarr'; + let errorMessage = translate('FailedToLoadSonarr'); 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) { - errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API'); + errorMessage = getErrorMessage(translationsError, translate('FailedToLoadTranslationsFromApi')); } else if (seriesError) { - errorMessage = getErrorMessage(seriesError, 'Failed to load series from API'); + errorMessage = getErrorMessage(seriesError, translate('FailedToLoadSeriesFromApi')); } else if (customFiltersError) { - errorMessage = getErrorMessage(customFiltersError, 'Failed to load custom filters from API'); + errorMessage = getErrorMessage(customFiltersError, translate('FailedToLoadCustomFiltersFromApi')); } else if (tagsError) { - errorMessage = getErrorMessage(tagsError, 'Failed to load tags from API'); + errorMessage = getErrorMessage(tagsError, translate('FailedToLoadTagsFromApi')); } else if (qualityProfilesError) { - errorMessage = getErrorMessage(qualityProfilesError, 'Failed to load quality profiles from API'); + errorMessage = getErrorMessage(qualityProfilesError, translate('FailedToLoadQualityProfilesFromApi')); } else if (uiSettingsError) { - errorMessage = getErrorMessage(uiSettingsError, 'Failed to load UI settings from API'); + errorMessage = getErrorMessage(uiSettingsError, translate('FailedToLoadUiSettingsFromApi')); } else if (systemStatusError) { - errorMessage = getErrorMessage(uiSettingsError, 'Failed to load system status from API'); + errorMessage = getErrorMessage(uiSettingsError, translate('FailedToLoadSystemStatusFromApi')); } return ( @@ -43,7 +44,7 @@ function ErrorPage(props) {
- Version {version} + {translate('VersionNumber', { version })}
); diff --git a/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js index e1a0e19e7..328e65420 100644 --- a/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js +++ b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js @@ -6,6 +6,7 @@ import ModalBody from 'Components/Modal/ModalBody'; import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; +import translate from 'Utilities/String/translate'; import styles from './KeyboardShortcutsModalContent.css'; function getShortcuts() { @@ -47,7 +48,7 @@ function KeyboardShortcutsModalContent(props) { return ( - Keyboard Shortcuts + {translate('KeyboardShortcuts')} @@ -75,7 +76,7 @@ function KeyboardShortcutsModalContent(props) { diff --git a/frontend/src/Components/Page/Header/PageHeader.js b/frontend/src/Components/Page/Header/PageHeader.js index 46abcd013..23d7d7f99 100644 --- a/frontend/src/Components/Page/Header/PageHeader.js +++ b/frontend/src/Components/Page/Header/PageHeader.js @@ -4,6 +4,7 @@ import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts'; import IconButton from 'Components/Link/IconButton'; import Link from 'Components/Link/Link'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import KeyboardShortcutsModal from './KeyboardShortcutsModal'; import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector'; import SeriesSearchInputConnector from './SeriesSearchInputConnector'; @@ -77,7 +78,7 @@ class PageHeader extends Component { diff --git a/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js index 1df8e4b7a..cb5914aaf 100644 --- a/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js +++ b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js @@ -7,6 +7,7 @@ import MenuContent from 'Components/Menu/MenuContent'; import MenuItem from 'Components/Menu/MenuItem'; import MenuItemSeparator from 'Components/Menu/MenuItemSeparator'; import { align, icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './PageHeaderActionsMenu.css'; function PageHeaderActionsMenu(props) { @@ -32,7 +33,7 @@ function PageHeaderActionsMenu(props) { className={styles.itemIcon} name={icons.KEYBOARD} /> - Keyboard Shortcuts + {translate('KeyboardShortcuts')} @@ -42,7 +43,7 @@ function PageHeaderActionsMenu(props) { className={styles.itemIcon} name={icons.RESTART} /> - Restart + {translate('Restart')} @@ -51,7 +52,7 @@ function PageHeaderActionsMenu(props) { name={icons.SHUTDOWN} kind={kinds.DANGER} /> - Shutdown + {translate('Shutdown')} { @@ -69,7 +70,7 @@ function PageHeaderActionsMenu(props) { className={styles.itemIcon} name={icons.LOGOUT} /> - Logout + {translate('Logout')} } diff --git a/frontend/src/Components/Page/Header/SeriesSearchInput.js b/frontend/src/Components/Page/Header/SeriesSearchInput.js index abaa8f904..a763a3f05 100644 --- a/frontend/src/Components/Page/Header/SeriesSearchInput.js +++ b/frontend/src/Components/Page/Header/SeriesSearchInput.js @@ -6,6 +6,7 @@ import Icon from 'Components/Icon'; import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import FuseWorker from './fuse.worker'; import SeriesSearchResult from './SeriesSearchResult'; import styles from './SeriesSearchInput.css'; @@ -91,7 +92,7 @@ class SeriesSearchInput extends Component { if (item.type === ADD_NEW_TYPE) { return (
- Search for {query} + {translate('SearchForQuery', { query })}
); } @@ -271,14 +272,14 @@ class SeriesSearchInput extends Component { if (suggestions.length || loading) { suggestionGroups.push({ - title: 'Existing Series', + title: translate('ExistingSeries'), loading, suggestions }); } suggestionGroups.push({ - title: 'Add New Series', + title: translate('AddNewSeries'), suggestions: [ { type: ADD_NEW_TYPE, @@ -292,7 +293,7 @@ class SeriesSearchInput extends Component { className: styles.input, name: 'seriesSearch', value, - placeholder: 'Search', + placeholder: translate('Search'), autoComplete: 'off', spellCheck: false, onChange: this.onChange, diff --git a/frontend/src/Components/Page/PageContentError.js b/frontend/src/Components/Page/PageContentError.js index 9a76f2ee3..c645a6771 100644 --- a/frontend/src/Components/Page/PageContentError.js +++ b/frontend/src/Components/Page/PageContentError.js @@ -1,5 +1,6 @@ import React from 'react'; import ErrorBoundaryError from 'Components/Error/ErrorBoundaryError'; +import translate from 'Utilities/String/translate'; import PageContentBody from './PageContentBody'; import styles from './PageContentError.css'; @@ -9,7 +10,7 @@ function PageContentError(props) { diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarSection.js b/frontend/src/Components/Page/Toolbar/PageToolbarSection.js index 2d4aca718..2d50bab8b 100644 --- a/frontend/src/Components/Page/Toolbar/PageToolbarSection.js +++ b/frontend/src/Components/Page/Toolbar/PageToolbarSection.js @@ -8,6 +8,7 @@ import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; import { forEach } from 'Helpers/elementChildren'; import { align, icons } from 'Helpers/Props'; import dimensions from 'Styles/Variables/dimensions'; +import translate from 'Utilities/String/translate'; import PageToolbarOverflowMenuItem from './PageToolbarOverflowMenuItem'; import styles from './PageToolbarSection.css'; @@ -160,7 +161,7 @@ class PageToolbarSection extends Component { diff --git a/frontend/src/Components/ProgressBar.js b/frontend/src/Components/ProgressBar.js index 0cf04da46..171b4c0fa 100644 --- a/frontend/src/Components/ProgressBar.js +++ b/frontend/src/Components/ProgressBar.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ColorImpairedConsumer } from 'App/ColorImpairedContext'; import { kinds, sizes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './ProgressBar.css'; function ProgressBar(props) { @@ -57,7 +58,7 @@ function ProgressBar(props) { enableColorImpairedMode && 'colorImpaired' )} role="meter" - aria-label={`Progress Bar at ${progress.toFixed(0)}%`} + aria-label={translate('ProgressBarProgress', { progress: progress.toFixed(0) })} aria-valuenow={progress.toFixed(0)} aria-valuemin="0" aria-valuemax="100" diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsModal.js b/frontend/src/Components/Table/TableOptions/TableOptionsModal.js index 3272989c5..45caee110 100644 --- a/frontend/src/Components/Table/TableOptions/TableOptionsModal.js +++ b/frontend/src/Components/Table/TableOptions/TableOptionsModal.js @@ -15,6 +15,7 @@ import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import { inputTypes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import TableOptionsColumn from './TableOptionsColumn'; import TableOptionsColumnDragPreview from './TableOptionsColumnDragPreview'; import TableOptionsColumnDragSource from './TableOptionsColumnDragSource'; @@ -50,9 +51,9 @@ class TableOptionsModal extends Component { let pageSizeError = null; if (value < 5) { - pageSizeError = 'Page size must be at least 5'; + pageSizeError = translate('TablePageSizeMinimum', { minimumValue: '5' }); } else if (value > 250) { - pageSizeError = 'Page size must not exceed 250'; + pageSizeError = translate('TablePageSizeMaximum', { maximumValue: '250' }); } else { this.props.onTableOptionChange({ pageSize: value }); } @@ -136,7 +137,7 @@ class TableOptionsModal extends Component { isOpen ? - Table Options + {translate('TableOptions')} @@ -144,13 +145,13 @@ class TableOptionsModal extends Component { { hasPageSize ? - Page Size + {translate('PageSize')} @@ -168,11 +169,11 @@ class TableOptionsModal extends Component { { canModifyColumns ? - Columns + {translate('TableColumns')}
@@ -231,7 +232,7 @@ class TableOptionsModal extends Component { : diff --git a/frontend/src/Components/Table/TablePager.js b/frontend/src/Components/Table/TablePager.js index 6f71ee5d2..d58824169 100644 --- a/frontend/src/Components/Table/TablePager.js +++ b/frontend/src/Components/Table/TablePager.js @@ -6,6 +6,7 @@ import Icon from 'Components/Icon'; import Link from 'Components/Link/Link'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './TablePager.css'; class TablePager extends Component { @@ -156,7 +157,7 @@ class TablePager extends Component {
- Total records: {totalRecords} + {translate('TotalRecords', { totalRecords })}
diff --git a/frontend/src/Components/keyboardShortcuts.js b/frontend/src/Components/keyboardShortcuts.js index 912522d49..7ba54ac46 100644 --- a/frontend/src/Components/keyboardShortcuts.js +++ b/frontend/src/Components/keyboardShortcuts.js @@ -1,31 +1,42 @@ import Mousetrap from 'mousetrap'; import React, { Component } from 'react'; import getDisplayName from 'Helpers/getDisplayName'; +import translate from 'Utilities/String/translate'; export const shortcuts = { OPEN_KEYBOARD_SHORTCUTS_MODAL: { key: '?', - name: 'Open This Modal' + get name() { + return translate('KeyboardShortcutsOpenModal'); + } }, CLOSE_MODAL: { key: 'Esc', - name: 'Close Current Modal' + get name() { + return translate('KeyboardShortcutsCloseModal'); + } }, ACCEPT_CONFIRM_MODAL: { key: 'Enter', - name: 'Accept Confirmation Modal' + get name() { + return translate('KeyboardShortcutsConfirmModal'); + } }, SERIES_SEARCH_INPUT: { key: 's', - name: 'Focus Search Box' + get name() { + return translate('KeyboardShortcutsFocusSearchBox'); + } }, SAVE_SETTINGS: { key: 'mod+s', - name: 'Save Settings' + get name() { + return translate('KeyboardShortcutsSaveSettings'); + } } }; diff --git a/frontend/src/Episode/EpisodeDetailsModalContent.js b/frontend/src/Episode/EpisodeDetailsModalContent.js index 75a9e64ad..cd5f37fab 100644 --- a/frontend/src/Episode/EpisodeDetailsModalContent.js +++ b/frontend/src/Episode/EpisodeDetailsModalContent.js @@ -8,6 +8,7 @@ import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import MonitorToggleButton from 'Components/MonitorToggleButton'; import episodeEntities from 'Episode/episodeEntities'; +import translate from 'Utilities/String/translate'; import EpisodeHistoryConnector from './History/EpisodeHistoryConnector'; import EpisodeSearchConnector from './Search/EpisodeSearchConnector'; import SeasonEpisodeNumber from './SeasonEpisodeNumber'; @@ -117,21 +118,21 @@ class EpisodeDetailsModalContent extends Component { className={styles.tab} selectedClassName={styles.selectedTab} > - Details + {translate('Details')} - History + {translate('History')} - Search + {translate('Search')} @@ -173,14 +174,14 @@ class EpisodeDetailsModalContent extends Component { to={seriesLink} onPress={onModalClose} > - Open Series + {translate('OpenSeries')} } diff --git a/frontend/src/Episode/EpisodeLanguages.js b/frontend/src/Episode/EpisodeLanguages.js index 53e3854cc..66f278897 100644 --- a/frontend/src/Episode/EpisodeLanguages.js +++ b/frontend/src/Episode/EpisodeLanguages.js @@ -3,6 +3,7 @@ import React from 'react'; import Label from 'Components/Label'; import Popover from 'Components/Tooltip/Popover'; import { kinds, tooltipPositions } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; function EpisodeLanguages(props) { const { @@ -34,10 +35,10 @@ function EpisodeLanguages(props) { className={className} kind={isCutoffNotMet ? kinds.INVERSE : kinds.DEFAULT} > - Multi-Languages + {translate('MultiLanguages')} } - title={'Languages'} + title={translate('Languages')} body={
    { diff --git a/frontend/src/Episode/EpisodeNumber.js b/frontend/src/Episode/EpisodeNumber.js index 948f8710c..7f5c448f1 100644 --- a/frontend/src/Episode/EpisodeNumber.js +++ b/frontend/src/Episode/EpisodeNumber.js @@ -5,6 +5,7 @@ import Popover from 'Components/Tooltip/Popover'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import padNumber from 'Utilities/Number/padNumber'; import filterAlternateTitles from 'Utilities/Series/filterAlternateTitles'; +import translate from 'Utilities/String/translate'; import SceneInfo from './SceneInfo'; import styles from './EpisodeNumber.css'; @@ -12,11 +13,11 @@ function getWarningMessage(unverifiedSceneNumbering, seriesType, absoluteEpisode const messages = []; if (unverifiedSceneNumbering) { - messages.push('Scene number hasn\'t been verified yet'); + messages.push(translate('SceneNumberNotVerified')); } if (seriesType === 'anime' && !absoluteEpisodeNumber) { - messages.push('Episode does not have an absolute episode number'); + messages.push(translate('EpisodeMissingAbsoluteNumber')); } return messages.join('\n'); @@ -70,7 +71,7 @@ function EpisodeNumber(props) { } } - title="Scene Information" + title={translate('SceneInformation')} body={
); @@ -66,7 +67,7 @@ function EpisodeStatus(props) { quality={quality} size={episodeFile.size} isCutoffNotMet={isCutoffNotMet} - title="Episode Downloaded" + title={translate('EpisodeDownloaded')} /> ); @@ -77,7 +78,7 @@ function EpisodeStatus(props) {
); @@ -89,7 +90,7 @@ function EpisodeStatus(props) { ); @@ -100,7 +101,7 @@ function EpisodeStatus(props) {
); @@ -110,7 +111,7 @@ function EpisodeStatus(props) {
); diff --git a/frontend/src/Episode/History/EpisodeHistory.js b/frontend/src/Episode/History/EpisodeHistory.js index c5d2c907d..7a420de26 100644 --- a/frontend/src/Episode/History/EpisodeHistory.js +++ b/frontend/src/Episode/History/EpisodeHistory.js @@ -79,13 +79,13 @@ class EpisodeHistory extends Component { if (!isFetching && !!error) { return ( - Unable to load episode history. + {translate('EpisodeHistoryLoadError')} ); } if (isPopulated && !hasItems && !error) { return ( - No episode history. + {translate('NoEpisodeHistory')} ); } diff --git a/frontend/src/Episode/History/EpisodeHistoryRow.js b/frontend/src/Episode/History/EpisodeHistoryRow.js index 8d50e2e1e..9e46f4e58 100644 --- a/frontend/src/Episode/History/EpisodeHistoryRow.js +++ b/frontend/src/Episode/History/EpisodeHistoryRow.js @@ -15,6 +15,7 @@ import EpisodeLanguages from 'Episode/EpisodeLanguages'; import EpisodeQuality from 'Episode/EpisodeQuality'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore'; +import translate from 'Utilities/String/translate'; import styles from './EpisodeHistoryRow.css'; function getTitle(eventType) { @@ -137,7 +138,7 @@ class EpisodeHistoryRow extends Component { { eventType === 'grabbed' && @@ -147,9 +148,9 @@ class EpisodeHistoryRow extends Component { diff --git a/frontend/src/Episode/SceneInfo.js b/frontend/src/Episode/SceneInfo.js index 154cdce28..dc700c98e 100644 --- a/frontend/src/Episode/SceneInfo.js +++ b/frontend/src/Episode/SceneInfo.js @@ -4,6 +4,7 @@ import React from 'react'; import DescriptionList from 'Components/DescriptionList/DescriptionList'; import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; import padNumber from 'Utilities/Number/padNumber'; +import translate from 'Utilities/String/translate'; import styles from './SceneInfo.css'; function SceneInfo(props) { @@ -56,7 +57,7 @@ function SceneInfo(props) { } @@ -66,7 +67,7 @@ function SceneInfo(props) { } @@ -76,7 +77,7 @@ function SceneInfo(props) { } @@ -86,7 +87,7 @@ function SceneInfo(props) { { diff --git a/frontend/src/Episode/Search/EpisodeSearch.js b/frontend/src/Episode/Search/EpisodeSearch.js index cd8d85477..87451e63e 100644 --- a/frontend/src/Episode/Search/EpisodeSearch.js +++ b/frontend/src/Episode/Search/EpisodeSearch.js @@ -3,6 +3,7 @@ import React from 'react'; import Icon from 'Components/Icon'; import Button from 'Components/Link/Button'; import { icons, kinds, sizes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './EpisodeSearch.css'; function EpisodeSearch(props) { @@ -24,7 +25,7 @@ function EpisodeSearch(props) { name={icons.QUICK} /> - Quick Search + {translate('QuickSearch')} @@ -40,7 +41,7 @@ function EpisodeSearch(props) { name={icons.INTERACTIVE} /> - Interactive Search + {translate('InteractiveSearch')} diff --git a/frontend/src/Episode/Summary/EpisodeAiring.js b/frontend/src/Episode/Summary/EpisodeAiring.js index e79bc19c2..2b64561dd 100644 --- a/frontend/src/Episode/Summary/EpisodeAiring.js +++ b/frontend/src/Episode/Summary/EpisodeAiring.js @@ -7,6 +7,7 @@ import formatTime from 'Utilities/Date/formatTime'; import isInNextWeek from 'Utilities/Date/isInNextWeek'; import isToday from 'Utilities/Date/isToday'; import isTomorrow from 'Utilities/Date/isTomorrow'; +import translate from '../../Utilities/String/translate'; function EpisodeAiring(props) { const { @@ -26,10 +27,11 @@ function EpisodeAiring(props) { ); + // TODO: Update InlineMarkdown to accept tags and pass in networkLabel object, for now blank string passed into translation if (!airDateUtc) { return ( - TBA on {networkLabel} + {translate('AirsTbaOn', { networkLabel: '' })}networkLabel ); } @@ -39,7 +41,7 @@ function EpisodeAiring(props) { if (!showRelativeDates) { return ( - {moment(airDateUtc).format(shortDateFormat)} at {time} on {networkLabel} + {translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format(shortDateFormat), time, networkLabel: '' })}{networkLabel} ); } @@ -47,7 +49,7 @@ function EpisodeAiring(props) { if (isToday(airDateUtc)) { return ( - {time} on {networkLabel} + {translate('AirsTimeOn', { time, networkLabel: '' })}{networkLabel} ); } @@ -55,7 +57,7 @@ function EpisodeAiring(props) { if (isTomorrow(airDateUtc)) { return ( - Tomorrow at {time} on {networkLabel} + {translate('AirsTomorrowOn', { time, networkLabel: '' })}{networkLabel} ); } @@ -63,14 +65,14 @@ function EpisodeAiring(props) { if (isInNextWeek(airDateUtc)) { return ( - {moment(airDateUtc).format('dddd')} at {time} on {networkLabel} + {translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format('dddd'), time, networkLabel: '' })}{networkLabel} ); } return ( - {moment(airDateUtc).format(shortDateFormat)} at {time} on {networkLabel} + {translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format(shortDateFormat), time, networkLabel: '' })}{networkLabel} ); } diff --git a/frontend/src/Episode/Summary/EpisodeFileRow.js b/frontend/src/Episode/Summary/EpisodeFileRow.js index 0fb44dbad..f23b7c9ce 100644 --- a/frontend/src/Episode/Summary/EpisodeFileRow.js +++ b/frontend/src/Episode/Summary/EpisodeFileRow.js @@ -11,6 +11,7 @@ import EpisodeLanguages from 'Episode/EpisodeLanguages'; import EpisodeQuality from 'Episode/EpisodeQuality'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; import MediaInfo from './MediaInfo'; import styles from './EpisodeFileRow.css'; @@ -140,7 +141,7 @@ class EpisodeFileRow extends Component { name={icons.MEDIA_INFO} /> } - title="Media Info" + title={translate('MediaInfo')} body={} position={tooltipPositions.LEFT} /> : @@ -148,7 +149,7 @@ class EpisodeFileRow extends Component { } @@ -163,9 +164,9 @@ class EpisodeFileRow extends Component { diff --git a/frontend/src/Episode/Summary/EpisodeSummary.js b/frontend/src/Episode/Summary/EpisodeSummary.js index f87c884d9..0d454e90e 100644 --- a/frontend/src/Episode/Summary/EpisodeSummary.js +++ b/frontend/src/Episode/Summary/EpisodeSummary.js @@ -103,7 +103,7 @@ class EpisodeSummary extends Component { return (
- Airs + {translate('Airs')}
- Quality Profile + {translate('QualityProfile')}