Feature/translate ml - jobs(part 2) (#25528)

Translate ml -> jobs - jobs-list(part_2)
This commit is contained in:
Nox911 2018-12-10 19:22:42 +03:00 committed by pavel06081991
parent 7b688066a8
commit d86996be01
7 changed files with 292 additions and 82 deletions

View file

@ -26,11 +26,16 @@ import { toastNotifications } from 'ui/notify';
import { loadFullJob } from '../utils';
import { mlCreateWatchService } from '../../../../jobs/new_job/simple/components/watcher/create_watch_service';
import { CreateWatch } from '../../../../jobs/new_job/simple/components/watcher/create_watch_view';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
function getSuccessToast(id, url) {
function getSuccessToast(id, url, intl) {
return {
title: `Watch ${id} created successfully`,
title: intl.formatMessage({
id: 'xpack.ml.jobsList.createWatchFlyout.watchCreatedSuccessfullyNotificationMessage',
defaultMessage: 'Watch {id} created successfully' },
{ id }
),
text: (
<React.Fragment>
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
@ -41,7 +46,10 @@ function getSuccessToast(id, url) {
target="_blank"
iconType="link"
>
Edit watch
{intl.formatMessage({
id: 'xpack.ml.jobsList.createWatchFlyout.editWatchButtonLabel',
defaultMessage: 'Edit watch' }
)}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
@ -50,7 +58,7 @@ function getSuccessToast(id, url) {
};
}
export class CreateWatchFlyout extends Component {
class CreateWatchFlyoutUI extends Component {
constructor(props) {
super(props);
@ -95,13 +103,17 @@ export class CreateWatchFlyout extends Component {
}
save = () => {
const { intl } = this.props;
mlCreateWatchService.createNewWatch(this.state.jobId)
.then((resp) => {
toastNotifications.addSuccess(getSuccessToast(resp.id, resp.url));
toastNotifications.addSuccess(getSuccessToast(resp.id, resp.url, intl));
this.closeFlyout();
})
.catch((error) => {
toastNotifications.addDanger(`Could not save watch`);
toastNotifications.addDanger(intl.formatMessage({
id: 'xpack.ml.jobsList.createWatchFlyout.watchNotSavedErrorNotificationMessage',
defaultMessage: 'Could not save watch'
}));
console.error(error);
});
}
@ -125,7 +137,11 @@ export class CreateWatchFlyout extends Component {
<EuiFlyoutHeader>
<EuiTitle>
<h2>
Create watch for {jobId}
<FormattedMessage
id="xpack.ml.jobsList.createWatchFlyout.pageTitle"
defaultMessage="Create watch for {jobId}"
values={{ jobId }}
/>
</h2>
</EuiTitle>
</EuiFlyoutHeader>
@ -145,7 +161,10 @@ export class CreateWatchFlyout extends Component {
onClick={this.closeFlyout}
flush="left"
>
Close
<FormattedMessage
id="xpack.ml.jobsList.createWatchFlyout.closeButtonLabel"
defaultMessage="Close"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
@ -153,7 +172,10 @@ export class CreateWatchFlyout extends Component {
onClick={this.save}
fill
>
Save
<FormattedMessage
id="xpack.ml.jobsList.createWatchFlyout.saveButtonLabel"
defaultMessage="Save"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
@ -169,8 +191,9 @@ export class CreateWatchFlyout extends Component {
}
}
CreateWatchFlyout.propTypes = {
CreateWatchFlyoutUI.propTypes = {
setShowFunction: PropTypes.func.isRequired,
unsetShowFunction: PropTypes.func.isRequired,
};
export const CreateWatchFlyout = injectI18n(CreateWatchFlyoutUI);

View file

@ -7,6 +7,7 @@
import { detectorToString } from 'plugins/ml/util/string_utils';
import { formatValues, filterObjects } from './format_values';
import { i18n } from '@kbn/i18n';
export function extractJobDetails(job) {
@ -15,14 +16,18 @@ export function extractJobDetails(job) {
}
const general = {
title: 'General',
title: i18n.translate('xpack.ml.jobsList.jobDetails.generalTitle', {
defaultMessage: 'General'
}),
position: 'left',
items: filterObjects(job, true).map(formatValues)
};
const customUrl = {
title: 'Custom URLs',
title: i18n.translate('xpack.ml.jobsList.jobDetails.customUrlsTitle', {
defaultMessage: 'Custom URLs'
}),
position: 'right',
items: []
};
@ -31,7 +36,9 @@ export function extractJobDetails(job) {
}
const node = {
title: 'Node',
title: i18n.translate('xpack.ml.jobsList.jobDetails.nodeTitle', {
defaultMessage: 'Node'
}),
position: 'right',
items: []
};
@ -40,7 +47,9 @@ export function extractJobDetails(job) {
}
const detectors = {
title: 'Detectors',
title: i18n.translate('xpack.ml.jobsList.jobDetails.detectorsTitle', {
defaultMessage: 'Detectors'
}),
position: 'left',
items: []
};
@ -55,31 +64,41 @@ export function extractJobDetails(job) {
}
const influencers = {
title: 'Influencers',
title: i18n.translate('xpack.ml.jobsList.jobDetails.influencersTitle', {
defaultMessage: 'Influencers'
}),
position: 'left',
items: job.analysis_config.influencers.map(i => ['', i])
};
const analysisConfig = {
title: 'Analysis config',
title: i18n.translate('xpack.ml.jobsList.jobDetails.analysisConfigTitle', {
defaultMessage: 'Analysis config'
}),
position: 'left',
items: filterObjects(job.analysis_config)
};
const analysisLimits = {
title: 'Analysis limits',
title: i18n.translate('xpack.ml.jobsList.jobDetails.analysisLimitsTitle', {
defaultMessage: 'Analysis limits'
}),
position: 'left',
items: filterObjects(job.analysis_limits)
};
const dataDescription = {
title: 'Data description',
title: i18n.translate('xpack.ml.jobsList.jobDetails.dataDescriptionTitle', {
defaultMessage: 'Data description'
}),
position: 'right',
items: filterObjects(job.data_description)
};
const datafeed = {
title: 'Datafeed',
title: i18n.translate('xpack.ml.jobsList.jobDetails.datafeedTitle', {
defaultMessage: 'Datafeed'
}),
position: 'left',
items: filterObjects(job.datafeed_config, true, true)
};
@ -88,13 +107,17 @@ export function extractJobDetails(job) {
}
const counts = {
title: 'Counts',
title: i18n.translate('xpack.ml.jobsList.jobDetails.countsTitle', {
defaultMessage: 'Counts'
}),
position: 'left',
items: filterObjects(job.data_counts).map(formatValues)
};
const modelSizeStats = {
title: 'Model size stats',
title: i18n.translate('xpack.ml.jobsList.jobDetails.modelSizeStatsTitle', {
defaultMessage: 'Model size stats'
}),
position: 'right',
items: filterObjects(job.model_size_stats).map(formatValues)
};

View file

@ -28,6 +28,7 @@ import chrome from 'ui/chrome';
import { FORECAST_REQUEST_STATE } from 'plugins/ml/../common/constants/states';
import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed';
import { mlForecastService } from 'plugins/ml/services/forecast_service';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
const MAX_FORECASTS = 500;
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
@ -35,7 +36,7 @@ const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
/**
* Table component for rendering the lists of forecasts run on an ML job.
*/
class ForecastsTable extends Component {
class ForecastsTableUI extends Component {
constructor(props) {
super(props);
this.state = {
@ -63,7 +64,10 @@ class ForecastsTable extends Component {
console.log('Error loading list of forecasts for jobs list:', resp);
this.setState({
isLoading: false,
errorMessage: 'Error loading the list of forecasts run on this job',
errorMessage: this.props.intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.loadingErrorMessage',
defaultMessage: 'Error loading the list of forecasts run on this job'
}),
forecasts: []
});
});
@ -150,65 +154,110 @@ class ForecastsTable extends Component {
if (forecasts.length === 0) {
return (
<EuiCallOut
title="No forecasts have been run for this job"
title={(<FormattedMessage
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsTitle"
defaultMessage="No forecasts have been run for this job"
/>)}
iconType="iInCircle"
>
<p>
To run a forecast,
open the <EuiLink onClick={() => this.openSingleMetricView()}>Single Metric Viewer</EuiLink>
<FormattedMessage
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsDescription"
defaultMessage="To run a forecast, open the {singleMetricViewerLink}"
values={{
singleMetricViewerLink: (
<EuiLink onClick={() => this.openSingleMetricView()}>
<FormattedMessage
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsDescription.linkText"
defaultMessage="Single Metric Viewer"
/>
</EuiLink>
)
}}
/>
</p>
</EuiCallOut>
);
}
const { intl } = this.props;
const columns = [
{
field: 'forecast_create_timestamp',
name: 'Created',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.createdLabel',
defaultMessage: 'Created'
}),
dataType: 'date',
render: (date) => formatDate(date, TIME_FORMAT),
sortable: true
},
{
field: 'forecast_start_timestamp',
name: 'From',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.fromLabel',
defaultMessage: 'From'
}),
dataType: 'date',
render: (date) => formatDate(date, TIME_FORMAT),
sortable: true
},
{
field: 'forecast_end_timestamp',
name: 'To',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.toLabel',
defaultMessage: 'To'
}),
dataType: 'date',
render: (date) => formatDate(date, TIME_FORMAT),
sortable: true
},
{
field: 'forecast_status',
name: 'Status',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.statusLabel',
defaultMessage: 'Status'
}),
sortable: true
},
{
field: 'forecast_memory_bytes',
name: 'Memory size',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.memorySizeLabel',
defaultMessage: 'Memory size'
}),
render: (bytes) => formatNumber(bytes, '0b'),
sortable: true
},
{
field: 'processing_time_ms',
name: 'Processing time',
render: (ms) => `${ms} ms`,
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.processingTimeLabel',
defaultMessage: 'Processing time'
}),
render: (ms) => intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.msTimeUnitLabel',
defaultMessage: '{ms} ms' }, {
ms
}),
sortable: true
},
{
field: 'forecast_expiry_timestamp',
name: 'Expires',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.expiresLabel',
defaultMessage: 'Expires'
}),
render: (date) => formatDate(date, TIME_FORMAT),
sortable: true
},
{
field: 'forecast_messages',
name: 'Messages',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.messagesLabel',
defaultMessage: 'Messages'
}),
sortable: false,
render: (messages) => {
return (
@ -221,7 +270,10 @@ class ForecastsTable extends Component {
}
},
{
name: 'View',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.viewLabel',
defaultMessage: 'View'
}),
render: (forecast) => (
<EuiButton
onClick={() => this.openSingleMetricView(forecast)}
@ -247,8 +299,10 @@ class ForecastsTable extends Component {
);
}
}
ForecastsTable.propTypes = {
ForecastsTableUI.propTypes = {
job: PropTypes.object.isRequired,
};
const ForecastsTable = injectI18n(ForecastsTableUI);
export { ForecastsTable };

View file

@ -21,8 +21,9 @@ import { DatafeedPreviewPane } from './datafeed_preview_tab';
import { ForecastsTable } from './forecasts_table';
import { JobDetailsPane } from './job_details_pane';
import { JobMessagesPane } from './job_messages_pane';
import { injectI18n } from '@kbn/i18n/react';
export class JobDetails extends Component {
class JobDetailsUI extends Component {
constructor(props) {
super(props);
@ -63,38 +64,64 @@ export class JobDetails extends Component {
modelSizeStats
} = extractJobDetails(job);
const { intl } = this.props;
const tabs = [{
id: 'job-settings',
name: 'Job settings',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.jobSettingsLabel',
defaultMessage: 'Job settings'
}),
content: <JobDetailsPane sections={[general, customUrl, node]} />,
time: job.open_time
}, {
id: 'job-config',
name: 'Job config',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.jobConfigLabel',
defaultMessage: 'Job config'
}),
content: <JobDetailsPane sections={[detectors, influencers, analysisConfig, analysisLimits, dataDescription]} />,
}, {
id: 'datafeed',
name: 'Datafeed',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.datafeedLabel',
defaultMessage: 'Datafeed'
}),
content: <JobDetailsPane sections={[datafeed]} />,
}, {
id: 'counts',
name: 'Counts',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.countsLabel',
defaultMessage: 'Counts'
}),
content: <JobDetailsPane sections={[counts, modelSizeStats]} />,
}, {
id: 'json',
name: 'JSON',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.jsonLabel',
defaultMessage: 'JSON'
}),
content: <JsonPane job={job} />,
}, {
id: 'job-messages',
name: 'Job messages',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.jobMessagesLabel',
defaultMessage: 'Job messages'
}),
content: <JobMessagesPane job={job} />,
}, {
id: 'datafeed-preview',
name: 'Datafeed preview',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.datafeedPreviewLabel',
defaultMessage: 'Datafeed preview'
}),
content: <DatafeedPreviewPane job={job} />,
}, {
id: 'forecasts',
name: 'Forecasts',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.tabs.forecastsLabel',
defaultMessage: 'Forecasts'
}),
content: <ForecastsTable job={job} />,
}
];
@ -111,9 +138,11 @@ export class JobDetails extends Component {
}
}
}
JobDetails.propTypes = {
JobDetailsUI.propTypes = {
jobId: PropTypes.string.isRequired,
job: PropTypes.object,
addYourself: PropTypes.func.isRequired,
removeYourself: PropTypes.func.isRequired,
};
export const JobDetails = injectI18n(JobDetailsUI);

View file

@ -18,10 +18,11 @@ import {
import { formatDate } from '@elastic/eui/lib/services/format';
import { ml } from 'plugins/ml/services/ml_api_service';
import { JobIcon } from '../job_message_icon';
import { injectI18n } from '@kbn/i18n/react';
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
export class JobMessagesPane extends Component {
class JobMessagesPaneUI extends Component {
constructor(props) {
super(props);
@ -44,18 +45,28 @@ export class JobMessagesPane extends Component {
render() {
const { messages } = this.state;
const { intl } = this.props;
const columns = [{
name: '',
render: item => (<JobIcon message={item} />)
}, {
name: 'Time',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.messagesPane.timeLabel',
defaultMessage: 'Time'
}),
render: item => formatDate(item.timestamp, TIME_FORMAT)
}, {
field: 'node_name',
name: 'Node',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.messagesPane.nodeLabel',
defaultMessage: 'Node'
}),
}, {
field: 'message',
name: 'Message',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobDetails.messagesPane.messageLabel',
defaultMessage: 'Message'
}),
}
];
return (
@ -71,7 +82,8 @@ export class JobMessagesPane extends Component {
);
}
}
JobMessagesPane.propTypes = {
JobMessagesPaneUI.propTypes = {
job: PropTypes.object.isRequired,
};
export const JobMessagesPane = injectI18n(JobMessagesPaneUI);

View file

@ -20,6 +20,7 @@ import {
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
function loadGroups() {
return ml.jobs.groups()
@ -28,7 +29,14 @@ function loadGroups() {
value: g.id,
view: (
<div className="group-item">
<JobGroup name={g.id} /> <span>({g.jobIds.length} job{(g.jobIds.length === 1) ? '' : 's'})</span>
<JobGroup name={g.id} />&nbsp;
<span>
<FormattedMessage
id="xpack.ml.jobsList.jobFilterBar.jobGroupTitle"
defaultMessage="({jobsCount, plural, one {# job} other {# jobs}})"
values={{ jobsCount: g.jobIds.length }}
/>
</span>
</div>
)
}));
@ -39,7 +47,7 @@ function loadGroups() {
});
}
export class JobFilterBar extends Component {
class JobFilterBarUI extends Component {
constructor(props) {
super(props);
@ -69,7 +77,12 @@ export class JobFilterBar extends Component {
<EuiFlexItem grow={false}>
<EuiCallOut
color="danger"
title={`Invalid search: ${error.message}`}
title={(<FormattedMessage
id="xpack.ml.jobsList.jobFilterBar.invalidSearchErrorMessage"
defaultMessage="Invalid search: {errorMessage}"
values={{ errorMessage: error.message }}
/>
)}
/>
<EuiSpacer size="l" />
</EuiFlexItem>
@ -77,6 +90,7 @@ export class JobFilterBar extends Component {
}
render() {
const { intl } = this.props;
const filters = [
{
type: 'field_value_toggle_group',
@ -84,15 +98,24 @@ export class JobFilterBar extends Component {
items: [
{
value: 'opened',
name: 'Opened'
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.openedLabel',
defaultMessage: 'Opened'
})
},
{
value: 'closed',
name: 'Closed'
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.closedLabel',
defaultMessage: 'Closed'
})
},
{
value: 'failed',
name: 'Failed'
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.failedLabel',
defaultMessage: 'Failed'
})
}
]
},
@ -102,18 +125,27 @@ export class JobFilterBar extends Component {
items: [
{
value: 'started',
name: 'Started'
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.startedLabel',
defaultMessage: 'Started'
})
},
{
value: 'stopped',
name: 'Stopped'
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.stoppedLabel',
defaultMessage: 'Stopped'
})
}
]
},
{
type: 'field_value_selection',
field: 'groups',
name: 'Group',
name: intl.formatMessage({
id: 'xpack.ml.jobsList.jobFilterBar.groupLabel',
defaultMessage: 'Group'
}),
multiSelect: 'or',
cache: 10000,
options: () => loadGroups()
@ -138,7 +170,8 @@ export class JobFilterBar extends Component {
);
}
}
JobFilterBar.propTypes = {
JobFilterBarUI.propTypes = {
setFilters: PropTypes.func.isRequired,
};
export const JobFilterBar = injectI18n(JobFilterBarUI);

View file

@ -11,6 +11,7 @@ import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar
import { mlJobService } from 'plugins/ml/services/job_service';
import { ml } from 'plugins/ml/services/ml_api_service';
import { JOB_STATE, DATAFEED_STATE } from 'plugins/ml/../common/constants/states';
import { i18n } from '@kbn/i18n';
export function loadFullJob(jobId) {
return new Promise((resolve, reject) => {
@ -49,7 +50,9 @@ export function forceStartDatafeeds(jobs, start, end, finish = () => {}) {
})
.catch((error) => {
mlMessageBarService.notify.error(error);
toastNotifications.addDanger(`Jobs failed to start`, error);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.startJobErrorMessage', {
defaultMessage: 'Jobs failed to start'
}), error);
finish();
});
}
@ -64,7 +67,9 @@ export function stopDatafeeds(jobs, finish = () => {}) {
})
.catch((error) => {
mlMessageBarService.notify.error(error);
toastNotifications.addDanger(`Jobs failed to stop`, error);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.stopJobErrorMessage', {
defaultMessage: 'Jobs failed to stop'
}), error);
finish();
});
}
@ -87,30 +92,54 @@ function showResults(resp, action) {
let actionText = '';
let actionTextPT = '';
if (action === DATAFEED_STATE.STARTED) {
actionText = 'start';
actionTextPT = 'started';
actionText = i18n.translate('xpack.ml.jobsList.startActionStatusText', {
defaultMessage: 'start'
});
actionTextPT = i18n.translate('xpack.ml.jobsList.startedActionStatusText', {
defaultMessage: 'started'
});
} else if (action === DATAFEED_STATE.STOPPED) {
actionText = 'stop';
actionTextPT = 'stopped';
actionText = i18n.translate('xpack.ml.jobsList.stopActionStatusText', {
defaultMessage: 'stop'
});
actionTextPT = i18n.translate('xpack.ml.jobsList.stoppedActionStatusText', {
defaultMessage: 'stopped'
});
} else if (action === DATAFEED_STATE.DELETED) {
actionText = 'delete';
actionTextPT = 'deleted';
actionText = i18n.translate('xpack.ml.jobsList.deleteActionStatusText', {
defaultMessage: 'delete'
});
actionTextPT = i18n.translate('xpack.ml.jobsList.deletedActionStatusText', {
defaultMessage: 'deleted'
});
} else if (action === JOB_STATE.CLOSED) {
actionText = 'close';
actionTextPT = 'closed';
actionText = i18n.translate('xpack.ml.jobsList.closeActionStatusText', {
defaultMessage: 'close'
});
actionTextPT = i18n.translate('xpack.ml.jobsList.closedActionStatusText', {
defaultMessage: 'closed'
});
}
if (successes.length > 1) {
toastNotifications.addSuccess(`${successes.length} jobs ${actionTextPT} successfully`);
} else if (successes.length === 1) {
toastNotifications.addSuccess(`${successes[0]} ${actionTextPT} successfully`);
}
toastNotifications.addSuccess(i18n.translate('xpack.ml.jobsList.actionExecuteSuccessfullyNotificationMessage', {
defaultMessage: '{successesJobsCount, plural, one{{successJob}} other{# jobs}} {actionTextPT} successfully',
values: {
successesJobsCount: successes.length,
successJob: successes[0],
actionTextPT
}
}));
if (failures.length > 0) {
failures.forEach((f) => {
mlMessageBarService.notify.error(f.result.error);
toastNotifications.addDanger(`${f.id} failed to ${actionText}`);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.actionFailedNotificationMessage', {
defaultMessage: '{failureId} failed to {actionText}',
values: {
failureId: f.id,
actionText
}
}));
});
}
}
@ -123,7 +152,10 @@ export function cloneJob(jobId) {
})
.catch((error) => {
mlMessageBarService.notify.error(error);
toastNotifications.addDanger(`Could not clone ${jobId}. Job could not be found`);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.cloneJobErrorMessage', {
defaultMessage: 'Could not clone {jobId}. Job could not be found',
values: { jobId }
}));
});
}
@ -136,7 +168,9 @@ export function closeJobs(jobs, finish = () => {}) {
})
.catch((error) => {
mlMessageBarService.notify.error(error);
toastNotifications.addDanger(`Jobs failed to close`, error);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.closeJobErrorMessage', {
defaultMessage: 'Jobs failed to close',
}), error);
finish();
});
}
@ -150,7 +184,9 @@ export function deleteJobs(jobs, finish = () => {}) {
})
.catch((error) => {
mlMessageBarService.notify.error(error);
toastNotifications.addDanger(`Jobs failed to delete`, error);
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.deleteJobErrorMessage', {
defaultMessage: 'Jobs failed to delete',
}), error);
finish();
});
}