Merge branch 'develop' into skip-redownload
This commit is contained in:
commit
d18b0554ef
|
@ -11,6 +11,7 @@ on:
|
||||||
- ".github/workflows/api_docs.yml"
|
- ".github/workflows/api_docs.yml"
|
||||||
- "docs.sh"
|
- "docs.sh"
|
||||||
- "src/Sonarr.Api.*/**"
|
- "src/Sonarr.Api.*/**"
|
||||||
|
- "src/Sonarr.Http/**"
|
||||||
- "src/**/*.csproj"
|
- "src/**/*.csproj"
|
||||||
- "src/*"
|
- "src/*"
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,8 @@ module.exports = (env) => {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: 'Content/styles.css'
|
filename: 'Content/styles.css',
|
||||||
|
chunkFilename: 'Content/[id]-[chunkhash].css'
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
|
|
|
@ -7,13 +7,13 @@ import PageConnector from 'Components/Page/PageConnector';
|
||||||
import ApplyTheme from './ApplyTheme';
|
import ApplyTheme from './ApplyTheme';
|
||||||
import AppRoutes from './AppRoutes';
|
import AppRoutes from './AppRoutes';
|
||||||
|
|
||||||
function App({ store, history, hasTranslationsError }) {
|
function App({ store, history }) {
|
||||||
return (
|
return (
|
||||||
<DocumentTitle title={window.Sonarr.instanceName}>
|
<DocumentTitle title={window.Sonarr.instanceName}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
<ApplyTheme>
|
<ApplyTheme>
|
||||||
<PageConnector hasTranslationsError={hasTranslationsError}>
|
<PageConnector>
|
||||||
<AppRoutes app={App} />
|
<AppRoutes app={App} />
|
||||||
</PageConnector>
|
</PageConnector>
|
||||||
</ApplyTheme>
|
</ApplyTheme>
|
||||||
|
@ -25,8 +25,7 @@ function App({ store, history, hasTranslationsError }) {
|
||||||
|
|
||||||
App.propTypes = {
|
App.propTypes = {
|
||||||
store: PropTypes.object.isRequired,
|
store: PropTypes.object.isRequired,
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired
|
||||||
hasTranslationsError: PropTypes.bool.isRequired
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Icon extends PureComponent {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={containerClassName}
|
className={containerClassName}
|
||||||
title={title}
|
title={typeof title === 'function' ? title() : title}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</span>
|
</span>
|
||||||
|
@ -60,7 +60,7 @@ Icon.propTypes = {
|
||||||
name: PropTypes.object.isRequired,
|
name: PropTypes.object.isRequired,
|
||||||
kind: PropTypes.string.isRequired,
|
kind: PropTypes.string.isRequired,
|
||||||
size: PropTypes.number.isRequired,
|
size: PropTypes.number.isRequired,
|
||||||
title: PropTypes.string,
|
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
darken: PropTypes.bool.isRequired,
|
darken: PropTypes.bool.isRequired,
|
||||||
isSpinning: PropTypes.bool.isRequired,
|
isSpinning: PropTypes.bool.isRequired,
|
||||||
fixedWidth: PropTypes.bool.isRequired
|
fixedWidth: PropTypes.bool.isRequired
|
||||||
|
|
|
@ -7,7 +7,7 @@ function ErrorPage(props) {
|
||||||
const {
|
const {
|
||||||
version,
|
version,
|
||||||
isLocalStorageSupported,
|
isLocalStorageSupported,
|
||||||
hasTranslationsError,
|
translationsError,
|
||||||
seriesError,
|
seriesError,
|
||||||
customFiltersError,
|
customFiltersError,
|
||||||
tagsError,
|
tagsError,
|
||||||
|
@ -20,8 +20,8 @@ function ErrorPage(props) {
|
||||||
|
|
||||||
if (!isLocalStorageSupported) {
|
if (!isLocalStorageSupported) {
|
||||||
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
||||||
} else if (hasTranslationsError) {
|
} else if (translationsError) {
|
||||||
errorMessage = 'Failed to load translations from API';
|
errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API');
|
||||||
} else if (seriesError) {
|
} else if (seriesError) {
|
||||||
errorMessage = getErrorMessage(seriesError, 'Failed to load series from API');
|
errorMessage = getErrorMessage(seriesError, 'Failed to load series from API');
|
||||||
} else if (customFiltersError) {
|
} else if (customFiltersError) {
|
||||||
|
@ -52,7 +52,7 @@ function ErrorPage(props) {
|
||||||
ErrorPage.propTypes = {
|
ErrorPage.propTypes = {
|
||||||
version: PropTypes.string.isRequired,
|
version: PropTypes.string.isRequired,
|
||||||
isLocalStorageSupported: PropTypes.bool.isRequired,
|
isLocalStorageSupported: PropTypes.bool.isRequired,
|
||||||
hasTranslationsError: PropTypes.bool.isRequired,
|
translationsError: PropTypes.object,
|
||||||
seriesError: PropTypes.object,
|
seriesError: PropTypes.object,
|
||||||
customFiltersError: PropTypes.object,
|
customFiltersError: PropTypes.object,
|
||||||
tagsError: PropTypes.object,
|
tagsError: PropTypes.object,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
import { fetchTranslations, saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
||||||
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
||||||
import { fetchSeries } from 'Store/Actions/seriesActions';
|
import { fetchSeries } from 'Store/Actions/seriesActions';
|
||||||
import { fetchImportLists, fetchLanguages, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
|
import { fetchImportLists, fetchLanguages, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
|
||||||
|
@ -52,6 +52,7 @@ const selectIsPopulated = createSelector(
|
||||||
(state) => state.settings.languages.isPopulated,
|
(state) => state.settings.languages.isPopulated,
|
||||||
(state) => state.settings.importLists.isPopulated,
|
(state) => state.settings.importLists.isPopulated,
|
||||||
(state) => state.system.status.isPopulated,
|
(state) => state.system.status.isPopulated,
|
||||||
|
(state) => state.app.translations.isPopulated,
|
||||||
(
|
(
|
||||||
seriesIsPopulated,
|
seriesIsPopulated,
|
||||||
customFiltersIsPopulated,
|
customFiltersIsPopulated,
|
||||||
|
@ -60,7 +61,8 @@ const selectIsPopulated = createSelector(
|
||||||
qualityProfilesIsPopulated,
|
qualityProfilesIsPopulated,
|
||||||
languagesIsPopulated,
|
languagesIsPopulated,
|
||||||
importListsIsPopulated,
|
importListsIsPopulated,
|
||||||
systemStatusIsPopulated
|
systemStatusIsPopulated,
|
||||||
|
translationsIsPopulated
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
seriesIsPopulated &&
|
seriesIsPopulated &&
|
||||||
|
@ -70,7 +72,8 @@ const selectIsPopulated = createSelector(
|
||||||
qualityProfilesIsPopulated &&
|
qualityProfilesIsPopulated &&
|
||||||
languagesIsPopulated &&
|
languagesIsPopulated &&
|
||||||
importListsIsPopulated &&
|
importListsIsPopulated &&
|
||||||
systemStatusIsPopulated
|
systemStatusIsPopulated &&
|
||||||
|
translationsIsPopulated
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -84,6 +87,7 @@ const selectErrors = createSelector(
|
||||||
(state) => state.settings.languages.error,
|
(state) => state.settings.languages.error,
|
||||||
(state) => state.settings.importLists.error,
|
(state) => state.settings.importLists.error,
|
||||||
(state) => state.system.status.error,
|
(state) => state.system.status.error,
|
||||||
|
(state) => state.app.translations.error,
|
||||||
(
|
(
|
||||||
seriesError,
|
seriesError,
|
||||||
customFiltersError,
|
customFiltersError,
|
||||||
|
@ -92,7 +96,8 @@ const selectErrors = createSelector(
|
||||||
qualityProfilesError,
|
qualityProfilesError,
|
||||||
languagesError,
|
languagesError,
|
||||||
importListsError,
|
importListsError,
|
||||||
systemStatusError
|
systemStatusError,
|
||||||
|
translationsError
|
||||||
) => {
|
) => {
|
||||||
const hasError = !!(
|
const hasError = !!(
|
||||||
seriesError ||
|
seriesError ||
|
||||||
|
@ -102,7 +107,8 @@ const selectErrors = createSelector(
|
||||||
qualityProfilesError ||
|
qualityProfilesError ||
|
||||||
languagesError ||
|
languagesError ||
|
||||||
importListsError ||
|
importListsError ||
|
||||||
systemStatusError
|
systemStatusError ||
|
||||||
|
translationsError
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -114,7 +120,8 @@ const selectErrors = createSelector(
|
||||||
qualityProfilesError,
|
qualityProfilesError,
|
||||||
languagesError,
|
languagesError,
|
||||||
importListsError,
|
importListsError,
|
||||||
systemStatusError
|
systemStatusError,
|
||||||
|
translationsError
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -173,6 +180,9 @@ function createMapDispatchToProps(dispatch, props) {
|
||||||
dispatchFetchStatus() {
|
dispatchFetchStatus() {
|
||||||
dispatch(fetchStatus());
|
dispatch(fetchStatus());
|
||||||
},
|
},
|
||||||
|
dispatchFetchTranslations() {
|
||||||
|
dispatch(fetchTranslations());
|
||||||
|
},
|
||||||
onResize(dimensions) {
|
onResize(dimensions) {
|
||||||
dispatch(saveDimensions(dimensions));
|
dispatch(saveDimensions(dimensions));
|
||||||
},
|
},
|
||||||
|
@ -205,6 +215,7 @@ class PageConnector extends Component {
|
||||||
this.props.dispatchFetchImportLists();
|
this.props.dispatchFetchImportLists();
|
||||||
this.props.dispatchFetchUISettings();
|
this.props.dispatchFetchUISettings();
|
||||||
this.props.dispatchFetchStatus();
|
this.props.dispatchFetchStatus();
|
||||||
|
this.props.dispatchFetchTranslations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +231,6 @@ class PageConnector extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
hasTranslationsError,
|
|
||||||
isPopulated,
|
isPopulated,
|
||||||
hasError,
|
hasError,
|
||||||
dispatchFetchSeries,
|
dispatchFetchSeries,
|
||||||
|
@ -230,15 +240,15 @@ class PageConnector extends Component {
|
||||||
dispatchFetchImportLists,
|
dispatchFetchImportLists,
|
||||||
dispatchFetchUISettings,
|
dispatchFetchUISettings,
|
||||||
dispatchFetchStatus,
|
dispatchFetchStatus,
|
||||||
|
dispatchFetchTranslations,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (hasTranslationsError || hasError || !this.state.isLocalStorageSupported) {
|
if (hasError || !this.state.isLocalStorageSupported) {
|
||||||
return (
|
return (
|
||||||
<ErrorPage
|
<ErrorPage
|
||||||
{...this.state}
|
{...this.state}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
hasTranslationsError={hasTranslationsError}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -259,7 +269,6 @@ class PageConnector extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
PageConnector.propTypes = {
|
PageConnector.propTypes = {
|
||||||
hasTranslationsError: PropTypes.bool.isRequired,
|
|
||||||
isPopulated: PropTypes.bool.isRequired,
|
isPopulated: PropTypes.bool.isRequired,
|
||||||
hasError: PropTypes.bool.isRequired,
|
hasError: PropTypes.bool.isRequired,
|
||||||
isSidebarVisible: PropTypes.bool.isRequired,
|
isSidebarVisible: PropTypes.bool.isRequired,
|
||||||
|
@ -271,6 +280,7 @@ PageConnector.propTypes = {
|
||||||
dispatchFetchImportLists: PropTypes.func.isRequired,
|
dispatchFetchImportLists: PropTypes.func.isRequired,
|
||||||
dispatchFetchUISettings: PropTypes.func.isRequired,
|
dispatchFetchUISettings: PropTypes.func.isRequired,
|
||||||
dispatchFetchStatus: PropTypes.func.isRequired,
|
dispatchFetchStatus: PropTypes.func.isRequired,
|
||||||
|
dispatchFetchTranslations: PropTypes.func.isRequired,
|
||||||
onSidebarVisibleChange: PropTypes.func.isRequired
|
onSidebarVisibleChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,22 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth);
|
||||||
const links = [
|
const links = [
|
||||||
{
|
{
|
||||||
iconName: icons.SERIES_CONTINUING,
|
iconName: icons.SERIES_CONTINUING,
|
||||||
title: translate('Series'),
|
get title() {
|
||||||
|
return translate('Series');
|
||||||
|
},
|
||||||
to: '/',
|
to: '/',
|
||||||
alias: '/series',
|
alias: '/series',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('AddNew'),
|
get title() {
|
||||||
|
return translate('AddNew');
|
||||||
|
},
|
||||||
to: '/add/new'
|
to: '/add/new'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('LibraryImport'),
|
get title() {
|
||||||
|
return translate('LibraryImport');
|
||||||
|
},
|
||||||
to: '/add/import'
|
to: '/add/import'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -38,26 +44,36 @@ const links = [
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.CALENDAR,
|
iconName: icons.CALENDAR,
|
||||||
title: translate('Calendar'),
|
get title() {
|
||||||
|
return translate('Calendar');
|
||||||
|
},
|
||||||
to: '/calendar'
|
to: '/calendar'
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.ACTIVITY,
|
iconName: icons.ACTIVITY,
|
||||||
title: translate('Activity'),
|
get title() {
|
||||||
|
return translate('Activity');
|
||||||
|
},
|
||||||
to: '/activity/queue',
|
to: '/activity/queue',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('Queue'),
|
get title() {
|
||||||
|
return translate('Queue');
|
||||||
|
},
|
||||||
to: '/activity/queue',
|
to: '/activity/queue',
|
||||||
statusComponent: QueueStatusConnector
|
statusComponent: QueueStatusConnector
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('History'),
|
get title() {
|
||||||
|
return translate('History');
|
||||||
|
},
|
||||||
to: '/activity/history'
|
to: '/activity/history'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Blocklist'),
|
get title() {
|
||||||
|
return translate('Blocklist');
|
||||||
|
},
|
||||||
to: '/activity/blocklist'
|
to: '/activity/blocklist'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -65,15 +81,21 @@ const links = [
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.WARNING,
|
iconName: icons.WARNING,
|
||||||
title: translate('Wanted'),
|
get title() {
|
||||||
|
return translate('Wanted');
|
||||||
|
},
|
||||||
to: '/wanted/missing',
|
to: '/wanted/missing',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('Missing'),
|
get title() {
|
||||||
|
return translate('Missing');
|
||||||
|
},
|
||||||
to: '/wanted/missing'
|
to: '/wanted/missing'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('CutoffUnmet'),
|
get title() {
|
||||||
|
return translate('CutoffUnmet');
|
||||||
|
},
|
||||||
to: '/wanted/cutoffunmet'
|
to: '/wanted/cutoffunmet'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -81,59 +103,87 @@ const links = [
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.SETTINGS,
|
iconName: icons.SETTINGS,
|
||||||
title: translate('Settings'),
|
get title() {
|
||||||
|
return translate('Settings');
|
||||||
|
},
|
||||||
to: '/settings',
|
to: '/settings',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('MediaManagement'),
|
get title() {
|
||||||
|
return translate('MediaManagement');
|
||||||
|
},
|
||||||
to: '/settings/mediamanagement'
|
to: '/settings/mediamanagement'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Profiles'),
|
get title() {
|
||||||
|
return translate('Profiles');
|
||||||
|
},
|
||||||
to: '/settings/profiles'
|
to: '/settings/profiles'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Quality'),
|
get title() {
|
||||||
|
return translate('Quality');
|
||||||
|
},
|
||||||
to: '/settings/quality'
|
to: '/settings/quality'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('CustomFormats'),
|
get title() {
|
||||||
|
return translate('CustomFormats');
|
||||||
|
},
|
||||||
to: '/settings/customformats'
|
to: '/settings/customformats'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Indexers'),
|
get title() {
|
||||||
|
return translate('Indexers');
|
||||||
|
},
|
||||||
to: '/settings/indexers'
|
to: '/settings/indexers'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('DownloadClients'),
|
get title() {
|
||||||
|
return translate('DownloadClients');
|
||||||
|
},
|
||||||
to: '/settings/downloadclients'
|
to: '/settings/downloadclients'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('ImportLists'),
|
get title() {
|
||||||
|
return translate('ImportLists');
|
||||||
|
},
|
||||||
to: '/settings/importlists'
|
to: '/settings/importlists'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Connect'),
|
get title() {
|
||||||
|
return translate('Connect');
|
||||||
|
},
|
||||||
to: '/settings/connect'
|
to: '/settings/connect'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Metadata'),
|
get title() {
|
||||||
|
return translate('Metadata');
|
||||||
|
},
|
||||||
to: '/settings/metadata'
|
to: '/settings/metadata'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('MetadataSource'),
|
get title() {
|
||||||
|
return translate('MetadataSource');
|
||||||
|
},
|
||||||
to: '/settings/metadatasource'
|
to: '/settings/metadatasource'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Tags'),
|
get title() {
|
||||||
|
return translate('Tags');
|
||||||
|
},
|
||||||
to: '/settings/tags'
|
to: '/settings/tags'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('General'),
|
get title() {
|
||||||
|
return translate('General');
|
||||||
|
},
|
||||||
to: '/settings/general'
|
to: '/settings/general'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('UI'),
|
get title() {
|
||||||
|
return translate('UI');
|
||||||
|
},
|
||||||
to: '/settings/ui'
|
to: '/settings/ui'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -141,32 +191,46 @@ const links = [
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.SYSTEM,
|
iconName: icons.SYSTEM,
|
||||||
title: translate('System'),
|
get title() {
|
||||||
|
return translate('System');
|
||||||
|
},
|
||||||
to: '/system/status',
|
to: '/system/status',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('Status'),
|
get title() {
|
||||||
|
return translate('Status');
|
||||||
|
},
|
||||||
to: '/system/status',
|
to: '/system/status',
|
||||||
statusComponent: HealthStatusConnector
|
statusComponent: HealthStatusConnector
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Tasks'),
|
get title() {
|
||||||
|
return translate('Tasks');
|
||||||
|
},
|
||||||
to: '/system/tasks'
|
to: '/system/tasks'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Backup'),
|
get title() {
|
||||||
|
return translate('Backup');
|
||||||
|
},
|
||||||
to: '/system/backup'
|
to: '/system/backup'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Updates'),
|
get title() {
|
||||||
|
return translate('Updates');
|
||||||
|
},
|
||||||
to: '/system/updates'
|
to: '/system/updates'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Events'),
|
get title() {
|
||||||
|
return translate('Events');
|
||||||
|
},
|
||||||
to: '/system/events'
|
to: '/system/events'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('LogFiles'),
|
get title() {
|
||||||
|
return translate('LogFiles');
|
||||||
|
},
|
||||||
to: '/system/logs/files'
|
to: '/system/logs/files'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,9 +27,25 @@ interface ManageDownloadClientsEditModalContentProps {
|
||||||
const NO_CHANGE = 'noChange';
|
const NO_CHANGE = 'noChange';
|
||||||
|
|
||||||
const enableOptions = [
|
const enableOptions = [
|
||||||
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
|
{
|
||||||
{ key: 'enabled', value: translate('Enabled') },
|
key: NO_CHANGE,
|
||||||
{ key: 'disabled', value: translate('Disabled') },
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'enabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Enabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'disabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Disabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function ManageDownloadClientsEditModalContent(
|
function ManageDownloadClientsEditModalContent(
|
||||||
|
|
|
@ -36,37 +36,49 @@ type OnSelectedChangeCallback = React.ComponentProps<
|
||||||
const COLUMNS = [
|
const COLUMNS = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: translate('Name'),
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'implementation',
|
name: 'implementation',
|
||||||
label: translate('Implementation'),
|
get label() {
|
||||||
|
return translate('Implementation');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enable',
|
name: 'enable',
|
||||||
label: translate('Enabled'),
|
get label() {
|
||||||
|
return translate('Enabled');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'priority',
|
name: 'priority',
|
||||||
label: translate('Priority'),
|
get label() {
|
||||||
|
return translate('Priority');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'removeCompletedDownloads',
|
name: 'removeCompletedDownloads',
|
||||||
label: translate('RemoveCompleted'),
|
get label() {
|
||||||
|
return translate('RemoveCompleted');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'removeFailedDownloads',
|
name: 'removeFailedDownloads',
|
||||||
label: translate('RemoveFailed'),
|
get label() {
|
||||||
|
return translate('RemoveFailed');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,9 +72,24 @@ function TagsModalContent(props: TagsModalContentProps) {
|
||||||
}, [tags, applyTags, onApplyTagsPress]);
|
}, [tags, applyTags, onApplyTagsPress]);
|
||||||
|
|
||||||
const applyTagsOptions = [
|
const applyTagsOptions = [
|
||||||
{ key: 'add', value: translate('Add') },
|
{
|
||||||
{ key: 'remove', value: translate('Remove') },
|
key: 'add',
|
||||||
{ key: 'replace', value: translate('Replace') },
|
get value() {
|
||||||
|
return translate('Add');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove',
|
||||||
|
get value() {
|
||||||
|
return translate('Remove');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'replace',
|
||||||
|
get value() {
|
||||||
|
return translate('Replace');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -26,9 +26,25 @@ interface ManageImportListsEditModalContentProps {
|
||||||
const NO_CHANGE = 'noChange';
|
const NO_CHANGE = 'noChange';
|
||||||
|
|
||||||
const autoAddOptions = [
|
const autoAddOptions = [
|
||||||
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
|
{
|
||||||
{ key: 'enabled', value: translate('Enabled') },
|
key: NO_CHANGE,
|
||||||
{ key: 'disabled', value: translate('Disabled') },
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'enabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Enabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'disabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Disabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function ManageImportListsEditModalContent(
|
function ManageImportListsEditModalContent(
|
||||||
|
|
|
@ -36,37 +36,49 @@ type OnSelectedChangeCallback = React.ComponentProps<
|
||||||
const COLUMNS = [
|
const COLUMNS = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: translate('Name'),
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'implementation',
|
name: 'implementation',
|
||||||
label: translate('Implementation'),
|
get label() {
|
||||||
|
return translate('Implementation');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'qualityProfileId',
|
name: 'qualityProfileId',
|
||||||
label: translate('QualityProfile'),
|
get label() {
|
||||||
|
return translate('QualityProfile');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'rootFolderPath',
|
name: 'rootFolderPath',
|
||||||
label: translate('RootFolder'),
|
get label() {
|
||||||
|
return translate('RootFolder');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enableAutomaticAdd',
|
name: 'enableAutomaticAdd',
|
||||||
label: translate('AutoAdd'),
|
get label() {
|
||||||
|
return translate('AutoAdd');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
label: translate('Tags'),
|
get label() {
|
||||||
|
return translate('Tags');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -70,9 +70,24 @@ function TagsModalContent(props: TagsModalContentProps) {
|
||||||
}, [tags, applyTags, onApplyTagsPress]);
|
}, [tags, applyTags, onApplyTagsPress]);
|
||||||
|
|
||||||
const applyTagsOptions = [
|
const applyTagsOptions = [
|
||||||
{ key: 'add', value: translate('Add') },
|
{
|
||||||
{ key: 'remove', value: translate('Remove') },
|
key: 'add',
|
||||||
{ key: 'replace', value: translate('Replace') },
|
get value() {
|
||||||
|
return translate('Add');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove',
|
||||||
|
get value() {
|
||||||
|
return translate('Remove');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'replace',
|
||||||
|
get value() {
|
||||||
|
return translate('Replace');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -27,9 +27,25 @@ interface ManageIndexersEditModalContentProps {
|
||||||
const NO_CHANGE = 'noChange';
|
const NO_CHANGE = 'noChange';
|
||||||
|
|
||||||
const enableOptions = [
|
const enableOptions = [
|
||||||
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
|
{
|
||||||
{ key: 'enabled', value: translate('Enabled') },
|
key: NO_CHANGE,
|
||||||
{ key: 'disabled', value: translate('Disabled') },
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'enabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Enabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'disabled',
|
||||||
|
get value() {
|
||||||
|
return translate('Disabled');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function ManageIndexersEditModalContent(
|
function ManageIndexersEditModalContent(
|
||||||
|
|
|
@ -36,43 +36,57 @@ type OnSelectedChangeCallback = React.ComponentProps<
|
||||||
const COLUMNS = [
|
const COLUMNS = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: translate('Name'),
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'implementation',
|
name: 'implementation',
|
||||||
label: translate('Implementation'),
|
get label() {
|
||||||
|
return translate('Implementation');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enableRss',
|
name: 'enableRss',
|
||||||
label: translate('EnableRSS'),
|
get label() {
|
||||||
|
return translate('EnableRSS');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enableAutomaticSearch',
|
name: 'enableAutomaticSearch',
|
||||||
label: translate('EnableAutomaticSearch'),
|
get label() {
|
||||||
|
return translate('EnableAutomaticSearch');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'enableInteractiveSearch',
|
name: 'enableInteractiveSearch',
|
||||||
label: translate('EnableInteractiveSearch'),
|
get label() {
|
||||||
|
return translate('EnableInteractiveSearch');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'priority',
|
name: 'priority',
|
||||||
label: translate('Priority'),
|
get label() {
|
||||||
|
return translate('Priority');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
label: translate('Tags'),
|
get label() {
|
||||||
|
return translate('Tags');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -70,9 +70,24 @@ function TagsModalContent(props: TagsModalContentProps) {
|
||||||
}, [tags, applyTags, onApplyTagsPress]);
|
}, [tags, applyTags, onApplyTagsPress]);
|
||||||
|
|
||||||
const applyTagsOptions = [
|
const applyTagsOptions = [
|
||||||
{ key: 'add', value: translate('Add') },
|
{
|
||||||
{ key: 'remove', value: translate('Remove') },
|
key: 'add',
|
||||||
{ key: 'replace', value: translate('Replace') },
|
get value() {
|
||||||
|
return translate('Add');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'remove',
|
||||||
|
get value() {
|
||||||
|
return translate('Remove');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'replace',
|
||||||
|
get value() {
|
||||||
|
return translate('Replace');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
import getSectionState from 'Utilities/State/getSectionState';
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
import { fetchTranslations as fetchAppTranslations } from 'Utilities/String/translate';
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
|
||||||
function getDimensions(width, height) {
|
function getDimensions(width, height) {
|
||||||
|
@ -41,7 +42,12 @@ export const defaultState = {
|
||||||
isReconnecting: false,
|
isReconnecting: false,
|
||||||
isDisconnected: false,
|
isDisconnected: false,
|
||||||
isRestarting: false,
|
isRestarting: false,
|
||||||
isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen
|
isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen,
|
||||||
|
translations: {
|
||||||
|
isFetching: true,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -53,6 +59,7 @@ export const SAVE_DIMENSIONS = 'app/saveDimensions';
|
||||||
export const SET_VERSION = 'app/setVersion';
|
export const SET_VERSION = 'app/setVersion';
|
||||||
export const SET_APP_VALUE = 'app/setAppValue';
|
export const SET_APP_VALUE = 'app/setAppValue';
|
||||||
export const SET_IS_SIDEBAR_VISIBLE = 'app/setIsSidebarVisible';
|
export const SET_IS_SIDEBAR_VISIBLE = 'app/setIsSidebarVisible';
|
||||||
|
export const FETCH_TRANSLATIONS = 'app/fetchTranslations';
|
||||||
|
|
||||||
export const PING_SERVER = 'app/pingServer';
|
export const PING_SERVER = 'app/pingServer';
|
||||||
|
|
||||||
|
@ -66,6 +73,7 @@ export const setAppValue = createAction(SET_APP_VALUE);
|
||||||
export const showMessage = createAction(SHOW_MESSAGE);
|
export const showMessage = createAction(SHOW_MESSAGE);
|
||||||
export const hideMessage = createAction(HIDE_MESSAGE);
|
export const hideMessage = createAction(HIDE_MESSAGE);
|
||||||
export const pingServer = createThunk(PING_SERVER);
|
export const pingServer = createThunk(PING_SERVER);
|
||||||
|
export const fetchTranslations = createThunk(FETCH_TRANSLATIONS);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helpers
|
// Helpers
|
||||||
|
@ -127,6 +135,17 @@ function pingServerAfterTimeout(getState, dispatch) {
|
||||||
export const actionHandlers = handleThunks({
|
export const actionHandlers = handleThunks({
|
||||||
[PING_SERVER]: function(getState, payload, dispatch) {
|
[PING_SERVER]: function(getState, payload, dispatch) {
|
||||||
pingServerAfterTimeout(getState, dispatch);
|
pingServerAfterTimeout(getState, dispatch);
|
||||||
|
},
|
||||||
|
[FETCH_TRANSLATIONS]: async function(getState, payload, dispatch) {
|
||||||
|
const isFetchingComplete = await fetchAppTranslations();
|
||||||
|
|
||||||
|
dispatch(setAppValue({
|
||||||
|
translations: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: isFetchingComplete,
|
||||||
|
error: isFetchingComplete ? null : 'Failed to load translations from API'
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -114,10 +114,13 @@ export const defaultState = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'customFormatScore',
|
name: 'customFormatScore',
|
||||||
columnLabel: translate('CustomFormatScore'),
|
get columnLabel() {
|
||||||
|
return translate('CustomFormatScore');
|
||||||
|
},
|
||||||
label: React.createElement(Icon, {
|
label: React.createElement(Icon, {
|
||||||
name: icons.SCORE,
|
name: icons.SCORE,
|
||||||
title: translate('CustomFormatScore')
|
title: () => translate('CustomFormatScore')
|
||||||
|
|
||||||
}),
|
}),
|
||||||
isVisible: false
|
isVisible: false
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,10 +36,17 @@ function mergeColumns(path, initialState, persistedState, computedState) {
|
||||||
const column = initialColumns.find((i) => i.name === persistedColumn.name);
|
const column = initialColumns.find((i) => i.name === persistedColumn.name);
|
||||||
|
|
||||||
if (column) {
|
if (column) {
|
||||||
columns.push({
|
const newColumn = {};
|
||||||
...column,
|
|
||||||
isVisible: persistedColumn.isVisible
|
// We can't use a spread operator or Object.assign to clone the column
|
||||||
});
|
// or any accessors are lost and can break translations.
|
||||||
|
for (const prop of Object.keys(column)) {
|
||||||
|
Object.defineProperty(newColumn, prop, Object.getOwnPropertyDescriptor(column, prop));
|
||||||
|
}
|
||||||
|
|
||||||
|
newColumn.isVisible = persistedColumn.isVisible;
|
||||||
|
|
||||||
|
columns.push(newColumn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import RestoreBackupModalConnector from './RestoreBackupModalConnector';
|
import RestoreBackupModalConnector from './RestoreBackupModalConnector';
|
||||||
import styles from './BackupRow.css';
|
import styles from './BackupRow.css';
|
||||||
|
|
||||||
|
@ -75,14 +76,14 @@ class BackupRow extends Component {
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
let iconClassName = icons.SCHEDULED;
|
let iconClassName = icons.SCHEDULED;
|
||||||
let iconTooltip = 'Scheduled';
|
let iconTooltip = translate('Scheduled');
|
||||||
|
|
||||||
if (type === 'manual') {
|
if (type === 'manual') {
|
||||||
iconClassName = icons.INTERACTIVE;
|
iconClassName = icons.INTERACTIVE;
|
||||||
iconTooltip = 'Manual';
|
iconTooltip = translate('Manual');
|
||||||
} else if (type === 'update') {
|
} else if (type === 'update') {
|
||||||
iconClassName = icons.UPDATE;
|
iconClassName = icons.UPDATE;
|
||||||
iconTooltip = 'Before update';
|
iconTooltip = translate('BeforeUpdate');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -115,12 +116,13 @@ class BackupRow extends Component {
|
||||||
|
|
||||||
<TableRowCell className={styles.actions}>
|
<TableRowCell className={styles.actions}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
title={translate('RestoreBackup')}
|
||||||
name={icons.RESTORE}
|
name={icons.RESTORE}
|
||||||
onPress={this.onRestorePress}
|
onPress={this.onRestorePress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
title="Delete backup"
|
title={translate('DeleteBackup')}
|
||||||
name={icons.DELETE}
|
name={icons.DELETE}
|
||||||
onPress={this.onDeletePress}
|
onPress={this.onDeletePress}
|
||||||
/>
|
/>
|
||||||
|
@ -136,9 +138,11 @@ class BackupRow extends Component {
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={isConfirmDeleteModalOpen}
|
isOpen={isConfirmDeleteModalOpen}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
title="Delete Backup"
|
title={translate('DeleteBackup')}
|
||||||
message={`Are you sure you want to delete the backup '${name}'?`}
|
message={translate('DeleteBackupMessageText', {
|
||||||
confirmLabel="Delete"
|
name
|
||||||
|
})}
|
||||||
|
confirmLabel={translate('Delete')}
|
||||||
onConfirm={this.onConfirmDeletePress}
|
onConfirm={this.onConfirmDeletePress}
|
||||||
onCancel={this.onConfirmDeleteModalClose}
|
onCancel={this.onConfirmDeleteModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import BackupRow from './BackupRow';
|
import BackupRow from './BackupRow';
|
||||||
import RestoreBackupModalConnector from './RestoreBackupModalConnector';
|
import RestoreBackupModalConnector from './RestoreBackupModalConnector';
|
||||||
|
|
||||||
|
@ -20,17 +21,23 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
label: 'Size',
|
get label() {
|
||||||
|
return translate('Size');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'time',
|
name: 'time',
|
||||||
label: 'Time',
|
get label() {
|
||||||
|
return translate('Time');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -81,18 +88,18 @@ class Backups extends Component {
|
||||||
const noBackups = isPopulated && !items.length;
|
const noBackups = isPopulated && !items.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Backups">
|
<PageContent title={translate('Backups')}>
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
<PageToolbarSection>
|
<PageToolbarSection>
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Backup Now"
|
label={translate('BackupNow')}
|
||||||
iconName={icons.BACKUP}
|
iconName={icons.BACKUP}
|
||||||
isSpinning={backupExecuting}
|
isSpinning={backupExecuting}
|
||||||
onPress={onBackupPress}
|
onPress={onBackupPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Restore Backup"
|
label={translate('RestoreBackup')}
|
||||||
iconName={icons.RESTORE}
|
iconName={icons.RESTORE}
|
||||||
onPress={this.onRestorePress}
|
onPress={this.onRestorePress}
|
||||||
/>
|
/>
|
||||||
|
@ -108,14 +115,14 @@ class Backups extends Component {
|
||||||
{
|
{
|
||||||
!isFetching && !!error &&
|
!isFetching && !!error &&
|
||||||
<Alert kind={kinds.DANGER}>
|
<Alert kind={kinds.DANGER}>
|
||||||
Unable to load backups
|
{translate('UnableToLoadBackups')}
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
noBackups &&
|
noBackups &&
|
||||||
<Alert kind={kinds.INFO}>
|
<Alert kind={kinds.INFO}>
|
||||||
No backups are available
|
{translate('NoBackupsAreAvailable')}
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,12 @@ 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 { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './RestoreBackupModalContent.css';
|
import styles from './RestoreBackupModalContent.css';
|
||||||
|
|
||||||
function getErrorMessage(error) {
|
function getErrorMessage(error) {
|
||||||
if (!error || !error.responseJSON || !error.responseJSON.message) {
|
if (!error || !error.responseJSON || !error.responseJSON.message) {
|
||||||
return 'Error restoring backup';
|
return translate('ErrorRestoringBackup');
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.responseJSON.message;
|
return error.responseJSON.message;
|
||||||
|
@ -145,7 +146,9 @@ class RestoreBackupModalContent extends Component {
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
{
|
{
|
||||||
!!id && `Would you like to restore the backup '${name}'?`
|
!!id && translate('WouldYouLikeToRestoreBackup', {
|
||||||
|
name
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -167,7 +170,9 @@ class RestoreBackupModalContent extends Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>Restore</div>
|
<div>
|
||||||
|
{translate('Restore')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.step}>
|
<div className={styles.step}>
|
||||||
|
@ -178,7 +183,9 @@ class RestoreBackupModalContent extends Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>Restart</div>
|
<div>
|
||||||
|
{translate('Restart')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.step}>
|
<div className={styles.step}>
|
||||||
|
@ -189,18 +196,20 @@ class RestoreBackupModalContent extends Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>Reload</div>
|
<div>
|
||||||
|
{translate('Reload')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<div className={styles.additionalInfo}>
|
<div className={styles.additionalInfo}>
|
||||||
Note: Sonarr will automatically restart and reload the UI during the restore process.
|
{translate('RestartReloadNote')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button onPress={onModalClose}>
|
<Button onPress={onModalClose}>
|
||||||
Cancel
|
{translate('Cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<SpinnerButton
|
<SpinnerButton
|
||||||
|
@ -209,7 +218,7 @@ class RestoreBackupModalContent extends Component {
|
||||||
isSpinning={isRestoring}
|
isSpinning={isRestoring}
|
||||||
onPress={this.onRestorePress}
|
onPress={this.onRestorePress}
|
||||||
>
|
>
|
||||||
Restore
|
{translate('Restore')}
|
||||||
</SpinnerButton>
|
</SpinnerButton>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import TableBody from 'Components/Table/TableBody';
|
||||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||||
import TablePager from 'Components/Table/TablePager';
|
import TablePager from 'Components/Table/TablePager';
|
||||||
import { align, icons, kinds } from 'Helpers/Props';
|
import { align, icons, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import LogsTableRow from './LogsTableRow';
|
import LogsTableRow from './LogsTableRow';
|
||||||
|
|
||||||
function LogsTable(props) {
|
function LogsTable(props) {
|
||||||
|
@ -33,11 +34,11 @@ function LogsTable(props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Logs">
|
<PageContent title={translate('Logs')}>
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
<PageToolbarSection>
|
<PageToolbarSection>
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Refresh"
|
label={translate('Refresh')}
|
||||||
iconName={icons.REFRESH}
|
iconName={icons.REFRESH}
|
||||||
spinningName={icons.REFRESH}
|
spinningName={icons.REFRESH}
|
||||||
isSpinning={isFetching}
|
isSpinning={isFetching}
|
||||||
|
@ -45,7 +46,7 @@ function LogsTable(props) {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Clear"
|
label={translate('Clear')}
|
||||||
iconName={icons.CLEAR}
|
iconName={icons.CLEAR}
|
||||||
isSpinning={clearLogExecuting}
|
isSpinning={clearLogExecuting}
|
||||||
onPress={onClearLogsPress}
|
onPress={onClearLogsPress}
|
||||||
|
@ -59,7 +60,7 @@ function LogsTable(props) {
|
||||||
canModifyColumns={false}
|
canModifyColumns={false}
|
||||||
>
|
>
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Options"
|
label={translate('Options')}
|
||||||
iconName={icons.TABLE}
|
iconName={icons.TABLE}
|
||||||
/>
|
/>
|
||||||
</TableOptionsModalWrapper>
|
</TableOptionsModalWrapper>
|
||||||
|
@ -83,7 +84,7 @@ function LogsTable(props) {
|
||||||
{
|
{
|
||||||
isPopulated && !error && !items.length &&
|
isPopulated && !error && !items.length &&
|
||||||
<Alert kind={kinds.INFO}>
|
<Alert kind={kinds.INFO}>
|
||||||
No events found
|
{translate('NoEventsFound')}
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
import Scroller from 'Components/Scroller/Scroller';
|
import Scroller from 'Components/Scroller/Scroller';
|
||||||
import { scrollDirections } from 'Helpers/Props';
|
import { scrollDirections } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './LogsTableDetailsModal.css';
|
import styles from './LogsTableDetailsModal.css';
|
||||||
|
|
||||||
function LogsTableDetailsModal(props) {
|
function LogsTableDetailsModal(props) {
|
||||||
|
@ -27,11 +28,13 @@ function LogsTableDetailsModal(props) {
|
||||||
onModalClose={onModalClose}
|
onModalClose={onModalClose}
|
||||||
>
|
>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
Details
|
{translate('Details')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<div>Message</div>
|
<div>
|
||||||
|
{translate('Message')}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Scroller
|
<Scroller
|
||||||
className={styles.detailsText}
|
className={styles.detailsText}
|
||||||
|
@ -43,7 +46,9 @@ function LogsTableDetailsModal(props) {
|
||||||
{
|
{
|
||||||
!!exception &&
|
!!exception &&
|
||||||
<div>
|
<div>
|
||||||
<div>Exception</div>
|
<div>
|
||||||
|
{translate('Exception')}
|
||||||
|
</div>
|
||||||
<Scroller
|
<Scroller
|
||||||
className={styles.detailsText}
|
className={styles.detailsText}
|
||||||
scrollDirection={scrollDirections.HORIZONTAL}
|
scrollDirection={scrollDirections.HORIZONTAL}
|
||||||
|
@ -56,7 +61,7 @@ function LogsTableDetailsModal(props) {
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button onPress={onModalClose}>
|
<Button onPress={onModalClose}>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Alert from 'Components/Alert';
|
import Alert from 'Components/Alert';
|
||||||
import Link from 'Components/Link/Link';
|
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
|
@ -12,18 +11,24 @@ import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
import InlineMarkdown from '../../../Components/Markdown/InlineMarkdown';
|
||||||
import LogsNavMenu from '../LogsNavMenu';
|
import LogsNavMenu from '../LogsNavMenu';
|
||||||
import LogFilesTableRow from './LogFilesTableRow';
|
import LogFilesTableRow from './LogFilesTableRow';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'filename',
|
name: 'filename',
|
||||||
label: 'Filename',
|
get label() {
|
||||||
|
return translate('Filename');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'lastWriteTime',
|
name: 'lastWriteTime',
|
||||||
label: 'Last Write Time',
|
get label() {
|
||||||
|
return translate('LastWriteTime');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -50,7 +55,7 @@ class LogFiles extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Log Files">
|
<PageContent title={translate('LogFiles')}>
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
<PageToolbarSection>
|
<PageToolbarSection>
|
||||||
<LogsNavMenu current={currentLogView} />
|
<LogsNavMenu current={currentLogView} />
|
||||||
|
@ -58,7 +63,7 @@ class LogFiles extends Component {
|
||||||
<PageToolbarSeparator />
|
<PageToolbarSeparator />
|
||||||
|
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Refresh"
|
label={translate('Refresh')}
|
||||||
iconName={icons.REFRESH}
|
iconName={icons.REFRESH}
|
||||||
spinningName={icons.REFRESH}
|
spinningName={icons.REFRESH}
|
||||||
isSpinning={isFetching}
|
isSpinning={isFetching}
|
||||||
|
@ -66,7 +71,7 @@ class LogFiles extends Component {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Clear"
|
label={translate('Clear')}
|
||||||
iconName={icons.CLEAR}
|
iconName={icons.CLEAR}
|
||||||
isSpinning={deleteFilesExecuting}
|
isSpinning={deleteFilesExecuting}
|
||||||
onPress={onDeleteFilesPress}
|
onPress={onDeleteFilesPress}
|
||||||
|
@ -76,13 +81,15 @@ class LogFiles extends Component {
|
||||||
<PageContentBody>
|
<PageContentBody>
|
||||||
<Alert>
|
<Alert>
|
||||||
<div>
|
<div>
|
||||||
Log files are located in: {location}
|
{translate('LogFilesLocation', {
|
||||||
|
location
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
currentLogView === 'Log Files' &&
|
currentLogView === 'Log Files' &&
|
||||||
<div>
|
<div>
|
||||||
The log level defaults to 'Info' and can be changed in <Link to="/settings/general">General Settings</Link>
|
<InlineMarkdown data={translate('TheLogLevelDefault')} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</Alert>
|
</Alert>
|
||||||
|
@ -118,7 +125,7 @@ class LogFiles extends Component {
|
||||||
{
|
{
|
||||||
!isFetching && !items.length &&
|
!isFetching && !items.length &&
|
||||||
<Alert kind={kinds.INFO}>
|
<Alert kind={kinds.INFO}>
|
||||||
No log files
|
{translate('NoLogFiles')}
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import { fetchLogFiles } from 'Store/Actions/systemActions';
|
import { fetchLogFiles } from 'Store/Actions/systemActions';
|
||||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||||
import combinePath from 'Utilities/String/combinePath';
|
import combinePath from 'Utilities/String/combinePath';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import LogFiles from './LogFiles';
|
import LogFiles from './LogFiles';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -29,7 +30,7 @@ function createMapStateToProps() {
|
||||||
isFetching,
|
isFetching,
|
||||||
items,
|
items,
|
||||||
deleteFilesExecuting,
|
deleteFilesExecuting,
|
||||||
currentLogView: 'Log Files',
|
currentLogView: translate('LogFiles'),
|
||||||
location: combinePath(isWindows, appData, ['logs'])
|
location: combinePath(isWindows, appData, ['logs'])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Link from 'Components/Link/Link';
|
||||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './LogFilesTableRow.css';
|
import styles from './LogFilesTableRow.css';
|
||||||
|
|
||||||
class LogFilesTableRow extends Component {
|
class LogFilesTableRow extends Component {
|
||||||
|
@ -32,7 +33,7 @@ class LogFilesTableRow extends Component {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
noRouter={true}
|
noRouter={true}
|
||||||
>
|
>
|
||||||
Download
|
{translate('Download')}
|
||||||
</Link>
|
</Link>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Menu from 'Components/Menu/Menu';
|
||||||
import MenuButton from 'Components/Menu/MenuButton';
|
import MenuButton from 'Components/Menu/MenuButton';
|
||||||
import MenuContent from 'Components/Menu/MenuContent';
|
import MenuContent from 'Components/Menu/MenuContent';
|
||||||
import MenuItem from 'Components/Menu/MenuItem';
|
import MenuItem from 'Components/Menu/MenuItem';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
class LogsNavMenu extends Component {
|
class LogsNavMenu extends Component {
|
||||||
|
|
||||||
|
@ -50,13 +51,13 @@ class LogsNavMenu extends Component {
|
||||||
<MenuItem
|
<MenuItem
|
||||||
to={'/system/logs/files'}
|
to={'/system/logs/files'}
|
||||||
>
|
>
|
||||||
Log Files
|
{translate('LogFiles')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
to={'/system/logs/files/update'}
|
to={'/system/logs/files/update'}
|
||||||
>
|
>
|
||||||
Updater Log Files
|
{translate('UpdaterLogFiles')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'
|
||||||
import FieldSet from 'Components/FieldSet';
|
import FieldSet from 'Components/FieldSet';
|
||||||
import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
|
import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
|
||||||
import titleCase from 'Utilities/String/titleCase';
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import StartTime from './StartTime';
|
import StartTime from './StartTime';
|
||||||
import styles from './About.css';
|
import styles from './About.css';
|
||||||
|
|
||||||
|
@ -30,25 +31,32 @@ class About extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldSet legend="About">
|
<FieldSet legend={translate('About')}>
|
||||||
<DescriptionList className={styles.descriptionList}>
|
<DescriptionList className={styles.descriptionList}>
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Version"
|
title={translate('Version')}
|
||||||
data={version}
|
data={version}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{
|
{
|
||||||
packageVersion &&
|
packageVersion &&
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Package Version"
|
title={translate('PackageVersion')}
|
||||||
data={(packageAuthor ? <span> {packageVersion} {' by '} <InlineMarkdown data={packageAuthor} /> </span> : packageVersion)}
|
data={(packageAuthor ?
|
||||||
|
<InlineMarkdown data={translate('PackageVersionInfo', {
|
||||||
|
packageVersion,
|
||||||
|
packageAuthor
|
||||||
|
})}
|
||||||
|
/> :
|
||||||
|
packageVersion
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
isNetCore &&
|
isNetCore &&
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title=".Net Version"
|
title={translate('DotNetVersion')}
|
||||||
data={`Yes (${runtimeVersion})`}
|
data={`Yes (${runtimeVersion})`}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -56,28 +64,28 @@ class About extends Component {
|
||||||
{
|
{
|
||||||
isDocker &&
|
isDocker &&
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Docker"
|
title={translate('Docker')}
|
||||||
data={'Yes'}
|
data={'Yes'}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="AppData directory"
|
title={translate('AppDataDirectory')}
|
||||||
data={appData}
|
data={appData}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Startup directory"
|
title={translate('StartupDirectory')}
|
||||||
data={startupPath}
|
data={startupPath}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Mode"
|
title={translate('Mode')}
|
||||||
data={titleCase(mode)}
|
data={titleCase(mode)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
title="Uptime"
|
title={translate('Uptime')}
|
||||||
data={
|
data={
|
||||||
<StartTime
|
<StartTime
|
||||||
startTime={startTime}
|
startTime={startTime}
|
||||||
|
|
|
@ -9,22 +9,29 @@ import TableBody from 'Components/Table/TableBody';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { kinds, sizes } from 'Helpers/Props';
|
import { kinds, sizes } from 'Helpers/Props';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './DiskSpace.css';
|
import styles from './DiskSpace.css';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'path',
|
name: 'path',
|
||||||
label: 'Location',
|
get label() {
|
||||||
|
return translate('Location');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'freeSpace',
|
name: 'freeSpace',
|
||||||
label: 'Free Space',
|
get label() {
|
||||||
|
return translate('FreeSpace');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'totalSpace',
|
name: 'totalSpace',
|
||||||
label: 'Total Space',
|
get label() {
|
||||||
|
return translate('TotalSpace');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -45,7 +52,7 @@ class DiskSpace extends Component {
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldSet legend="Disk Space">
|
<FieldSet legend={translate('DiskSpace')}>
|
||||||
{
|
{
|
||||||
isFetching &&
|
isFetching &&
|
||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
|
|
|
@ -11,6 +11,7 @@ import TableBody from 'Components/Table/TableBody';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import titleCase from 'Utilities/String/titleCase';
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './Health.css';
|
import styles from './Health.css';
|
||||||
|
|
||||||
function getInternalLink(source) {
|
function getInternalLink(source) {
|
||||||
|
@ -23,7 +24,7 @@ function getInternalLink(source) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.SETTINGS}
|
name={icons.SETTINGS}
|
||||||
title="Settings"
|
title={translate('Settings')}
|
||||||
to="/settings/indexers"
|
to="/settings/indexers"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -33,7 +34,7 @@ function getInternalLink(source) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.SETTINGS}
|
name={icons.SETTINGS}
|
||||||
title="Settings"
|
title={translate('Settings')}
|
||||||
to="/settings/downloadclients"
|
to="/settings/downloadclients"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -41,7 +42,7 @@ function getInternalLink(source) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.SERIES_CONTINUING}
|
name={icons.SERIES_CONTINUING}
|
||||||
title="Series Editor"
|
title={translate('SeriesEditor')}
|
||||||
to="/serieseditor"
|
to="/serieseditor"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -49,7 +50,7 @@ function getInternalLink(source) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.UPDATE}
|
name={icons.UPDATE}
|
||||||
title="Updates"
|
title={translate('Updates')}
|
||||||
to="/system/updates"
|
to="/system/updates"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -64,7 +65,7 @@ function getTestLink(source, props) {
|
||||||
return (
|
return (
|
||||||
<SpinnerIconButton
|
<SpinnerIconButton
|
||||||
name={icons.TEST}
|
name={icons.TEST}
|
||||||
title="Test All"
|
title={translate('TestAll')}
|
||||||
isSpinning={props.isTestingAllIndexers}
|
isSpinning={props.isTestingAllIndexers}
|
||||||
onPress={props.dispatchTestAllIndexers}
|
onPress={props.dispatchTestAllIndexers}
|
||||||
/>
|
/>
|
||||||
|
@ -74,7 +75,7 @@ function getTestLink(source, props) {
|
||||||
return (
|
return (
|
||||||
<SpinnerIconButton
|
<SpinnerIconButton
|
||||||
name={icons.TEST}
|
name={icons.TEST}
|
||||||
title="Test All"
|
title={translate('TestAll')}
|
||||||
isSpinning={props.isTestingAllDownloadClients}
|
isSpinning={props.isTestingAllDownloadClients}
|
||||||
onPress={props.dispatchTestAllDownloadClients}
|
onPress={props.dispatchTestAllDownloadClients}
|
||||||
/>
|
/>
|
||||||
|
@ -93,12 +94,16 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'message',
|
name: 'message',
|
||||||
label: 'Message',
|
get label() {
|
||||||
|
return translate('Message');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'actions',
|
name: 'actions',
|
||||||
label: 'Actions',
|
get label() {
|
||||||
|
return translate('Actions');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -121,7 +126,7 @@ class Health extends Component {
|
||||||
<FieldSet
|
<FieldSet
|
||||||
legend={
|
legend={
|
||||||
<div className={styles.legend}>
|
<div className={styles.legend}>
|
||||||
Health
|
{translate('Health')}
|
||||||
|
|
||||||
{
|
{
|
||||||
isFetching && isPopulated &&
|
isFetching && isPopulated &&
|
||||||
|
@ -141,7 +146,7 @@ class Health extends Component {
|
||||||
{
|
{
|
||||||
!healthIssues &&
|
!healthIssues &&
|
||||||
<div className={styles.healthOk}>
|
<div className={styles.healthOk}>
|
||||||
No issues with your configuration
|
{translate('NoIssuesWithYourConfiguration')}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +191,7 @@ class Health extends Component {
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.WIKI}
|
name={icons.WIKI}
|
||||||
to={item.wikiUrl}
|
to={item.wikiUrl}
|
||||||
title="Read the Wiki for more information"
|
title={translate('ReadTheWikiForMoreInformation')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ import DescriptionListItemDescription from 'Components/DescriptionList/Descripti
|
||||||
import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
|
import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
|
||||||
import FieldSet from 'Components/FieldSet';
|
import FieldSet from 'Components/FieldSet';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
class MoreInfo extends Component {
|
class MoreInfo extends Component {
|
||||||
|
|
||||||
|
@ -12,34 +13,46 @@ class MoreInfo extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<FieldSet legend="More Info">
|
<FieldSet legend={translate('MoreInfo')}>
|
||||||
<DescriptionList>
|
<DescriptionList>
|
||||||
<DescriptionListItemTitle>Home page</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('HomePage')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://sonarr.tv/">sonarr.tv</Link>
|
<Link to="https://sonarr.tv/">sonarr.tv</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Wiki</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Wiki')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://wiki.servarr.com/sonarr">wiki.servarr.com/sonarr</Link>
|
<Link to="https://wiki.servarr.com/sonarr">wiki.servarr.com/sonarr</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Forums</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Forums')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://forums.sonarr.tv/">forums.sonarr.tv</Link>
|
<Link to="https://forums.sonarr.tv/">forums.sonarr.tv</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Twitter</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Twitter')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://twitter.com/sonarrtv">@sonarrtv</Link>
|
<Link to="https://twitter.com/sonarrtv">@sonarrtv</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Discord</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Discord')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://discord.sonarr.tv/">discord.sonarr.tv</Link>
|
<Link to="https://discord.sonarr.tv/">discord.sonarr.tv</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>IRC</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('IRC')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="irc://irc.libera.chat/#sonarr">#sonarr on Libera</Link>
|
<Link to="irc://irc.libera.chat/#sonarr">#sonarr on Libera</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
@ -47,17 +60,23 @@ class MoreInfo extends Component {
|
||||||
<Link to="https://web.libera.chat/?channels=#sonarr">Libera webchat</Link>
|
<Link to="https://web.libera.chat/?channels=#sonarr">Libera webchat</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Donations</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Donations')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://sonarr.tv/donate">sonarr.tv/donate</Link>
|
<Link to="https://sonarr.tv/donate">sonarr.tv/donate</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Source</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('Source')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://github.com/Sonarr/Sonarr/">github.com/Sonarr/Sonarr</Link>
|
<Link to="https://github.com/Sonarr/Sonarr/">github.com/Sonarr/Sonarr</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
||||||
<DescriptionListItemTitle>Feature Requests</DescriptionListItemTitle>
|
<DescriptionListItemTitle>
|
||||||
|
{translate('FeatureRequests')}
|
||||||
|
</DescriptionListItemTitle>
|
||||||
<DescriptionListItemDescription>
|
<DescriptionListItemDescription>
|
||||||
<Link to="https://forums.sonarr.tv/">forums.sonarr.tv</Link>
|
<Link to="https://forums.sonarr.tv/">forums.sonarr.tv</Link>
|
||||||
</DescriptionListItemDescription>
|
</DescriptionListItemDescription>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import AboutConnector from './About/AboutConnector';
|
import AboutConnector from './About/AboutConnector';
|
||||||
import DiskSpaceConnector from './DiskSpace/DiskSpaceConnector';
|
import DiskSpaceConnector from './DiskSpace/DiskSpaceConnector';
|
||||||
import HealthConnector from './Health/HealthConnector';
|
import HealthConnector from './Health/HealthConnector';
|
||||||
|
@ -13,7 +14,7 @@ class Status extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<PageContent title="Status">
|
<PageContent title={translate('Status')}>
|
||||||
<PageContentBody>
|
<PageContentBody>
|
||||||
<HealthConnector />
|
<HealthConnector />
|
||||||
<DiskSpaceConnector />
|
<DiskSpaceConnector />
|
||||||
|
|
|
@ -11,6 +11,7 @@ import formatDate from 'Utilities/Date/formatDate';
|
||||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||||
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
|
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
|
||||||
import titleCase from 'Utilities/String/titleCase';
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './QueuedTaskRow.css';
|
import styles from './QueuedTaskRow.css';
|
||||||
|
|
||||||
function getStatusIconProps(status, message) {
|
function getStatusIconProps(status, message) {
|
||||||
|
@ -198,8 +199,8 @@ class QueuedTaskRow extends Component {
|
||||||
</span>
|
</span>
|
||||||
{
|
{
|
||||||
clientUserAgent ?
|
clientUserAgent ?
|
||||||
<span className={styles.userAgent} title="User-Agent provided by the app that called the API">
|
<span className={styles.userAgent} title={translate('TaskUserAgentTooltip')}>
|
||||||
from: {clientUserAgent}
|
{translate('From')}: {clientUserAgent}
|
||||||
</span> :
|
</span> :
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -236,7 +237,7 @@ class QueuedTaskRow extends Component {
|
||||||
{
|
{
|
||||||
status === 'queued' &&
|
status === 'queued' &&
|
||||||
<IconButton
|
<IconButton
|
||||||
title="Removed from task queue"
|
title={translate('RemovedFromTaskQueue')}
|
||||||
name={icons.REMOVE}
|
name={icons.REMOVE}
|
||||||
onPress={this.onCancelPress}
|
onPress={this.onCancelPress}
|
||||||
/>
|
/>
|
||||||
|
@ -246,10 +247,10 @@ class QueuedTaskRow extends Component {
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={isCancelConfirmModalOpen}
|
isOpen={isCancelConfirmModalOpen}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
title="Cancel"
|
title={translate('Cancel')}
|
||||||
message={'Are you sure you want to cancel this pending task?'}
|
message={translate('CancelPendingTask')}
|
||||||
confirmLabel="Yes, Cancel"
|
confirmLabel={translate('YesCancel')}
|
||||||
cancelLabel="No, Leave It"
|
cancelLabel={translate('NoLeaveIt')}
|
||||||
onConfirm={onCancelPress}
|
onConfirm={onCancelPress}
|
||||||
onCancel={this.onAbortCancel}
|
onCancel={this.onAbortCancel}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import FieldSet from 'Components/FieldSet';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import QueuedTaskRowConnector from './QueuedTaskRowConnector';
|
import QueuedTaskRowConnector from './QueuedTaskRowConnector';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
@ -14,27 +15,37 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'commandName',
|
name: 'commandName',
|
||||||
label: 'Name',
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'queued',
|
name: 'queued',
|
||||||
label: 'Queued',
|
get label() {
|
||||||
|
return translate('Queued');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'started',
|
name: 'started',
|
||||||
label: 'Started',
|
get label() {
|
||||||
|
return translate('Started');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ended',
|
name: 'ended',
|
||||||
label: 'Ended',
|
get label() {
|
||||||
|
return translate('Ended');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'duration',
|
name: 'duration',
|
||||||
label: 'Duration',
|
get label() {
|
||||||
|
return translate('Duration');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -51,7 +62,7 @@ function QueuedTasks(props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldSet legend="Queue">
|
<FieldSet legend={translate('Queue')}>
|
||||||
{
|
{
|
||||||
isFetching && !isPopulated &&
|
isFetching && !isPopulated &&
|
||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
|
|
|
@ -4,32 +4,43 @@ import FieldSet from 'Components/FieldSet';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import ScheduledTaskRowConnector from './ScheduledTaskRowConnector';
|
import ScheduledTaskRowConnector from './ScheduledTaskRowConnector';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'interval',
|
name: 'interval',
|
||||||
label: 'Interval',
|
get label() {
|
||||||
|
return translate('Interval');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'lastExecution',
|
name: 'lastExecution',
|
||||||
label: 'Last Execution',
|
get label() {
|
||||||
|
return translate('LastExecution');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'lastDuration',
|
name: 'lastDuration',
|
||||||
label: 'Last Duration',
|
get label() {
|
||||||
|
return translate('LastDuration');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nextExecution',
|
name: 'nextExecution',
|
||||||
label: 'Next Execution',
|
get label() {
|
||||||
|
return translate('NextExecution');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -46,7 +57,7 @@ function ScheduledTasks(props) {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldSet legend="Scheduled">
|
<FieldSet legend={translate('Scheduled')}>
|
||||||
{
|
{
|
||||||
isFetching && !isPopulated &&
|
isFetching && !isPopulated &&
|
||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import QueuedTasksConnector from './Queued/QueuedTasksConnector';
|
import QueuedTasksConnector from './Queued/QueuedTasksConnector';
|
||||||
import ScheduledTasksConnector from './Scheduled/ScheduledTasksConnector';
|
import ScheduledTasksConnector from './Scheduled/ScheduledTasksConnector';
|
||||||
|
|
||||||
function Tasks() {
|
function Tasks() {
|
||||||
return (
|
return (
|
||||||
<PageContent title="Tasks">
|
<PageContent title={translate('Tasks')}>
|
||||||
<PageContentBody>
|
<PageContentBody>
|
||||||
<ScheduledTasksConnector />
|
<ScheduledTasksConnector />
|
||||||
<QueuedTasksConnector />
|
<QueuedTasksConnector />
|
||||||
|
|
|
@ -12,6 +12,7 @@ import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import formatDate from 'Utilities/Date/formatDate';
|
import formatDate from 'Utilities/Date/formatDate';
|
||||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import UpdateChanges from './UpdateChanges';
|
import UpdateChanges from './UpdateChanges';
|
||||||
import styles from './Updates.css';
|
import styles from './Updates.css';
|
||||||
|
|
||||||
|
@ -43,15 +44,15 @@ class Updates extends Component {
|
||||||
const hasUpdateToInstall = hasUpdates && _.some(items, { installable: true, latest: true });
|
const hasUpdateToInstall = hasUpdates && _.some(items, { installable: true, latest: true });
|
||||||
const noUpdateToInstall = hasUpdates && !hasUpdateToInstall;
|
const noUpdateToInstall = hasUpdates && !hasUpdateToInstall;
|
||||||
|
|
||||||
const externalUpdaterPrefix = 'Unable to update Sonarr directly,';
|
const externalUpdaterPrefix = translate('UnableToUpdateSonarrDirectly');
|
||||||
const externalUpdaterMessages = {
|
const externalUpdaterMessages = {
|
||||||
external: 'Sonarr is configured to use an external update mechanism',
|
external: translate('ExternalUpdater'),
|
||||||
apt: 'use apt to install the update',
|
apt: translate('AptUpdater'),
|
||||||
docker: 'update the docker container to receive the update'
|
docker: translate('DockerUpdater')
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Updates">
|
<PageContent title={translate('Updates')}>
|
||||||
<PageContentBody>
|
<PageContentBody>
|
||||||
{
|
{
|
||||||
!isPopulated && !hasError &&
|
!isPopulated && !hasError &&
|
||||||
|
@ -61,7 +62,7 @@ class Updates extends Component {
|
||||||
{
|
{
|
||||||
noUpdates &&
|
noUpdates &&
|
||||||
<Alert kind={kinds.INFO}>
|
<Alert kind={kinds.INFO}>
|
||||||
No updates are available
|
{translate('NoUpdatesAreAvailable')}
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ class Updates extends Component {
|
||||||
isSpinning={isInstallingUpdate}
|
isSpinning={isInstallingUpdate}
|
||||||
onPress={onInstallLatestPress}
|
onPress={onInstallLatestPress}
|
||||||
>
|
>
|
||||||
Install Latest
|
{translate('InstallLatest')}
|
||||||
</SpinnerButton> :
|
</SpinnerButton> :
|
||||||
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -112,7 +113,7 @@ class Updates extends Component {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.message}>
|
<div className={styles.message}>
|
||||||
The latest version of Sonarr is already installed
|
{translate('OnLatestVersion')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -164,7 +165,7 @@ class Updates extends Component {
|
||||||
kind={kinds.SUCCESS}
|
kind={kinds.SUCCESS}
|
||||||
title={formatDateTime(update.installedOn, longDateFormat, timeFormat)}
|
title={formatDateTime(update.installedOn, longDateFormat, timeFormat)}
|
||||||
>
|
>
|
||||||
Currently Installed
|
{translate('CurrentlyInstalled')}
|
||||||
</Label> :
|
</Label> :
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -176,7 +177,7 @@ class Updates extends Component {
|
||||||
kind={kinds.INVERSE}
|
kind={kinds.INVERSE}
|
||||||
title={formatDateTime(update.installedOn, longDateFormat, timeFormat)}
|
title={formatDateTime(update.installedOn, longDateFormat, timeFormat)}
|
||||||
>
|
>
|
||||||
Previously Installed
|
{translate('PreviouslyInstalled')}
|
||||||
</Label> :
|
</Label> :
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -184,19 +185,21 @@ class Updates extends Component {
|
||||||
|
|
||||||
{
|
{
|
||||||
!hasChanges &&
|
!hasChanges &&
|
||||||
<div>Maintenance Release: See GitHub commit history for details.</div>
|
<div>
|
||||||
|
{translate('MaintenanceRelease')}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
hasChanges &&
|
hasChanges &&
|
||||||
<div className={styles.changes}>
|
<div className={styles.changes}>
|
||||||
<UpdateChanges
|
<UpdateChanges
|
||||||
title="New"
|
title={translate('New')}
|
||||||
changes={update.changes.new}
|
changes={update.changes.new}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UpdateChanges
|
<UpdateChanges
|
||||||
title="Fixed"
|
title={translate('Fixed')}
|
||||||
changes={update.changes.fixed}
|
changes={update.changes.fixed}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -211,14 +214,14 @@ class Updates extends Component {
|
||||||
{
|
{
|
||||||
!!updatesError &&
|
!!updatesError &&
|
||||||
<div>
|
<div>
|
||||||
Failed to fetch updates
|
{translate('FailedToFetchUpdates')}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
!!generalSettingsError &&
|
!!generalSettingsError &&
|
||||||
<div>
|
<div>
|
||||||
Failed to update settings
|
{translate('FailedToUpdateSettings')}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
|
|
|
@ -4,14 +4,14 @@ function getTranslations() {
|
||||||
return createAjaxRequest({
|
return createAjaxRequest({
|
||||||
global: false,
|
global: false,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
url: '/localization'
|
url: '/localization',
|
||||||
}).request;
|
}).request;
|
||||||
}
|
}
|
||||||
|
|
||||||
let translations = {};
|
let translations: Record<string, string> = {};
|
||||||
|
|
||||||
export function fetchTranslations() {
|
export async function fetchTranslations(): Promise<boolean> {
|
||||||
return new Promise(async(resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
try {
|
try {
|
||||||
const data = await getTranslations();
|
const data = await getTranslations();
|
||||||
translations = data.strings;
|
translations = data.strings;
|
||||||
|
@ -23,7 +23,10 @@ export function fetchTranslations() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function translate(key, tokens) {
|
export default function translate(
|
||||||
|
key: string,
|
||||||
|
tokens?: Record<string, string | number | boolean>
|
||||||
|
) {
|
||||||
const translation = translations[key] || key;
|
const translation = translations[key] || key;
|
||||||
|
|
||||||
if (tokens) {
|
if (tokens) {
|
|
@ -2,7 +2,6 @@ import { createBrowserHistory } from 'history';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import createAppStore from 'Store/createAppStore';
|
import createAppStore from 'Store/createAppStore';
|
||||||
import { fetchTranslations } from 'Utilities/String/translate';
|
|
||||||
import App from './App/App';
|
import App from './App/App';
|
||||||
|
|
||||||
import 'Diag/ConsoleApi';
|
import 'Diag/ConsoleApi';
|
||||||
|
@ -10,14 +9,9 @@ import 'Diag/ConsoleApi';
|
||||||
export async function bootstrap() {
|
export async function bootstrap() {
|
||||||
const history = createBrowserHistory();
|
const history = createBrowserHistory();
|
||||||
const store = createAppStore(history);
|
const store = createAppStore(history);
|
||||||
const hasTranslationsError = !(await fetchTranslations());
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<App
|
<App store={store} history={history} />,
|
||||||
store={store}
|
|
||||||
history={history}
|
|
||||||
hasTranslationsError={hasTranslationsError}
|
|
||||||
/>,
|
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
"DownloadClientSortingHealthCheckMessage": "Im Download-Client {0} ist die Sortierung {1} für die Kategorie von Sonarr aktiviert. Sie sollten die Sortierung in Ihrem Download-Client deaktivieren, um Importprobleme zu vermeiden.",
|
"DownloadClientSortingHealthCheckMessage": "Im Download-Client {0} ist die Sortierung {1} für die Kategorie von Sonarr aktiviert. Sie sollten die Sortierung in Ihrem Download-Client deaktivieren, um Importprobleme zu vermeiden.",
|
||||||
"DownloadClientStatusSingleClientHealthCheckMessage": "Download-Clients sind aufgrund von Fehlern nicht verfügbar: {0}",
|
"DownloadClientStatusSingleClientHealthCheckMessage": "Download-Clients sind aufgrund von Fehlern nicht verfügbar: {0}",
|
||||||
"DownloadClientStatusAllClientHealthCheckMessage": "Alle Download-Clients sind aufgrund von Fehlern nicht verfügbar",
|
"DownloadClientStatusAllClientHealthCheckMessage": "Alle Download-Clients sind aufgrund von Fehlern nicht verfügbar",
|
||||||
"EditSelectedDownloadClients": "Ausgewählte Download-Clients bearbeiten",
|
"EditSelectedDownloadClients": "Ausgewählte Download Clienten bearbeiten",
|
||||||
"EditSelectedImportLists": "Ausgewählte Importlisten bearbeiten",
|
"EditSelectedImportLists": "Ausgewählte Einspiel-Liste bearbeten",
|
||||||
"EditSelectedIndexers": "Ausgewählte Indexer bearbeiten",
|
"EditSelectedIndexers": "Ausgewähle Indexer bearbeiten",
|
||||||
"EditSeries": "Serie bearbeiten",
|
"EditSeries": "Serie bearbeiten",
|
||||||
"EnableAutomaticSearch": "Automatische Suche einschalten",
|
"EnableAutomaticSearch": "Automatische Suche einschalten",
|
||||||
"EnableInteractiveSearch": "Interaktive Suche einschalten",
|
"EnableInteractiveSearch": "Interaktive Suche einschalten",
|
||||||
|
@ -26,5 +26,17 @@
|
||||||
"DeleteConditionMessageText": "Bist du sicher, dass du die Bedingung '{0}' löschen willst?",
|
"DeleteConditionMessageText": "Bist du sicher, dass du die Bedingung '{0}' löschen willst?",
|
||||||
"DeleteCustomFormatMessageText": "Bist du sicher, dass du das eigene Format '{0}' löschen willst?",
|
"DeleteCustomFormatMessageText": "Bist du sicher, dass du das eigene Format '{0}' löschen willst?",
|
||||||
"RemoveSelectedItemQueueMessageText": "Bist du sicher, dass du ein Eintrag aus der Warteschlange entfernen willst?",
|
"RemoveSelectedItemQueueMessageText": "Bist du sicher, dass du ein Eintrag aus der Warteschlange entfernen willst?",
|
||||||
"RemoveSelectedItemsQueueMessageText": "Bist du sicher, dass du {0} Einträge aus der Warteschlange entfernen willst?"
|
"RemoveSelectedItemsQueueMessageText": "Bist du sicher, dass du {0} Einträge aus der Warteschlange entfernen willst?",
|
||||||
|
"DeleteSelectedDownloadClients": "Lösche Download Client(s)",
|
||||||
|
"DeleteSelectedIndexers": "Lösche Indexer",
|
||||||
|
"DeleteSelectedImportLists": "Lösche Einspiel Liste",
|
||||||
|
"Implementation": "Integration",
|
||||||
|
"ManageIndexers": "Verwalte Indexer",
|
||||||
|
"ManageLists": "Verwalte Listen",
|
||||||
|
"NoImportListsFound": "Keine Einspiel-Listen gefunden",
|
||||||
|
"NoIndexersFound": "Keine Indexer gefunden",
|
||||||
|
"ManageClients": "Verwalte Clienten",
|
||||||
|
"ManageDownloadClients": "Verwalte Download Clienten",
|
||||||
|
"ManageImportLists": "Verwalte Einspiel-Listen",
|
||||||
|
"NoDownloadClientsFound": "Keine Download Clienten gefunden"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
{
|
{
|
||||||
|
"About": "About",
|
||||||
"AbsoluteEpisodeNumbers": "Absolute Episode Number(s)",
|
"AbsoluteEpisodeNumbers": "Absolute Episode Number(s)",
|
||||||
|
"Actions": "Actions",
|
||||||
"Activity": "Activity",
|
"Activity": "Activity",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
"AddNew": "Add New",
|
|
||||||
"Added": "Added",
|
"Added": "Added",
|
||||||
"AddingTag": "Adding tag",
|
"AddingTag": "Adding tag",
|
||||||
|
"AddNew": "Add New",
|
||||||
"AirDate": "Air Date",
|
"AirDate": "Air Date",
|
||||||
"AllTitles": "All Titles",
|
"AllTitles": "All Titles",
|
||||||
"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",
|
||||||
"AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update",
|
"AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update",
|
||||||
"Apply": "Apply",
|
"Apply": "Apply",
|
||||||
"ApplyChanges": "Apply Changes",
|
"ApplyChanges": "Apply Changes",
|
||||||
|
@ -20,9 +23,13 @@
|
||||||
"ApplyTagsHelpTextHowToApplySeries": "How to apply tags to the selected series",
|
"ApplyTagsHelpTextHowToApplySeries": "How to apply tags to the selected series",
|
||||||
"ApplyTagsHelpTextRemove": "Remove: Remove the entered tags",
|
"ApplyTagsHelpTextRemove": "Remove: Remove the entered tags",
|
||||||
"ApplyTagsHelpTextReplace": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)",
|
"ApplyTagsHelpTextReplace": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)",
|
||||||
|
"AptUpdater": "Use apt to install the update",
|
||||||
"AutoAdd": "Auto Add",
|
"AutoAdd": "Auto Add",
|
||||||
"AutomaticAdd": "Automatic Add",
|
"AutomaticAdd": "Automatic Add",
|
||||||
"Backup": "Backup",
|
"Backup": "Backup",
|
||||||
|
"BackupNow": "Backup Now",
|
||||||
|
"Backups": "Backups",
|
||||||
|
"BeforeUpdate": "Before update",
|
||||||
"Blocklist": "Blocklist",
|
"Blocklist": "Blocklist",
|
||||||
"BlocklistRelease": "Blocklist Release",
|
"BlocklistRelease": "Blocklist Release",
|
||||||
"BlocklistReleaseHelpText": "Prevents Sonarr from automatically grabbing this release again",
|
"BlocklistReleaseHelpText": "Prevents Sonarr from automatically grabbing this release again",
|
||||||
|
@ -30,6 +37,8 @@
|
||||||
"Browser Reload Required": "Browser Reload Required",
|
"Browser Reload Required": "Browser Reload Required",
|
||||||
"Calendar": "Calendar",
|
"Calendar": "Calendar",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
|
"CancelPendingTask": "Are you sure you want to cancel this pending task?",
|
||||||
|
"Clear": "Clear",
|
||||||
"CloneCondition": "Clone Condition",
|
"CloneCondition": "Clone Condition",
|
||||||
"CloneCustomFormat": "Clone Custom Format",
|
"CloneCustomFormat": "Clone Custom Format",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
@ -38,11 +47,14 @@
|
||||||
"CountImportListsSelected": "{count} import list(s) selected",
|
"CountImportListsSelected": "{count} import list(s) selected",
|
||||||
"CountIndexersSelected": "{count} indexer(s) selected",
|
"CountIndexersSelected": "{count} indexer(s) selected",
|
||||||
"CountSeasons": "{count} seasons",
|
"CountSeasons": "{count} seasons",
|
||||||
"CustomFormatScore": "Custom Format Score",
|
"CurrentlyInstalled": "Currently Installed",
|
||||||
"CustomFormats": "Custom Formats",
|
"CustomFormats": "Custom Formats",
|
||||||
|
"CustomFormatScore": "Custom Format Score",
|
||||||
"CutoffUnmet": "Cutoff Unmet",
|
"CutoffUnmet": "Cutoff Unmet",
|
||||||
"Daily": "Daily",
|
"Daily": "Daily",
|
||||||
"Delete": "Delete",
|
"Delete": "Delete",
|
||||||
|
"DeleteBackup": "Delete Backup",
|
||||||
|
"DeleteBackupMessageText": "Are you sure you want to delete the backup '{name}'?",
|
||||||
"DeleteCondition": "Delete Condition",
|
"DeleteCondition": "Delete Condition",
|
||||||
"DeleteConditionMessageText": "Are you sure you want to delete the condition '{0}'?",
|
"DeleteConditionMessageText": "Are you sure you want to delete the condition '{0}'?",
|
||||||
"DeleteCustomFormat": "Delete Custom Format",
|
"DeleteCustomFormat": "Delete Custom Format",
|
||||||
|
@ -55,39 +67,61 @@
|
||||||
"DeleteSelectedIndexersMessageText": "Are you sure you want to delete {count} selected indexer(s)?",
|
"DeleteSelectedIndexersMessageText": "Are you sure you want to delete {count} selected indexer(s)?",
|
||||||
"Details": "Details",
|
"Details": "Details",
|
||||||
"Disabled": "Disabled",
|
"Disabled": "Disabled",
|
||||||
|
"Discord": "Discord",
|
||||||
|
"DiskSpace": "Disk Space",
|
||||||
|
"Docker": "Docker",
|
||||||
|
"DockerUpdater": "Update the docker container to receive the update",
|
||||||
|
"Donations": "Donations",
|
||||||
|
"DotNetVersion": ".NET",
|
||||||
|
"Download": "Download",
|
||||||
"DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available",
|
"DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available",
|
||||||
"DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {0}.",
|
"DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {0}.",
|
||||||
"DownloadClientRootFolderHealthCheckMessage": "Download client {0} places downloads in the root folder {1}. You should not download to a root folder.",
|
"DownloadClientRootFolderHealthCheckMessage": "Download client {0} places downloads in the root folder {1}. You should not download to a root folder.",
|
||||||
|
"DownloadClients": "Download Clients",
|
||||||
"DownloadClientSortingHealthCheckMessage": "Download client {0} has {1} sorting enabled for Sonarr's category. You should disable sorting in your download client to avoid import issues.",
|
"DownloadClientSortingHealthCheckMessage": "Download client {0} has {1} sorting enabled for Sonarr's category. You should disable sorting in your download client to avoid import issues.",
|
||||||
"DownloadClientStatusAllClientHealthCheckMessage": "All download clients are unavailable due to failures",
|
"DownloadClientStatusAllClientHealthCheckMessage": "All download clients are unavailable due to failures",
|
||||||
"DownloadClientStatusSingleClientHealthCheckMessage": "Download clients unavailable due to failures: {0}",
|
"DownloadClientStatusSingleClientHealthCheckMessage": "Download clients unavailable due to failures: {0}",
|
||||||
"DownloadClients": "Download Clients",
|
"Duration": "Duration",
|
||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
"EditSelectedDownloadClients": "Edit Selected Download Clients",
|
"EditSelectedDownloadClients": "Edit Selected Download Clients",
|
||||||
"EditSelectedImportLists": "Edit Selected Import Lists",
|
"EditSelectedImportLists": "Edit Selected Import Lists",
|
||||||
"EditSelectedIndexers": "Edit Selected Indexers",
|
"EditSelectedIndexers": "Edit Selected Indexers",
|
||||||
"EditSeries": "Edit Series",
|
"EditSeries": "Edit Series",
|
||||||
"EnableAutomaticSearch": "Enable Automatic Search",
|
"EnableAutomaticSearch": "Enable Automatic Search",
|
||||||
|
"Enabled": "Enabled",
|
||||||
"EnableInteractiveSearch": "Enable Interactive Search",
|
"EnableInteractiveSearch": "Enable Interactive Search",
|
||||||
"EnableRSS": "Enable RSS",
|
"EnableRSS": "Enable RSS",
|
||||||
"Enabled": "Enabled",
|
|
||||||
"Ended": "Ended",
|
"Ended": "Ended",
|
||||||
"EpisodeInfo": "Episode Info",
|
"EpisodeInfo": "Episode Info",
|
||||||
"EpisodeNumbers": "Episode Number(s)",
|
"EpisodeNumbers": "Episode Number(s)",
|
||||||
|
"ErrorRestoringBackup": "Error restoring backup",
|
||||||
"Events": "Events",
|
"Events": "Events",
|
||||||
|
"Exception": "Exception",
|
||||||
"ExistingTag": "Existing tag",
|
"ExistingTag": "Existing tag",
|
||||||
"ExportCustomFormat": "Export Custom Format",
|
"ExportCustomFormat": "Export Custom Format",
|
||||||
|
"ExternalUpdater": "Sonarr is configured to use an external update mechanism",
|
||||||
|
"FailedToFetchUpdates": "Failed to fetch updates",
|
||||||
|
"FailedToUpdateSettings": "Failed to update settings",
|
||||||
|
"FeatureRequests": "Feature Requests",
|
||||||
|
"Filename": "Filename",
|
||||||
|
"Fixed": "Fixed",
|
||||||
|
"Forums": "Forums",
|
||||||
|
"FreeSpace": "Free Space",
|
||||||
|
"From": "From",
|
||||||
"FullSeason": "Full Season",
|
"FullSeason": "Full Season",
|
||||||
"General": "General",
|
"General": "General",
|
||||||
|
"GeneralSettings": "General Settings",
|
||||||
|
"Health": "Health",
|
||||||
"HiddenClickToShow": "Hidden, click to show",
|
"HiddenClickToShow": "Hidden, click to show",
|
||||||
"HideAdvanced": "Hide Advanced",
|
"HideAdvanced": "Hide Advanced",
|
||||||
"History": "History",
|
"History": "History",
|
||||||
|
"HomePage": "Home Page",
|
||||||
"Implementation": "Implementation",
|
"Implementation": "Implementation",
|
||||||
"ImportListRootFolderMissingRootHealthCheckMessage": "Missing root folder for import list(s): {0}",
|
"ImportListRootFolderMissingRootHealthCheckMessage": "Missing root folder for import list(s): {0}",
|
||||||
"ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Multiple root folders are missing for import lists: {0}",
|
"ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Multiple root folders are missing for import lists: {0}",
|
||||||
|
"ImportLists": "Import Lists",
|
||||||
"ImportListStatusAllUnavailableHealthCheckMessage": "All lists are unavailable due to failures",
|
"ImportListStatusAllUnavailableHealthCheckMessage": "All lists are unavailable due to failures",
|
||||||
"ImportListStatusUnavailableHealthCheckMessage": "Lists unavailable due to failures: {0}",
|
"ImportListStatusUnavailableHealthCheckMessage": "Lists unavailable due to failures: {0}",
|
||||||
"ImportLists": "Import Lists",
|
|
||||||
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleHealthCheckMessage": "Enable Completed Download Handling if possible",
|
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleHealthCheckMessage": "Enable Completed Download Handling if possible",
|
||||||
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleMultiComputerHealthCheckMessage": "Enable Completed Download Handling if possible (Multi-Computer unsupported)",
|
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleMultiComputerHealthCheckMessage": "Enable Completed Download Handling if possible (Multi-Computer unsupported)",
|
||||||
"ImportMechanismHandlingDisabledHealthCheckMessage": "Enable Completed Download Handling",
|
"ImportMechanismHandlingDisabledHealthCheckMessage": "Enable Completed Download Handling",
|
||||||
|
@ -96,47 +130,74 @@
|
||||||
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {0}",
|
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {0}",
|
||||||
"IndexerRssNoIndexersAvailableHealthCheckMessage": "All rss-capable indexers are temporarily unavailable due to recent indexer errors",
|
"IndexerRssNoIndexersAvailableHealthCheckMessage": "All rss-capable indexers are temporarily unavailable due to recent indexer errors",
|
||||||
"IndexerRssNoIndexersEnabledHealthCheckMessage": "No indexers available with RSS sync enabled, Sonarr will not grab new releases automatically",
|
"IndexerRssNoIndexersEnabledHealthCheckMessage": "No indexers available with RSS sync enabled, Sonarr will not grab new releases automatically",
|
||||||
|
"Indexers": "Indexers",
|
||||||
"IndexerSearchNoAutomaticHealthCheckMessage": "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results",
|
"IndexerSearchNoAutomaticHealthCheckMessage": "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results",
|
||||||
"IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors",
|
"IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors",
|
||||||
"IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results",
|
"IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results",
|
||||||
"IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures",
|
"IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures",
|
||||||
"IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {0}",
|
"IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {0}",
|
||||||
"Indexers": "Indexers",
|
"InstallLatest": "Install Latest",
|
||||||
|
"Interval": "Interval",
|
||||||
|
"IRC": "IRC",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Language that Sonarr will use for UI": "Language that Sonarr will use for UI",
|
"Language that Sonarr will use for UI": "Language that Sonarr will use for UI",
|
||||||
"Languages": "Languages",
|
"Languages": "Languages",
|
||||||
|
"LastDuration": "Last Duration",
|
||||||
|
"LastExecution": "Last Execution",
|
||||||
|
"LastWriteTime": "Last Write Time",
|
||||||
"LibraryImport": "Library Import",
|
"LibraryImport": "Library Import",
|
||||||
|
"Location": "Location",
|
||||||
"LogFiles": "Log Files",
|
"LogFiles": "Log Files",
|
||||||
|
"LogFilesLocation": "Log files are located in: {location}",
|
||||||
|
"Logs": "Logs",
|
||||||
|
"MaintenanceRelease": "Maintenance Release: bug fixes and other improvements. See Github Commit History for more details",
|
||||||
"ManageClients": "Manage Clients",
|
"ManageClients": "Manage Clients",
|
||||||
"ManageDownloadClients": "Manage Download Clients",
|
"ManageDownloadClients": "Manage Download Clients",
|
||||||
"ManageImportLists": "Manage Import Lists",
|
"ManageImportLists": "Manage Import Lists",
|
||||||
"ManageIndexers": "Manage Indexers",
|
"ManageIndexers": "Manage Indexers",
|
||||||
"ManageLists": "Manage Lists",
|
"ManageLists": "Manage Lists",
|
||||||
|
"Manual": "Manual",
|
||||||
"MatchedToEpisodes": "Matched to Episodes",
|
"MatchedToEpisodes": "Matched to Episodes",
|
||||||
"MatchedToSeason": "Matched to Season",
|
"MatchedToSeason": "Matched to Season",
|
||||||
"MatchedToSeries": "Matched to Series",
|
"MatchedToSeries": "Matched to Series",
|
||||||
"MediaManagement": "Media Management",
|
"MediaManagement": "Media Management",
|
||||||
|
"Message": "Message",
|
||||||
"Metadata": "Metadata",
|
"Metadata": "Metadata",
|
||||||
"MetadataSource": "Metadata Source",
|
"MetadataSource": "Metadata Source",
|
||||||
"Missing": "Missing",
|
"Missing": "Missing",
|
||||||
|
"Mode": "Mode",
|
||||||
"Monitored": "Monitored",
|
"Monitored": "Monitored",
|
||||||
|
"MoreInfo": "More Info",
|
||||||
"MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ",
|
"MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ",
|
||||||
"MultiSeason": "Multi-Season",
|
"MultiSeason": "Multi-Season",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Negated": "Negated",
|
"Negated": "Negated",
|
||||||
"Network": "Network",
|
"Network": "Network",
|
||||||
|
"New": "New",
|
||||||
"NextAiring": "Next Airing",
|
"NextAiring": "Next Airing",
|
||||||
|
"NextExecution": "Next Execution",
|
||||||
"No": "No",
|
"No": "No",
|
||||||
|
"NoBackupsAreAvailable": "No backups are available",
|
||||||
"NoChange": "No Change",
|
"NoChange": "No Change",
|
||||||
"NoDownloadClientsFound": "No download clients found",
|
"NoDownloadClientsFound": "No download clients found",
|
||||||
|
"NoEventsFound": "No events found",
|
||||||
"NoImportListsFound": "No import lists found",
|
"NoImportListsFound": "No import lists found",
|
||||||
"NoIndexersFound": "No indexers found",
|
"NoIndexersFound": "No indexers found",
|
||||||
|
"NoIssuesWithYourConfiguration": "No issues with your configuration",
|
||||||
|
"NoLeaveIt": "No, Leave It",
|
||||||
|
"NoLogFiles": "No log files",
|
||||||
"NoSeasons": "No seasons",
|
"NoSeasons": "No seasons",
|
||||||
|
"NoUpdatesAreAvailable": "No updates are available",
|
||||||
"OneSeason": "1 season",
|
"OneSeason": "1 season",
|
||||||
|
"OnLatestVersion": "The latest version of Radarr is already installed",
|
||||||
|
"Options": "Options",
|
||||||
"OriginalLanguage": "Original Language",
|
"OriginalLanguage": "Original Language",
|
||||||
|
"PackageVersion": "Package Version",
|
||||||
|
"PackageVersionInfo": "{packageVersion} by {packageAuthor}",
|
||||||
"PartialSeason": "Partial Season",
|
"PartialSeason": "Partial Season",
|
||||||
"Path": "Path",
|
"Path": "Path",
|
||||||
"PreviousAiring": "Previous Airing",
|
"PreviousAiring": "Previous Airing",
|
||||||
|
"PreviouslyInstalled": "Previously Installed",
|
||||||
"Priority": "Priority",
|
"Priority": "Priority",
|
||||||
"Profiles": "Profiles",
|
"Profiles": "Profiles",
|
||||||
"Proper": "Proper",
|
"Proper": "Proper",
|
||||||
|
@ -146,13 +207,17 @@
|
||||||
"Quality": "Quality",
|
"Quality": "Quality",
|
||||||
"QualityProfile": "Quality Profile",
|
"QualityProfile": "Quality Profile",
|
||||||
"Queue": "Queue",
|
"Queue": "Queue",
|
||||||
|
"Queued": "Queued",
|
||||||
|
"ReadTheWikiForMoreInformation": "Read the Wiki for more information",
|
||||||
"Real": "Real",
|
"Real": "Real",
|
||||||
"RecycleBinUnableToWriteHealthCheckMessage": "Unable to write to configured recycling bin folder: {0}. Ensure this path exists and is writable by the user running Sonarr",
|
"RecycleBinUnableToWriteHealthCheckMessage": "Unable to write to configured recycling bin folder: {0}. Ensure this path exists and is writable by the user running Sonarr",
|
||||||
|
"Refresh": "Refresh",
|
||||||
"RefreshSeries": "Refresh Series",
|
"RefreshSeries": "Refresh Series",
|
||||||
"Release": "Release",
|
"Release": "Release",
|
||||||
"ReleaseGroup": "Release Group",
|
"ReleaseGroup": "Release Group",
|
||||||
"ReleaseHash": "Release Hash",
|
"ReleaseHash": "Release Hash",
|
||||||
"ReleaseTitle": "Release Title",
|
"ReleaseTitle": "Release Title",
|
||||||
|
"Reload": "Reload",
|
||||||
"RemotePathMappingBadDockerPathHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.",
|
"RemotePathMappingBadDockerPathHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.",
|
||||||
"RemotePathMappingDockerFolderMissingHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.",
|
"RemotePathMappingDockerFolderMissingHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.",
|
||||||
"RemotePathMappingDownloadPermissionsHealthCheckMessage": "Sonarr can see but not access downloaded episode {0}. Likely permissions error.",
|
"RemotePathMappingDownloadPermissionsHealthCheckMessage": "Sonarr can see but not access downloaded episode {0}. Likely permissions error.",
|
||||||
|
@ -171,6 +236,9 @@
|
||||||
"Remove": "Remove",
|
"Remove": "Remove",
|
||||||
"RemoveCompleted": "Remove Completed",
|
"RemoveCompleted": "Remove Completed",
|
||||||
"RemoveCompletedDownloads": "Remove Completed Downloads",
|
"RemoveCompletedDownloads": "Remove Completed Downloads",
|
||||||
|
"RemovedFromTaskQueue": "Removed from task queue",
|
||||||
|
"RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB",
|
||||||
|
"RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB",
|
||||||
"RemoveFailed": "Remove Failed",
|
"RemoveFailed": "Remove Failed",
|
||||||
"RemoveFailedDownloads": "Remove Failed Downloads",
|
"RemoveFailedDownloads": "Remove Failed Downloads",
|
||||||
"RemoveFromDownloadClient": "Remove From Download Client",
|
"RemoveFromDownloadClient": "Remove From Download Client",
|
||||||
|
@ -179,43 +247,69 @@
|
||||||
"RemoveSelectedItemQueueMessageText": "Are you sure you want to remove 1 item from the queue?",
|
"RemoveSelectedItemQueueMessageText": "Are you sure you want to remove 1 item from the queue?",
|
||||||
"RemoveSelectedItems": "Remove Selected Items",
|
"RemoveSelectedItems": "Remove Selected Items",
|
||||||
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {0} items from the queue?",
|
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {0} items from the queue?",
|
||||||
"RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB",
|
|
||||||
"RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB",
|
|
||||||
"RemovingTag": "Removing tag",
|
"RemovingTag": "Removing tag",
|
||||||
"Repack": "Repack",
|
"Repack": "Repack",
|
||||||
"Replace": "Replace",
|
"Replace": "Replace",
|
||||||
"Required": "Required",
|
"Required": "Required",
|
||||||
|
"Reset": "Reset",
|
||||||
|
"ResetDefinitionTitlesHelpText": "Reset definition titles as well as values",
|
||||||
|
"ResetQualityDefinitions": "Reset Quality Definitions",
|
||||||
|
"ResetQualityDefinitionsMessageText": "Are you sure you want to reset quality definitions?",
|
||||||
|
"ResetTitles": "Reset Titles",
|
||||||
|
"Restart": "Restart",
|
||||||
|
"RestartReloadNote": "Note: Sonarr will automatically restart and reload the UI during the restore process.",
|
||||||
|
"Restore": "Restore",
|
||||||
|
"RestoreBackup": "Restore Backup",
|
||||||
"Result": "Result",
|
"Result": "Result",
|
||||||
"RootFolder": "Root Folder",
|
"RootFolder": "Root Folder",
|
||||||
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
|
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
|
||||||
"RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}",
|
"RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}",
|
||||||
|
"Scheduled": "Scheduled",
|
||||||
"SearchForMonitoredEpisodes": "Search for monitored episodes",
|
"SearchForMonitoredEpisodes": "Search for monitored episodes",
|
||||||
"SeasonNumber": "Season Number",
|
"SeasonNumber": "Season Number",
|
||||||
"Series": "Series",
|
"Series": "Series",
|
||||||
|
"SeriesEditor": "Series Editor",
|
||||||
"SeriesTitle": "Series Title",
|
"SeriesTitle": "Series Title",
|
||||||
"SetTags": "Set Tags",
|
"SetTags": "Set Tags",
|
||||||
"Settings": "Settings",
|
"Settings": "Settings",
|
||||||
"ShowAdvanced": "Show Advanced",
|
"ShowAdvanced": "Show Advanced",
|
||||||
"ShownClickToHide": "Shown, click to hide",
|
"ShownClickToHide": "Shown, click to hide",
|
||||||
|
"Size": "Size",
|
||||||
"SizeOnDisk": "Size on disk",
|
"SizeOnDisk": "Size on disk",
|
||||||
"SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
|
"SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
|
||||||
"SkipRedownload": "Skip Redownload",
|
"SkipRedownload": "Skip Redownload",
|
||||||
"Source": "Source",
|
"Source": "Source",
|
||||||
"Special": "Special",
|
"Special": "Special",
|
||||||
|
"Started": "Started",
|
||||||
|
"StartupDirectory": "Startup directory",
|
||||||
|
"Status": "Status",
|
||||||
"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",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
"Tasks": "Tasks",
|
"Tasks": "Tasks",
|
||||||
|
"TaskUserAgentTooltip": "User-Agent provided by the app that called the API",
|
||||||
|
"TestAll": "Test All",
|
||||||
"TestParsing": "Test Parsing",
|
"TestParsing": "Test Parsing",
|
||||||
|
"TheLogLevelDefault": "The log level defaults to 'Info' and can be changed in [General Settings](/settings/general)",
|
||||||
|
"Time": "Time",
|
||||||
|
"TotalSpace": "Total Space",
|
||||||
|
"Twitter": "Twitter",
|
||||||
"UI": "UI",
|
"UI": "UI",
|
||||||
"UI Language": "UI Language",
|
"UI Language": "UI Language",
|
||||||
|
"UnableToLoadBackups": "Unable to load backups",
|
||||||
|
"UnableToUpdateSonarrDirectly": "Unable to update Sonarr directly,",
|
||||||
"Unmonitored": "Unmonitored",
|
"Unmonitored": "Unmonitored",
|
||||||
"UpdateAvailableHealthCheckMessage": "New update is available",
|
"UpdateAvailableHealthCheckMessage": "New update is available",
|
||||||
|
"UpdaterLogFiles": "Updater Log Files",
|
||||||
|
"Updates": "Updates",
|
||||||
"UpdateStartupNotWritableHealthCheckMessage": "Cannot install update because startup folder '{0}' is not writable by the user '{1}'.",
|
"UpdateStartupNotWritableHealthCheckMessage": "Cannot install update because startup folder '{0}' is not writable by the user '{1}'.",
|
||||||
"UpdateStartupTranslocationHealthCheckMessage": "Cannot install update because startup folder '{0}' is in an App Translocation folder.",
|
"UpdateStartupTranslocationHealthCheckMessage": "Cannot install update because startup folder '{0}' is in an App Translocation folder.",
|
||||||
"UpdateUINotWritableHealthCheckMessage": "Cannot install update because UI folder '{0}' is not writable by the user '{1}'.",
|
"UpdateUINotWritableHealthCheckMessage": "Cannot install update because UI folder '{0}' is not writable by the user '{1}'.",
|
||||||
"Updates": "Updates",
|
"Uptime": "Uptime",
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
"Wanted": "Wanted",
|
"Wanted": "Wanted",
|
||||||
"Yes": "Yes"
|
"Wiki": "Wiki",
|
||||||
|
"WouldYouLikeToRestoreBackup": "Would you like to restore the backup '{name}'?",
|
||||||
|
"Yes": "Yes",
|
||||||
|
"YesCancel": "Yes, Cancel"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
"UI Language": "UI Langue",
|
"UI Language": "UI Langue",
|
||||||
"Language that Sonarr will use for UI": "Langue que Sonarr utilisera pour l'interface utilisateur",
|
"Language that Sonarr will use for UI": "Langue que Sonarr utilisera pour l'interface utilisateur",
|
||||||
"Browser Reload Required": "Rechargement du navigateur requis",
|
"Browser Reload Required": "Rechargement du navigateur requis",
|
||||||
"Added": "Ajouter",
|
"Added": "Ajouté",
|
||||||
"ApiKeyValidationHealthCheckMessage": "Veuillez mettre à jour votre clé API pour qu'elle contienne au moins {0} caractères. Vous pouvez le faire via les paramètres ou le fichier de configuration",
|
"ApiKeyValidationHealthCheckMessage": "Veuillez mettre à jour votre clé API pour qu'elle contienne au moins {0} caractères. Vous pouvez le faire via les paramètres ou le fichier de configuration",
|
||||||
"AppDataLocationHealthCheckMessage": "La mise à jour ne sera pas possible pour empêcher la suppression de AppData lors de la mise à jour",
|
"AppDataLocationHealthCheckMessage": "La mise à jour ne sera pas possible pour empêcher la suppression de AppData lors de la mise à jour",
|
||||||
"ApplyChanges": "Appliquer les modifications",
|
"ApplyChanges": "Appliquer les modifications",
|
||||||
"AutomaticAdd": "Ajout automatique",
|
"AutomaticAdd": "Ajout automatique",
|
||||||
"CountSeasons": "{count} saisons",
|
"CountSeasons": "{count} saisons",
|
||||||
"DownloadClientCheckNoneAvailableHealthCheckMessage": "Aucun client de téléchargement disponible"
|
"DownloadClientCheckNoneAvailableHealthCheckMessage": "Aucun client de téléchargement disponible",
|
||||||
|
"Add": "Ajouter",
|
||||||
|
"AddingTag": "Ajout d'un tag",
|
||||||
|
"Apply": "Appliquer",
|
||||||
|
"ApplyTags": "Appliquer les tags"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
"Added": "נוסף",
|
"Added": "נוסף",
|
||||||
"ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה API שלך שיהיה עם לפחות {0} תווים. ניתן לעשות זאת דרך ההגדות או קובץ הקונפיגורציה"
|
"ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה־API שלך כדי שיהיה באורך של לפחות {0} תווים. תוכל לעשות זאת בהגדרות או דרך קובץ הקונפיגורציה.",
|
||||||
|
"Add": "הוסף",
|
||||||
|
"Activity": "פעילות"
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
"DownloadClientStatusSingleClientHealthCheckMessage": "Letöltési kliensek elérhetetlenek meghibásodások miatt: {0}",
|
"DownloadClientStatusSingleClientHealthCheckMessage": "Letöltési kliensek elérhetetlenek meghibásodások miatt: {0}",
|
||||||
"EnableAutomaticSearch": "Automatikus keresés engedélyezése",
|
"EnableAutomaticSearch": "Automatikus keresés engedélyezése",
|
||||||
"EditSeries": "Sorozat szerkesztése",
|
"EditSeries": "Sorozat szerkesztése",
|
||||||
"EnableRss": "RSS engedélyezése",
|
|
||||||
"EnableInteractiveSearch": "Interaktív keresés engedélyezése",
|
"EnableInteractiveSearch": "Interaktív keresés engedélyezése",
|
||||||
"Ended": "Vége",
|
"Ended": "Vége",
|
||||||
"HideAdvanced": "Haladó elrejtése",
|
"HideAdvanced": "Haladó elrejtése",
|
||||||
|
|
|
@ -1,3 +1,41 @@
|
||||||
{
|
{
|
||||||
"Added": "Ditambahkan"
|
"Added": "Ditambahkan",
|
||||||
|
"BlocklistReleaseHelpText": "Mencegah Sonarr memperoleh rilis ini secara otomatis",
|
||||||
|
"Delete": "Hapus",
|
||||||
|
"Close": "Tutup",
|
||||||
|
"Language that Sonarr will use for UI": "Bahasa yang digunakan UI Sonarr",
|
||||||
|
"EnableAutomaticSearch": "Aktifkan Penelusuran Otomatis",
|
||||||
|
"EnableInteractiveSearch": "Aktifkan Penelusuran Interaktif",
|
||||||
|
"Enabled": "Aktif",
|
||||||
|
"Language": "Bahasa",
|
||||||
|
"Network": "Jaringan",
|
||||||
|
"NextAiring": "Tayang Selanjutnya",
|
||||||
|
"Monitored": "Dimonitor",
|
||||||
|
"Path": "Path",
|
||||||
|
"PreviousAiring": "Sebelumnya Tayang",
|
||||||
|
"OriginalLanguage": "Bahasa Asli",
|
||||||
|
"Priority": "Prioritas",
|
||||||
|
"ProxyFailedToTestHealthCheckMessage": "Gagal menguji proxy: {0}",
|
||||||
|
"ProxyBadRequestHealthCheckMessage": "Gagal menguji proxy. Kode Status: {0}",
|
||||||
|
"QualityProfile": "Profil Kualitas",
|
||||||
|
"Add": "Tambah",
|
||||||
|
"Cancel": "Batal",
|
||||||
|
"NoSeasons": "Tidak ada musim",
|
||||||
|
"OneSeason": "1 musim",
|
||||||
|
"Disabled": "Nonaktif",
|
||||||
|
"Activity": "Aktivitas",
|
||||||
|
"Calendar": "Kalender",
|
||||||
|
"EnableRSS": "Aktifkan RSS",
|
||||||
|
"Ended": "Berakhir",
|
||||||
|
"LibraryImport": "Impor Pustaka",
|
||||||
|
"LogFiles": "Berkas Log",
|
||||||
|
"MediaManagement": "Pengelolaan Media",
|
||||||
|
"Metadata": "Metadata",
|
||||||
|
"MetadataSource": "Sumber Metadata",
|
||||||
|
"Name": "Nama",
|
||||||
|
"No": "Tidak",
|
||||||
|
"NoChange": "Tidak Ada Perubahan",
|
||||||
|
"Profiles": "Profil",
|
||||||
|
"Quality": "Kualitas",
|
||||||
|
"Queue": "Antrean"
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
"DownloadClientStatusAllClientHealthCheckMessage": "Todos os clientes de download estão indisponíveis devido a falhas",
|
"DownloadClientStatusAllClientHealthCheckMessage": "Todos os clientes de download estão indisponíveis devido a falhas",
|
||||||
"EditSelectedDownloadClients": "Editar clientes de download selecionados",
|
"EditSelectedDownloadClients": "Editar clientes de download selecionados",
|
||||||
"EditSelectedImportLists": "Editar listas de importação selecionadas",
|
"EditSelectedImportLists": "Editar listas de importação selecionadas",
|
||||||
"EnableRss": "Ativar Rss",
|
|
||||||
"Enabled": "Habilitado",
|
"Enabled": "Habilitado",
|
||||||
"Ended": "Terminou",
|
"Ended": "Terminou",
|
||||||
"HideAdvanced": "Ocultar Avançado",
|
"HideAdvanced": "Ocultar Avançado",
|
||||||
|
@ -92,14 +91,14 @@
|
||||||
"UpdateStartupNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' não pode ser gravada pelo usuário '{1}'.",
|
"UpdateStartupNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' não pode ser gravada pelo usuário '{1}'.",
|
||||||
"UpdateStartupTranslocationHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta de translocação de aplicativo.",
|
"UpdateStartupTranslocationHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta de translocação de aplicativo.",
|
||||||
"BlocklistReleaseHelpText": "Impede que o Sonarr pegue automaticamente esta versão novamente",
|
"BlocklistReleaseHelpText": "Impede que o Sonarr pegue automaticamente esta versão novamente",
|
||||||
"BlocklistReleases": "Lista de Bloqueio de Lançamentos",
|
"BlocklistReleases": "Lançamentos na lista de bloqueio",
|
||||||
"CloneCondition": "Condição de Clone",
|
"CloneCondition": "Condição de clone",
|
||||||
"CloneCustomFormat": "Clonar Formato Personalizado",
|
"CloneCustomFormat": "Clonar formato personalizado",
|
||||||
"Close": "Fechar",
|
"Close": "Fechar",
|
||||||
"Delete": "Excluir",
|
"Delete": "Excluir",
|
||||||
"DeleteCondition": "Excluir Condição",
|
"DeleteCondition": "Excluir condição",
|
||||||
"DeleteConditionMessageText": "Tem certeza de que deseja excluir a condição '{0}'?",
|
"DeleteConditionMessageText": "Tem certeza de que deseja excluir a condição '{0}'?",
|
||||||
"DeleteCustomFormat": "Excluir Formato Personalizado",
|
"DeleteCustomFormat": "Excluir formato personalizado",
|
||||||
"DeleteCustomFormatMessageText": "Tem certeza de que deseja excluir o formato personalizado '{0}'?",
|
"DeleteCustomFormatMessageText": "Tem certeza de que deseja excluir o formato personalizado '{0}'?",
|
||||||
"ExportCustomFormat": "Exportar Formato Personalizado",
|
"ExportCustomFormat": "Exportar Formato Personalizado",
|
||||||
"Negated": "Negado",
|
"Negated": "Negado",
|
||||||
|
@ -111,5 +110,109 @@
|
||||||
"RemoveSelectedItems": "Remover Itens Selecionados",
|
"RemoveSelectedItems": "Remover Itens Selecionados",
|
||||||
"RemoveSelectedItemsQueueMessageText": "Tem certeza de que deseja remover {0} itens da fila?",
|
"RemoveSelectedItemsQueueMessageText": "Tem certeza de que deseja remover {0} itens da fila?",
|
||||||
"Required": "Requerido",
|
"Required": "Requerido",
|
||||||
"BlocklistRelease": "Lista de Bloqueio de Lançamentos"
|
"BlocklistRelease": "Lançamento na lista de bloqueio",
|
||||||
|
"Add": "Adicionar",
|
||||||
|
"AddingTag": "Adicionar tag",
|
||||||
|
"Apply": "Aplicar",
|
||||||
|
"ApplyTags": "Aplicar Tags",
|
||||||
|
"Cancel": "Cancelar",
|
||||||
|
"CountDownloadClientsSelected": "{count} cliente(s) de download selecionado(s)",
|
||||||
|
"CountImportListsSelected": "{count} lista(s) de importação selecionada(s)",
|
||||||
|
"CountIndexersSelected": "{count} indexador(es) selecionado(s)",
|
||||||
|
"DeleteSelectedDownloadClients": "Excluir cliente(s) de download",
|
||||||
|
"DeleteSelectedImportLists": "Excluir lista(s) de importação",
|
||||||
|
"DeleteSelectedIndexers": "Excluir indexador(es)",
|
||||||
|
"DeleteSelectedDownloadClientsMessageText": "Tem certeza de que deseja excluir {count} cliente(s) de download selecionado(s)?",
|
||||||
|
"DeleteSelectedImportListsMessageText": "Tem certeza de que deseja excluir {count} lista(s) de importação selecionada(s)?",
|
||||||
|
"ExistingTag": "Etiqueta existente",
|
||||||
|
"Implementation": "Implementação",
|
||||||
|
"Disabled": "Desabilitado",
|
||||||
|
"Edit": "Editar",
|
||||||
|
"EnableRSS": "Habilitar RSS",
|
||||||
|
"ManageClients": "Gerenciar clientes",
|
||||||
|
"ManageIndexers": "Gerenciar indexadores",
|
||||||
|
"ManageDownloadClients": "Gerenciar clientes de download",
|
||||||
|
"ManageImportLists": "Gerenciar listas de importação",
|
||||||
|
"No": "Não",
|
||||||
|
"ManageLists": "Gerenciar listas",
|
||||||
|
"Name": "Nome",
|
||||||
|
"NoChange": "Sem alteração",
|
||||||
|
"NoDownloadClientsFound": "Nenhum cliente de download encontrado",
|
||||||
|
"NoImportListsFound": "Nenhuma lista de importação encontrada",
|
||||||
|
"NoIndexersFound": "Nenhum indexador encontrado",
|
||||||
|
"RemoveFailed": "Falha na remoção",
|
||||||
|
"Replace": "Substituir",
|
||||||
|
"Result": "Resultado",
|
||||||
|
"SetTags": "Definir etiquetas",
|
||||||
|
"Yes": "Sim",
|
||||||
|
"Tags": "Tags",
|
||||||
|
"AutoAdd": "Adicionar automaticamente",
|
||||||
|
"RemovingTag": "Removendo etiqueta",
|
||||||
|
"DeleteSelectedIndexersMessageText": "Tem certeza de que deseja excluir {count} indexadores selecionados?",
|
||||||
|
"RemoveCompleted": "Remoção Concluída",
|
||||||
|
"LibraryImport": "Importar para biblioteca",
|
||||||
|
"LogFiles": "Arquivos de registro",
|
||||||
|
"MediaManagement": "Gerenciamento de Mídia",
|
||||||
|
"Metadata": "Metadados",
|
||||||
|
"MetadataSource": "Fonte de Metadados",
|
||||||
|
"Missing": "Ausente",
|
||||||
|
"Profiles": "Perfis",
|
||||||
|
"Quality": "Qualidade",
|
||||||
|
"Queue": "Fila",
|
||||||
|
"Series": "Séries",
|
||||||
|
"Settings": "Configurações",
|
||||||
|
"System": "Sistema",
|
||||||
|
"Tasks": "Tarefas",
|
||||||
|
"UI": "UI",
|
||||||
|
"Updates": "Atualizações",
|
||||||
|
"Wanted": "Procurado",
|
||||||
|
"ApplyTagsHelpTextHowToApply": "Como aplicar tags nos indexadores selecionados",
|
||||||
|
"ApplyTagsHelpTextAdd": "Adicionar: adicione as etiquetas à lista existente de etiquetas",
|
||||||
|
"ApplyTagsHelpTextReplace": "Substituir: Substitua as etiquetas pelas etiquetas inseridas (não digite nenhuma etiqueta para limpar todas as etiquetas)",
|
||||||
|
"ApplyTagsHelpTextRemove": "Remover: remove as etiquetas inseridas",
|
||||||
|
"CustomFormatScore": "Pontuação do formato personalizado",
|
||||||
|
"Activity": "Atividade",
|
||||||
|
"AddNew": "Adicionar Novo",
|
||||||
|
"Backup": "Backup",
|
||||||
|
"Blocklist": "Lista de Bloqueio",
|
||||||
|
"Calendar": "Calendário",
|
||||||
|
"Connect": "Conectar",
|
||||||
|
"CustomFormats": "Formatos personalizados",
|
||||||
|
"CutoffUnmet": "Corte não alcançado",
|
||||||
|
"DownloadClients": "Clientes de download",
|
||||||
|
"Events": "Eventos",
|
||||||
|
"General": "Geral",
|
||||||
|
"History": "Histórico",
|
||||||
|
"ImportLists": "Listas de importação",
|
||||||
|
"Indexers": "Indexadores",
|
||||||
|
"AbsoluteEpisodeNumbers": "Número(s) absoluto(s) do episódio",
|
||||||
|
"AirDate": "Data de Exibição",
|
||||||
|
"Daily": "Diário",
|
||||||
|
"Details": "Detalhes",
|
||||||
|
"AllTitles": "Todos os Títulos",
|
||||||
|
"Version": "Versão",
|
||||||
|
"ApplyTagsHelpTextHowToApplyDownloadClients": "Como aplicar tags aos clientes de download selecionados",
|
||||||
|
"ApplyTagsHelpTextHowToApplyImportLists": "Como aplicar tags às listas de importação selecionadas",
|
||||||
|
"ApplyTagsHelpTextHowToApplyIndexers": "Como aplicar tags aos indexadores selecionados",
|
||||||
|
"ApplyTagsHelpTextHowToApplySeries": "Como aplicar tags à série selecionada",
|
||||||
|
"EpisodeInfo": "Info do Episódio",
|
||||||
|
"EpisodeNumbers": "Número(s) do(s) Episódio(s)",
|
||||||
|
"FullSeason": "Temporada Completa",
|
||||||
|
"Languages": "Idiomas",
|
||||||
|
"MatchedToEpisodes": "Correspondente aos Episódios",
|
||||||
|
"MatchedToSeason": "Correspondente a Temporada",
|
||||||
|
"MatchedToSeries": "Correspondente à Série",
|
||||||
|
"MultiSeason": "Multi-Temporada",
|
||||||
|
"PartialSeason": "Temporada Parcial",
|
||||||
|
"Proper": "Proper",
|
||||||
|
"Real": "Real",
|
||||||
|
"Release": "Lançamento",
|
||||||
|
"ReleaseGroup": "Grupo do Lançamento",
|
||||||
|
"ReleaseHash": "Hash do Lançamento",
|
||||||
|
"ReleaseTitle": "Título do Lançamento",
|
||||||
|
"Repack": "Repack",
|
||||||
|
"SeasonNumber": "Número da Temporada",
|
||||||
|
"SeriesTitle": "Título da Série",
|
||||||
|
"Special": "Especial",
|
||||||
|
"TestParsing": "Análise de Teste"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
"EditSeries": "Редактировать серию",
|
"EditSeries": "Редактировать серию",
|
||||||
"EnableAutomaticSearch": "Включить автоматический поиск",
|
"EnableAutomaticSearch": "Включить автоматический поиск",
|
||||||
"EnableInteractiveSearch": "Включить интерактивный поиск",
|
"EnableInteractiveSearch": "Включить интерактивный поиск",
|
||||||
"EnableRss": "Включить RSS",
|
|
||||||
"Enabled": "Включено",
|
"Enabled": "Включено",
|
||||||
"HiddenClickToShow": "Скрыто, нажмите чтобы показать",
|
"HiddenClickToShow": "Скрыто, нажмите чтобы показать",
|
||||||
"HideAdvanced": "Скрыть расширенные",
|
"HideAdvanced": "Скрыть расширенные",
|
||||||
|
|
|
@ -3,5 +3,38 @@
|
||||||
"DeleteCondition": "删除条件",
|
"DeleteCondition": "删除条件",
|
||||||
"DeleteConditionMessageText": "是否确实要删除条件“{0}”?",
|
"DeleteConditionMessageText": "是否确实要删除条件“{0}”?",
|
||||||
"DeleteCustomFormatMessageText": "是否确实要删除条件“{0}”?",
|
"DeleteCustomFormatMessageText": "是否确实要删除条件“{0}”?",
|
||||||
"ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作"
|
"ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作",
|
||||||
|
"RemoveSelectedItemQueueMessageText": "您确定要从队列中删除 1 项吗?",
|
||||||
|
"RemoveSelectedItemsQueueMessageText": "您确定要从队列中删除 {0} 个项目吗?",
|
||||||
|
"ApplyChanges": "应用更改",
|
||||||
|
"AutomaticAdd": "自动添加",
|
||||||
|
"Browser Reload Required": "需要重新加载浏览器",
|
||||||
|
"EditSelectedDownloadClients": "编辑选定的下载客户端",
|
||||||
|
"EditSelectedIndexers": "编辑选定的索引器",
|
||||||
|
"EditSelectedImportLists": "编辑选定的导入列表",
|
||||||
|
"HiddenClickToShow": "隐藏,点击显示",
|
||||||
|
"HideAdvanced": "隐藏高级",
|
||||||
|
"Language": "语言",
|
||||||
|
"RemoveCompletedDownloads": "删除已完成的下载",
|
||||||
|
"RemoveFailedDownloads": "删除失败的下载",
|
||||||
|
"ShowAdvanced": "显示高级",
|
||||||
|
"ShownClickToHide": "显示,点击隐藏",
|
||||||
|
"UI Language": "用户界面语言",
|
||||||
|
"DeleteSelectedDownloadClients": "删除下载客户端",
|
||||||
|
"DeleteSelectedImportLists": "删除导入列表",
|
||||||
|
"DeleteSelectedIndexers": "删除索引器",
|
||||||
|
"Implementation": "执行",
|
||||||
|
"ManageClients": "管理客户",
|
||||||
|
"ManageDownloadClients": "管理下载客户端",
|
||||||
|
"ManageImportLists": "管理导入列表",
|
||||||
|
"ManageIndexers": "管理索引器",
|
||||||
|
"ManageLists": "管理列表",
|
||||||
|
"NoDownloadClientsFound": "找不到下载客户端",
|
||||||
|
"NoImportListsFound": "未找到导入列表",
|
||||||
|
"NoIndexersFound": "未找到索引器",
|
||||||
|
"Added": "已添加",
|
||||||
|
"Add": "添加",
|
||||||
|
"AddingTag": "添加标签",
|
||||||
|
"Apply": "应用",
|
||||||
|
"ApplyTags": "应用标签"
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,12 +101,12 @@ namespace NzbDrone.Core.RemotePathMappings
|
||||||
|
|
||||||
if (remotePath.IsEmpty)
|
if (remotePath.IsEmpty)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Invalid RemotePath");
|
throw new ArgumentException("Invalid RemotePath. RemotePath cannot be empty.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localPath.IsEmpty || !localPath.IsRooted)
|
if (localPath.IsEmpty || !localPath.IsRooted)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Invalid LocalPath");
|
throw new ArgumentException("Invalid LocalPath. LocalPath cannot be empty and must not be the root.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_diskProvider.FolderExists(localPath.FullPath))
|
if (!_diskProvider.FolderExists(localPath.FullPath))
|
||||||
|
@ -116,7 +116,7 @@ namespace NzbDrone.Core.RemotePathMappings
|
||||||
|
|
||||||
if (existing.Exists(r => r.Host == mapping.Host && r.RemotePath == mapping.RemotePath))
|
if (existing.Exists(r => r.Host == mapping.Host && r.RemotePath == mapping.RemotePath))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("RemotePath already mounted.");
|
throw new InvalidOperationException("RemotePath already configured.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,11 +127,14 @@ namespace NzbDrone.Core.RemotePathMappings
|
||||||
return remotePath;
|
return remotePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.Trace("Evaluating remote path remote mappings for match to host [{0}] and remote path [{1}]", host, remotePath.FullPath);
|
||||||
foreach (var mapping in All())
|
foreach (var mapping in All())
|
||||||
{
|
{
|
||||||
|
_logger.Trace("Checking configured remote path mapping: {0} - {1}", mapping.Host, mapping.RemotePath);
|
||||||
if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.RemotePath).Contains(remotePath))
|
if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.RemotePath).Contains(remotePath))
|
||||||
{
|
{
|
||||||
var localPath = new OsPath(mapping.LocalPath) + (remotePath - new OsPath(mapping.RemotePath));
|
var localPath = new OsPath(mapping.LocalPath) + (remotePath - new OsPath(mapping.RemotePath));
|
||||||
|
_logger.Debug("Remapped remote path [{0}] to local path [{1}] for host [{2}]", remotePath, localPath, host);
|
||||||
|
|
||||||
return localPath;
|
return localPath;
|
||||||
}
|
}
|
||||||
|
@ -147,11 +150,14 @@ namespace NzbDrone.Core.RemotePathMappings
|
||||||
return localPath;
|
return localPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.Trace("Evaluating remote path local mappings for match to host [{0}] and local path [{1}]", host, localPath.FullPath);
|
||||||
foreach (var mapping in All())
|
foreach (var mapping in All())
|
||||||
{
|
{
|
||||||
|
_logger.Trace("Checking configured remote path mapping {0} - {1}", mapping.Host, mapping.RemotePath);
|
||||||
if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.LocalPath).Contains(localPath))
|
if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.LocalPath).Contains(localPath))
|
||||||
{
|
{
|
||||||
var remotePath = new OsPath(mapping.RemotePath) + (localPath - new OsPath(mapping.LocalPath));
|
var remotePath = new OsPath(mapping.RemotePath) + (localPath - new OsPath(mapping.LocalPath));
|
||||||
|
_logger.Debug("Remapped local path [{0}] to remote path [{1}] for host [{2}]", localPath, remotePath, host);
|
||||||
|
|
||||||
return remotePath;
|
return remotePath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3327,18 +3327,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/initialize.js": {
|
|
||||||
"get": {
|
|
||||||
"tags": [
|
|
||||||
"InitializeJs"
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Success"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/v3/language": {
|
"/api/v3/language": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
@ -9025,6 +9013,10 @@
|
||||||
},
|
},
|
||||||
"nullable": true
|
"nullable": true
|
||||||
},
|
},
|
||||||
|
"customFormatScore": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
"rejections": {
|
"rejections": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|
Loading…
Reference in New Issue