@@ -108,10 +129,22 @@ export class DeleteJobModal extends Component {
{(this.state.deleting === false) &&
- Are you sure you want to delete {(this.state.jobs.length > 1) ? 'these jobs' : 'this job'}?
+
+
+
{(this.state.jobs.length > 1) &&
- Deleting multiple jobs can be time consuming.
- They will be deleted in the background and may not disappear from the jobs list instantly
+
+
}
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
index 734e38844bd73..51eb70098aebe 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
@@ -32,8 +32,9 @@ import {
isValidCustomUrls } from '../validate_job';
import { mlMessageBarService } from '../../../../components/messagebar/messagebar_service';
import { toastNotifications } from 'ui/notify';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-export class EditJobFlyout extends Component {
+class EditJobFlyoutUI extends Component {
constructor(props) {
super(props);
@@ -134,7 +135,10 @@ export class EditJobFlyout extends Component {
if (jobDetails.jobGroups !== undefined) {
if (jobDetails.jobGroups.some(j => this.props.allJobIds.includes(j))) {
- jobGroupsValidationError = 'A job with this ID already exists. Groups and jobs cannot use the same ID.';
+ jobGroupsValidationError = this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.groupsAndJobsHasSameIdErrorMessage',
+ defaultMessage: 'A job with this ID already exists. Groups and jobs cannot use the same ID.'
+ });
} else {
jobGroupsValidationError = validateGroupNames(jobDetails.jobGroups).message;
}
@@ -185,13 +189,21 @@ export class EditJobFlyout extends Component {
saveJob(this.state.job, newJobData)
.then(() => {
- toastNotifications.addSuccess(`Changes to ${this.state.job.job_id} saved`);
+ toastNotifications.addSuccess(this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.changesSavedNotificationMessage',
+ defaultMessage: 'Changes to {jobId} saved' }, {
+ jobId: this.state.job.job_id }
+ ));
this.refreshJobs();
this.closeFlyout();
})
.catch((error) => {
console.error(error);
- toastNotifications.addDanger(`Could not save changes to ${this.state.job.job_id}`);
+ toastNotifications.addDanger(this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.changesNotSavedNotificationMessage',
+ defaultMessage: 'Could not save changes to {jobId}' }, {
+ jobId: this.state.job.job_id }
+ ));
mlMessageBarService.notify.error(error);
});
}
@@ -219,9 +231,14 @@ export class EditJobFlyout extends Component {
isValidJobCustomUrls,
} = this.state;
+ const { intl } = this.props;
+
const tabs = [{
id: 'job-details',
- name: 'Job details',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.jobDetailsTitle',
+ defaultMessage: 'Job details'
+ }),
content:
,
}, {
id: 'detectors',
- name: 'Detectors',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.detectorsTitle',
+ defaultMessage: 'Detectors'
+ }),
content:
,
}, {
id: 'datafeed',
- name: 'Datafeed',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.datafeedTitle',
+ defaultMessage: 'Datafeed'
+ }),
content:
,
}, {
id: 'custom-urls',
- name: 'Custom URLs',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrlsTitle',
+ defaultMessage: 'Custom URLs'
+ }),
content:
- Edit {job.id}
+
@@ -290,7 +320,10 @@ export class EditJobFlyout extends Component {
onClick={this.closeFlyout}
flush="left"
>
- Close
+
@@ -299,7 +332,10 @@ export class EditJobFlyout extends Component {
fill
isDisabled={(isValidJobDetails === false) || (isValidJobCustomUrls === false)}
>
- Save
+
@@ -317,9 +353,11 @@ export class EditJobFlyout extends Component {
}
}
-EditJobFlyout.propTypes = {
+EditJobFlyoutUI.propTypes = {
setShowFunction: PropTypes.func.isRequired,
unsetShowFunction: PropTypes.func.isRequired,
refreshJobs: PropTypes.func.isRequired,
allJobIds: PropTypes.array.isRequired,
};
+
+export const EditJobFlyout = injectI18n(EditJobFlyoutUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js
index 1a8e36b539099..49964514a21fa 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.js
@@ -37,10 +37,12 @@ import {
loadIndexPatterns,
} from '../edit_utils';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
+
const MAX_NUMBER_DASHBOARDS = 1000;
const MAX_NUMBER_INDEX_PATTERNS = 1000;
-export class CustomUrls extends Component {
+class CustomUrlsUI extends Component {
constructor(props) {
super(props);
@@ -65,13 +67,18 @@ export class CustomUrls extends Component {
}
componentDidMount() {
+ const { intl } = this.props;
+
loadSavedDashboards(MAX_NUMBER_DASHBOARDS)
.then((dashboards)=> {
this.setState({ dashboards });
})
.catch((resp) => {
console.log('Error loading list of dashboards:', resp);
- toastNotifications.addDanger('An error occurred loading the list of saved Kibana dashboards');
+ toastNotifications.addDanger(intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.loadSavedDashboardsErrorNotificationMessage',
+ defaultMessage: 'An error occurred loading the list of saved Kibana dashboards'
+ }));
});
loadIndexPatterns(MAX_NUMBER_INDEX_PATTERNS)
@@ -80,7 +87,10 @@ export class CustomUrls extends Component {
})
.catch((resp) => {
console.log('Error loading list of dashboards:', resp);
- toastNotifications.addDanger('An error occurred loading the list of saved index patterns');
+ toastNotifications.addDanger(intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.loadIndexPatternsErrorNotificationMessage',
+ defaultMessage: 'An error occurred loading the list of saved index patterns'
+ }));
});
}
@@ -111,12 +121,16 @@ export class CustomUrls extends Component {
})
.catch((resp) => {
console.log('Error building custom URL from settings:', resp);
- toastNotifications.addDanger('An error occurred building the new custom URL from the supplied settings');
+ toastNotifications.addDanger(this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.addNewUrlErrorNotificationMessage',
+ defaultMessage: 'An error occurred building the new custom URL from the supplied settings'
+ }));
});
}
onTestButtonClick = () => {
const job = this.props.job;
+ const { intl } = this.props;
buildCustomUrlFromSettings(this.state.editorSettings, job)
.then((customUrl) => {
getTestUrl(job, customUrl)
@@ -125,12 +139,18 @@ export class CustomUrls extends Component {
})
.catch((resp) => {
console.log('Error obtaining URL for test:', resp);
- toastNotifications.addWarning('An error occurred obtaining the URL to test the configuration');
+ toastNotifications.addWarning(intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.getTestUrlErrorNotificationMessage',
+ defaultMessage: 'An error occurred obtaining the URL to test the configuration'
+ }));
});
})
.catch((resp) => {
console.log('Error building custom URL from settings:', resp);
- toastNotifications.addWarning('An error occurred building the custom URL for testing from the supplied settings');
+ toastNotifications.addWarning(intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.buildUrlErrorNotificationMessage',
+ defaultMessage: 'An error occurred building the custom URL for testing from the supplied settings'
+ }));
});
}
@@ -160,7 +180,10 @@ export class CustomUrls extends Component {
size="s"
onClick={() => this.editNewCustomUrl()}
>
- Add custom URL
+
) : (
@@ -170,7 +193,10 @@ export class CustomUrls extends Component {
color="text"
onClick={() => this.closeEditor()}
iconType="cross"
- aria-label="Close custom URL editor"
+ aria-label={this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.editJobFlyout.customUrls.closeEditorAriaLabel',
+ defaultMessage: 'Close custom URL editor'
+ })}
className="close-editor-button"
/>
this.addNewCustomUrl()}
isDisabled={!isValidEditorSettings}
>
- Add
+
@@ -198,7 +227,10 @@ export class CustomUrls extends Component {
onClick={() => this.onTestButtonClick()}
isDisabled={!isValidEditorSettings}
>
- Test
+
@@ -217,8 +249,10 @@ export class CustomUrls extends Component {
);
}
}
-CustomUrls.propTypes = {
+CustomUrlsUI.propTypes = {
job: PropTypes.object.isRequired,
jobCustomUrls: PropTypes.array.isRequired,
setCustomUrls: PropTypes.func.isRequired,
};
+
+export const CustomUrls = injectI18n(CustomUrlsUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/datafeed.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/datafeed.js
index 4d1dca27389ad..c9e431dee846e 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/datafeed.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/edit_job_flyout/tabs/datafeed.js
@@ -22,6 +22,7 @@ import { calculateDatafeedFrequencyDefaultSeconds } from 'plugins/ml/../common/u
import { newJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults';
import { parseInterval } from 'plugins/ml/../common/util/parse_interval';
import { MLJobEditor } from '../../ml_job_editor';
+import { FormattedMessage } from '@kbn/i18n/react';
function getDefaults(bucketSpan, jobDefaults) {
const bucketSpanSeconds = (bucketSpan !== undefined) ? parseInterval(bucketSpan).asSeconds() : '';
@@ -91,7 +92,10 @@ export class Datafeed extends Component {
)}
style={{ maxWidth: 'inherit' }}
>
)}
>
)}
>
)}
>
)}
>
)}
isInvalid={(groupsValidationError !== '')}
error={groupsValidationError}
>
)}
isInvalid={(mmlValidationError !== '')}
error={mmlValidationError}
>
@@ -155,9 +168,11 @@ export class JobDetails extends Component {
);
}
}
-JobDetails.propTypes = {
+JobDetailsUI.propTypes = {
jobDescription: PropTypes.string.isRequired,
jobGroups: PropTypes.array.isRequired,
jobModelMemoryLimit: PropTypes.string.isRequired,
setJobDetails: PropTypes.func.isRequired,
};
+
+export const JobDetails = injectI18n(JobDetailsUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/management.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/management.js
index 4aa47dfd177fa..7234e3f9252d9 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/management.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/management.js
@@ -15,6 +15,7 @@ import {
isStoppable,
isClosable,
} from '../utils';
+import { i18n } from '@kbn/i18n';
export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showStartDatafeedModal, refreshJobs) {
const canCreateJob = (checkPermission('canCreateJob') && mlNodesAvailable());
@@ -26,8 +27,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
return [
{
- name: 'Start datafeed',
- description: 'Start datafeed',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.startDatafeedLabel', {
+ defaultMessage: 'Start datafeed'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.startDatafeedDescription', {
+ defaultMessage: 'Start datafeed'
+ }),
icon: 'play',
enabled: () => (canStartStopDatafeed),
available: (item) => (isStartable([item])),
@@ -36,8 +41,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
closeMenu();
}
}, {
- name: 'Stop datafeed',
- description: 'Stop datafeed',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.stopDatafeedLabel', {
+ defaultMessage: 'Stop datafeed'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.stopDatafeedDescription', {
+ defaultMessage: 'Stop datafeed'
+ }),
icon: 'stop',
enabled: () => (canStartStopDatafeed),
available: (item) => (isStoppable([item])),
@@ -46,8 +55,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
closeMenu(true);
}
}, {
- name: 'Close job',
- description: 'Close job',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.closeJobLabel', {
+ defaultMessage: 'Close job'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.closeJobDescription', {
+ defaultMessage: 'Close job'
+ }),
icon: 'cross',
enabled: () => (canCloseJob),
available: (item) => (isClosable([item])),
@@ -56,8 +69,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
closeMenu(true);
}
}, {
- name: 'Clone job',
- description: 'Clone job',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.cloneJobLabel', {
+ defaultMessage: 'Clone job'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.cloneJobDescription', {
+ defaultMessage: 'Clone job'
+ }),
icon: 'copy',
enabled: () => (canCreateJob),
onClick: (item) => {
@@ -65,8 +82,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
closeMenu(true);
}
}, {
- name: 'Edit job',
- description: 'Edit job',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.editJobLabel', {
+ defaultMessage: 'Edit job'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.editJobDescription', {
+ defaultMessage: 'Edit job'
+ }),
icon: 'pencil',
enabled: () => (canUpdateJob && canUpdateDatafeed),
onClick: (item) => {
@@ -74,8 +95,12 @@ export function actionsMenuContent(showEditJobFlyout, showDeleteJobModal, showSt
closeMenu();
}
}, {
- name: 'Delete job',
- description: 'Delete job',
+ name: i18n.translate('xpack.ml.jobsList.managementActions.deleteJobLabel', {
+ defaultMessage: 'Delete job'
+ }),
+ description: i18n.translate('xpack.ml.jobsList.managementActions.deleteJobDescription', {
+ defaultMessage: 'Delete job'
+ }),
icon: 'trash',
color: 'danger',
enabled: () => (canDeleteJob),
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/results.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/results.js
index 486d27e8b9dbb..054ce12f65935 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/results.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/job_actions/results.js
@@ -18,6 +18,7 @@ import moment from 'moment';
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
import { mlJobService } from 'plugins/ml/services/job_service';
+import { injectI18n } from '@kbn/i18n/react';
function getLink(location, jobs) {
let from = 0;
@@ -38,8 +39,19 @@ function getLink(location, jobs) {
return `${chrome.getBasePath()}/app/${url}`;
}
-export function ResultLinks({ jobs }) {
- const tooltipJobs = (jobs.length === 1) ? jobs[0].id : `${jobs.length} jobs`;
+function ResultLinksUI({ jobs, intl }) {
+ const openJobsInSingleMetricViewerText = intl.formatMessage({
+ id: 'xpack.ml.jobsList.resultActions.openJobsInSingleMetricViewerText',
+ defaultMessage: 'Open {jobsCount, plural, one {{jobId}} other {# jobs}} in Single Metric Viewer' }, {
+ jobsCount: jobs.length,
+ jobId: jobs[0].id
+ });
+ const openJobsInAnomalyExplorerText = intl.formatMessage({
+ id: 'xpack.ml.jobsList.resultActions.openJobsInAnomalyExplorerText',
+ defaultMessage: 'Open {jobsCount, plural, one {{jobId}} other {# jobs}} in Anomaly Explorer' }, {
+ jobsCount: jobs.length,
+ jobId: jobs[0].id
+ });
const singleMetricVisible = (jobs.length < 2);
const singleMetricEnabled = (jobs.length === 1 && jobs[0].isSingleMetricViewerJob);
return (
@@ -47,12 +59,12 @@ export function ResultLinks({ jobs }) {
{(singleMetricVisible) &&
@@ -60,12 +72,12 @@ export function ResultLinks({ jobs }) {
}
@@ -73,7 +85,8 @@ export function ResultLinks({ jobs }) {
);
}
-ResultLinks.propTypes = {
+ResultLinksUI.propTypes = {
jobs: PropTypes.array.isRequired,
};
+export const ResultLinks = injectI18n(ResultLinksUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list/jobs_list.js
index 0165b26095b16..5a495352bdb6f 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list/jobs_list.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list/jobs_list.js
@@ -22,12 +22,13 @@ import {
EuiBasicTable,
EuiButtonIcon,
} from '@elastic/eui';
+import { injectI18n } from '@kbn/i18n/react';
const PAGE_SIZE = 10;
const PAGE_SIZE_OPTIONS = [10, 25, 50];
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
-export class JobsList extends Component {
+class JobsListUI extends Component {
constructor(props) {
super(props);
@@ -97,9 +98,13 @@ export class JobsList extends Component {
}
render() {
+ const { intl } = this.props;
const selectionControls = {
selectable: () => true,
- selectableMessage: (selectable) => (!selectable) ? 'Cannot select job' : undefined,
+ selectableMessage: (selectable) => (!selectable) ? intl.formatMessage({
+ id: 'xpack.ml.jobsList.cannotSelectJobTooltip',
+ defaultMessage: 'Cannot select job' })
+ : undefined,
onSelectionChange: this.props.selectJobChange
};
@@ -110,13 +115,26 @@ export class JobsList extends Component {
this.toggleRow(item)}
iconType={this.state.itemIdToExpandedRowMap[item.id] ? 'arrowDown' : 'arrowRight'}
- aria-label={`${this.state.itemIdToExpandedRowMap[item.id] ? 'Hide' : 'Show'} details for ${item.id}`}
+ aria-label={this.state.itemIdToExpandedRowMap[item.id]
+ ? intl.formatMessage({
+ id: 'xpack.ml.jobsList.collapseJobDetailsAriaLabel',
+ defaultMessage: 'Hide details for {itemId}' },
+ { itemId: item.id }
+ )
+ : intl.formatMessage({
+ id: 'xpack.ml.jobsList.expandJobDetailsAriaLabel',
+ defaultMessage: 'Show details for {itemId}' },
+ { itemId: item.id }
+ )}
data-row-id={item.id}
/>
)
}, {
field: 'id',
- name: 'ID',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.idLabel',
+ defaultMessage: 'ID'
+ }),
sortable: true,
truncateText: false,
@@ -127,7 +145,10 @@ export class JobsList extends Component {
)
}, {
- name: 'Description',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.descriptionLabel',
+ defaultMessage: 'Description'
+ }),
sortable: true,
field: 'description',
render: (description, item) => (
@@ -135,28 +156,43 @@ export class JobsList extends Component {
)
}, {
field: 'processed_record_count',
- name: 'Processed records',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.processedRecordsLabel',
+ defaultMessage: 'Processed records'
+ }),
sortable: true,
truncateText: false,
dataType: 'number',
render: count => toLocaleString(count)
}, {
field: 'memory_status',
- name: 'Memory status',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.memoryStatusLabel',
+ defaultMessage: 'Memory status'
+ }),
sortable: true,
truncateText: false,
}, {
field: 'jobState',
- name: 'Job state',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.jobStateLabel',
+ defaultMessage: 'Job state'
+ }),
sortable: true,
truncateText: false,
}, {
field: 'datafeedState',
- name: 'Datafeed state',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.datafeedStateLabel',
+ defaultMessage: 'Datafeed state'
+ }),
sortable: true,
truncateText: false,
}, {
- name: 'Latest timestamp',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.latestTimestampLabel',
+ defaultMessage: 'Latest timestamp'
+ }),
truncateText: false,
field: 'latestTimestampSortValue',
sortable: true,
@@ -168,7 +204,10 @@ export class JobsList extends Component {
)
}, {
- name: 'Actions',
+ name: intl.formatMessage({
+ id: 'xpack.ml.jobsList.actionsLabel',
+ defaultMessage: 'Actions'
+ }),
render: (item) => (
)
@@ -228,7 +267,7 @@ export class JobsList extends Component {
);
}
}
-JobsList.propTypes = {
+JobsListUI.propTypes = {
jobsSummaryList: PropTypes.array.isRequired,
fullJobsList: PropTypes.object.isRequired,
itemIdToExpandedRowMap: PropTypes.object.isRequired,
@@ -240,3 +279,5 @@ JobsList.propTypes = {
refreshJobs: PropTypes.func.isRequired,
selectedJobsCount: PropTypes.number.isRequired,
};
+
+export const JobsList = injectI18n(JobsListUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js
index 79cc8bf8ee861..5af623cb82449 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js
@@ -9,16 +9,53 @@ import { JOB_STATE, DATAFEED_STATE } from 'plugins/ml/../common/constants/states
import PropTypes from 'prop-types';
import React from 'react';
+import { i18n } from '@kbn/i18n';
function createJobStats(jobsSummaryList) {
const jobStats = {
- activeNodes: { label: 'Active ML Nodes', value: 0, show: true },
- total: { label: 'Total jobs', value: 0, show: true },
- open: { label: 'Open jobs', value: 0, show: true },
- closed: { label: 'Closed jobs', value: 0, show: true },
- failed: { label: 'Failed jobs', value: 0, show: false },
- activeDatafeeds: { label: 'Active datafeeds', value: 0, show: true }
+ activeNodes: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.activeMLNodesLabel', {
+ defaultMessage: 'Active ML Nodes'
+ }),
+ value: 0,
+ show: true
+ },
+ total: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.totalJobsLabel', {
+ defaultMessage: 'Total jobs'
+ }),
+ value: 0,
+ show: true
+ },
+ open: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.openJobsLabel', {
+ defaultMessage: 'Open jobs'
+ }),
+ value: 0,
+ show: true
+ },
+ closed: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.closedJobsLabel', {
+ defaultMessage: 'Closed jobs'
+ }),
+ value: 0,
+ show: true
+ },
+ failed: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.failedJobsLabel', {
+ defaultMessage: 'Failed jobs'
+ }),
+ value: 0,
+ show: false
+ },
+ activeDatafeeds: {
+ label: i18n.translate('xpack.ml.jobsList.statsBar.activeDatafeedsLabel', {
+ defaultMessage: 'Active datafeeds'
+ }),
+ value: 0,
+ show: true
+ }
};
if (jobsSummaryList === undefined) {
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/actions_menu.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/actions_menu.js
index c4fbc39eba7c7..571203b5fa99e 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/actions_menu.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/actions_menu.js
@@ -26,8 +26,9 @@ import {
isStoppable,
isClosable,
} from '../utils';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-export class MultiJobActionsMenu extends Component {
+class MultiJobActionsMenuUI extends Component {
constructor(props) {
super(props);
@@ -58,13 +59,15 @@ export class MultiJobActionsMenu extends Component {
size="s"
onClick={this.onButtonClick}
iconType="gear"
- aria-label="Management actions"
+ aria-label={this.props.intl.formatMessage({
+ id: 'xpack.ml.jobsList.multiJobActionsMenu.managementActionsAriaLabel',
+ defaultMessage: 'Management actions'
+ })}
color="text"
disabled={(this.canDeleteJob === false && this.canStartStopDatafeed === false)}
/>
);
- const s = (this.props.jobs.length > 1) ? 's' : '';
const items = [
(
{ this.props.showDeleteJobModal(this.props.jobs); this.closePopover(); }}
>
- Delete job{s}
+
)
];
@@ -86,7 +93,11 @@ export class MultiJobActionsMenu extends Component {
disabled={(this.canCloseJob === false)}
onClick={() => { closeJobs(this.props.jobs); this.closePopover(); }}
>
- Close job{s}
+
);
}
@@ -99,7 +110,11 @@ export class MultiJobActionsMenu extends Component {
disabled={(this.canStartStopDatafeed === false)}
onClick={() => { stopDatafeeds(this.props.jobs, this.props.refreshJobs); this.closePopover(); }}
>
- Stop datafeed{s}
+
);
}
@@ -112,7 +127,11 @@ export class MultiJobActionsMenu extends Component {
disabled={(this.canStartStopDatafeed === false)}
onClick={() => { this.props.showStartDatafeedModal(this.props.jobs); this.closePopover(); }}
>
- Start datafeed{s}
+
);
}
@@ -132,9 +151,11 @@ export class MultiJobActionsMenu extends Component {
);
}
}
-MultiJobActionsMenu.propTypes = {
+MultiJobActionsMenuUI.propTypes = {
jobs: PropTypes.array.isRequired,
showStartDatafeedModal: PropTypes.func.isRequired,
showDeleteJobModal: PropTypes.func.isRequired,
refreshJobs: PropTypes.func.isRequired,
};
+
+export const MultiJobActionsMenu = injectI18n(MultiJobActionsMenuUI);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/multi_job_actions.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/multi_job_actions.js
index 4089b2b3e5881..26017bad23ea6 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/multi_job_actions.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/multi_job_actions/multi_job_actions.js
@@ -13,6 +13,7 @@ import React, {
import { ResultLinks } from '../job_actions';
import { MultiJobActionsMenu } from './actions_menu';
import { GroupSelector } from './group_selector';
+import { FormattedMessage } from '@kbn/i18n/react';
export class MultiJobActions extends Component {
constructor(props) {
@@ -22,13 +23,18 @@ export class MultiJobActions extends Component {
}
render() {
- const s = (this.props.selectedJobs.length > 1) ? 's' : '';
const jobsSelected = (this.props.selectedJobs.length > 0);
return (
{jobsSelected &&
- {this.props.selectedJobs.length} job{s} selected
+
+
+
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/new_job_button/new_job_button.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/new_job_button/new_job_button.js
index df61ddf6decdb..6c56b4c8b1076 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/new_job_button/new_job_button.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/new_job_button/new_job_button.js
@@ -14,6 +14,7 @@ import React from 'react';
import {
EuiButton,
} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
function newJob() {
window.location.href = `#/jobs/new_job`;
@@ -29,7 +30,10 @@ export function NewJobButton() {
fill
iconType="plusInCircle"
>
- Create new job
+
);
}
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/node_available_warning/node_available_warning.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/node_available_warning/node_available_warning.js
index 7e0d39ffd4c07..b8bf465eea576 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/node_available_warning/node_available_warning.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/node_available_warning/node_available_warning.js
@@ -14,6 +14,7 @@ import {
EuiLink,
EuiSpacer,
} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
export function NodeAvailableWarning() {
const isCloud = false; // placeholder for future specific cloud functionality
@@ -23,18 +24,40 @@ export function NodeAvailableWarning() {
return (
)}
color="warning"
iconType="alert"
>
- There are no ML nodes available.
- You will not be able to create or run jobs.
- {isCloud &&
-
- This can be configured in Cloud here.
-
- }
+
+
+
+
+ )
+ }}
+ />
+ : '',
+ }}
+ />
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js
index 3aecf95d55f56..72338915cc1fc 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js
@@ -12,6 +12,7 @@ import PropTypes from 'prop-types';
import {
EuiButtonEmpty,
} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
export const RefreshJobsListButton = ({ onRefreshClick, isRefreshing }) => (
@@ -19,7 +20,10 @@ export const RefreshJobsListButton = ({ onRefreshClick, isRefreshing }) => (
onClick={onRefreshClick}
isLoading={isRefreshing}
>
- Refresh
+
);
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
index f37db8d6309fc..6617f3cdc81ae 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
@@ -30,6 +30,8 @@ import { forceStartDatafeeds } from '../utils';
import { TimeRangeSelector } from './time_range_selector';
+import { FormattedMessage } from '@kbn/i18n/react';
+
export class StartDatafeedModal extends Component {
constructor(props) {
super(props);
@@ -136,7 +138,14 @@ export class StartDatafeedModal extends Component {
>
- Start {(startableJobs.length > 1) ? `${startableJobs.length} jobs` : startableJobs[0].id}
+
@@ -154,7 +163,10 @@ export class StartDatafeedModal extends Component {
)}
checked={createWatch}
onChange={this.setCreateWatch}
/>
@@ -166,7 +178,10 @@ export class StartDatafeedModal extends Component {
- Cancel
+
- Start
+
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js
index d3b815ac253d5..d7b2b5ddf18ea 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js
@@ -15,6 +15,7 @@ import {
} from '@elastic/eui';
import moment from 'moment';
+import { FormattedMessage } from '@kbn/i18n/react';
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
@@ -78,8 +79,34 @@ export class TimeRangeSelector extends Component {
// the job has seen any data yet
const showContinueLabels = (this.latestTimestamp.valueOf() > 0);
const startLabels = (showContinueLabels === true) ?
- [`Continue from ${formattedStartTime}`, 'Continue from now', 'Continue from specified time'] :
- ['Start at beginning of data', 'Start from now', 'Specify start time'];
+ [
+ (),
+ (),
+ ()
+ ] : [
+ (),
+ (),
+ ()
+ ];
const startItems = [
{ index: 0, label: startLabels[0] },
@@ -96,8 +123,19 @@ export class TimeRangeSelector extends Component {
},
];
const endItems = [
- { index: 0, label: 'No end time (Real-time search)' },
- { index: 1, label: 'Specify end time',
+ {
+ index: 0,
+ label: ()
+ },
+ {
+ index: 1,
+ label: (),
body: (
)}
items={startItems}
switchState={this.state.startTab}
switchFunc={this.setStartTab}
/>
)}
items={endItems}
switchState={this.state.endTab}
switchFunc={this.setEndTab}
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/directive.js b/x-pack/plugins/ml/public/jobs/jobs_list/directive.js
index 84164c5213e70..030524baff642 100644
--- a/x-pack/plugins/ml/public/jobs/jobs_list/directive.js
+++ b/x-pack/plugins/ml/public/jobs/jobs_list/directive.js
@@ -34,6 +34,7 @@ uiRoutes
});
import { JobsPage } from './jobs';
+import { I18nProvider } from '@kbn/i18n/react';
module.directive('jobsPage', function () {
return {
@@ -41,7 +42,7 @@ module.directive('jobsPage', function () {
restrict: 'E',
link: (scope, element) => {
ReactDOM.render(
- React.createElement(JobsPage),
+ {React.createElement(JobsPage)},
element[0]
);
}