translate Machine Learning datavisualizer (#25527)

* translate Machine Learning datavisualizer

* change some ids, change some structures and dont translate unnesesary scripts

* update i18nrc.json

* update datavisualizer_selector.js - remove eslint-disable

* add html_ prefix to values containing html

* use i18n angular service.

translate missed labels

* Fix syntax in i18n-values

* Replace FormatedMessage to intl.formatMessage for  betaBadgeLabel

* Fix issue
This commit is contained in:
tibmt 2018-12-20 11:53:44 +02:00 committed by Nox911
parent 5a7ab185f9
commit 16033357c2
5 changed files with 300 additions and 86 deletions

View file

@ -29,14 +29,20 @@
type="text"
class="kuiLocalSearchInput"
ng-model="searchQueryText"
placeholder="Search... (e.g. status:200 AND extension:PHP)"
aria-label="Search input"
placeholder="{{ ::'xpack.ml.datavisualizer.searchFieldPlaceholder' | i18n: {
defaultMessage: 'Search… (e.g. status:200 AND extension:PHP)'
} }}"
aria-label="{{ ::'xpack.ml.datavisualizer.searchFieldAriaLabel' | i18n: {
defaultMessage: 'Search input'
} }}"
autocomplete="off"
>
<button
class="kuiLocalSearchButton"
type="submit"
aria-label="Search"
aria-label="{{ ::'xpack.ml.datavisualizer.searchButtonAriaLabel' | i18n: {
defaultMessage: 'Search'
} }}"
>
<span aria-hidden="true" class="kuiIcon fa-search"></span>
</button>
@ -44,48 +50,86 @@
</form>
<div class="document-count-container">
<label for="sampleShardSize">Sample</label>
<label
for="sampleShardSize"
i18n-id="xpack.ml.datavisualizer.sampleLabel"
i18n-default-message="Sample"
></label>
<select id="sampleShardSize" class="kuiSelect type-input" ng-model="samplerShardSize" ng-change="samplerShardSizeChanged(samplerShardSize)">
<option ng-value="1000">1000</option>
<option ng-value="5000">5000</option>
<option ng-value="10000">10000</option>
<option ng-value="100000">100000</option>
<option ng-value="-1">all</option>
<option
ng-value="-1"
i18n-id="xpack.ml.datavisualizer.allOptionLabel"
i18n-default-message="all"
></option>
</select>
<span>documents per shard from a total of</span>
<span class="field-emphasis">{{ overallStats.totalCount }}</span>
<ng-pluralize count="overallStats.totalCount" when="{'1':'document', 'other':'documents'}">documents</ng-pluralize>
<i aria-hidden="true" class="fa fa-info-circle" tooltip-placement="right"
tooltip="Selecting a smaller sample size will reduce query run times and the load on the cluster."></i>
<span
i18n-id="xpack.ml.datavisualizer.documentsPerShardDescription"
i18n-default-message="documents per shard from a total of {wrappedTotalCount} {totalCount, plural, one {document} other {documents}}"
i18n-values="{
html_wrappedTotalCount: '<span class=\'field-emphasis\'>' + overallStats.totalCount + '</span>',
totalCount: overallStats.totalCount
}"
></span>
<i
aria-hidden="true"
class="fa fa-info-circle"
tooltip-placement="right"
tooltip="{{ ::'xpack.ml.datavisualizer.documentsPerShardTooltip' | i18n: {
defaultMessage: 'Selecting a smaller sample size will reduce query run times and the load on the cluster.'
} }}"
></i>
</div>
</div>
<div class="kuiPanel kuiVerticalRhythm datavisualizer-panel card-panel">
<div class="euiText">
<h2 class="kuiSubTitle kuiVerticalRhythm">Metrics</h2>
<h2
class="kuiSubTitle kuiVerticalRhythm"
i18n-id="xpack.ml.datavisualizer.metricsTitle"
i18n-default-message="Metrics"
></h2>
</div>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--responsive euiFlexGroup--wrap">
<div class="field-sort-controls euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div ng-if="showAllMetrics === false" class="field-count-label euiFlexItem euiFlexItem--flexGrowZero">
<span class="field-emphasis">{{ metricCards.length }}</span>
<ng-pluralize count="metricCards.length" when="{'1':'field exists', 'other':'fields exist'}">fields exist</ng-pluralize> in documents (
<span class="field-emphasis">{{ totalMetricFieldCount }}</span> in total)
<span
i18n-id="xpack.ml.datavisualizer.showMetricsDescription"
i18n-default-message="{wrappedMetricCardsCount} {metricCardsCount, plural, one {field exists} other {fields exist}} in documents ({totalMetricFieldCount} in total)"
i18n-values="{
html_wrappedMetricCardsCount: '<span class=\'field-emphasis\'>' + metricCards.length + '</span>',
metricCardsCount: metricCards.length,
html_totalMetricFieldCount: '<span class=\'field-emphasis\'>' + totalMetricFieldCount + '</span>'
}"
></span>
</div>
<div ng-if="showAllMetrics === true" class="field-count-label euiFlexItem euiFlexItem--flexGrowZero">
<span class="field-emphasis">{{ metricCards.length }}</span>
<ng-pluralize count="metricCards.length" when="{'1':'field', 'other':'fields'}">fields</ng-pluralize>
(
<span class="field-emphasis">{{ populatedMetricFieldCount }}</span>
<ng-pluralize count="populatedMetricFieldCount" when="{'1':'exists', 'other':'exist'}">exist</ng-pluralize> in documents)
<span
i18n-id="xpack.ml.datavisualizer.showAllMetricsDescription"
i18n-default-message="{wrappedMetricCardsCount} {metricCardsCount, plural, one {field} other {fields}} ({wrappedPopulatedMetricFieldCount} {populatedMetricFieldCount, plural, one {exists} other {exist}} in documents)"
i18n-values="{
html_wrappedMetricCardsCount: '<span class=\'field-emphasis\'>' + metricCards.length + '</span>',
metricCardsCount: metricCards.length,
html_wrappedPopulatedMetricFieldCount: '<span class=\'field-emphasis\'>' + populatedMetricFieldCount + '</span>',
populatedMetricFieldCount
}"
></span>
</div>
<div ng-hide="populatedMetricFieldCount === totalMetricFieldCount" class="field-group-input euiFlexItem euiFlexItem--flexGrowZero">
<input id="toggleAllMetricsCheckbox" type="checkbox" class="kuiCheckBox" ng-click="toggleAllMetrics()" ng-checked="showAllMetrics === true">
<label for="toggleAllMetricsCheckbox">show empty fields</label>
<label
for="toggleAllMetricsCheckbox"
i18n-id="xpack.ml.datavisualizer.showEmptyFieldsLabel"
i18n-default-message="show empty fields"
></label>
</div>
</div>
</div>
@ -112,28 +156,49 @@
<div class="kuiPanel kuiVerticalRhythm datavisualizer-panel card-panel">
<div class="euiText">
<h2 class="kuiSubTitle kuiVerticalRhythm">Fields</h2>
<h2
class="kuiSubTitle kuiVerticalRhythm"
i18n-id="xpack.ml.datavisualizer.fieldsTitle"
i18n-default-message="Fields"
></h2>
</div>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--responsive euiFlexGroup--wrap">
<div class="field-sort-controls euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div ng-if="showAllFields === false" class="field-count-label euiFlexItem euiFlexItem--flexGrowZero">
<span class="field-emphasis">{{ fieldCards.length }}</span>
<ng-pluralize count="fieldCards.length" when="{'1':'field exists', 'other':'fields exist'}">fields exist</ng-pluralize> in documents
(<span class="field-emphasis">{{ totalNonMetricFieldCount }}</span> in total)
<span
i18n-id="xpack.ml.datavisualizer.showMFieldDescription"
i18n-default-message="{wrappedFieldCardsCount} {fieldCardsCount, plural, one {field exists} other {fields exist}} in documents ({totalNonMetricFieldCount} in total)"
i18n-values="{
html_wrappedFieldCardsCount: '<span class=\'field-emphasis\'>' + fieldCards.length + '</span>',
fieldCardsCount: fieldCards.length,
html_totalNonMetricFieldCount: '<span class=\'field-emphasis\'>' + totalNonMetricFieldCount + '</span>'
}"
></span>
</div>
<div ng-if="showAllFields === true" class="field-count-label euiFlexItem euiFlexItem--flexGrowZero">
<span class="field-emphasis">{{ fieldCards.length }}</span>
<ng-pluralize count="fieldCards.length" when="{'1':'field', 'other':'fields'}">fields</ng-pluralize>
(<span class="field-emphasis">{{ populatedNonMetricFieldCount }}</span>
<ng-pluralize count="populatedNonMetricFieldCount" when="{'1':'exists', 'other':'exist'}">exist</ng-pluralize> in documents)
<span
i18n-id="xpack.ml.datavisualizer.showAllFieldsDescription"
i18n-default-message="{wrappedFieldCardsCount} {fieldCardsCount, plural, one {field} other {fields}} ({wrappedPopulatedNonMetricFieldCount} {populatedNonMetricFieldCount, plural, one {exists} other {exist}} in documents)"
i18n-values="{
html_wrappedFieldCardsCount: '<span class=\'field-emphasis\'>' + fieldCards.length + '</span>',
fieldCardsCount: fieldCards.length,
html_wrappedPopulatedNonMetricFieldCount: '<span class=\'field-emphasis\'>' + populatedNonMetricFieldCount +'</span>',
populatedNonMetricFieldCount
}"
></span>
</div>
<div ng-hide="populatedNonMetricFieldCount === totalNonMetricFieldCount" class="field-group-input euiFlexItem euiFlexItem--flexGrowZero">
<input id="toggleAllFieldsCheckbox" type="checkbox" class="kuiCheckBox" ng-click="toggleAllFields()" ng-checked="showAllFields === true">
<label for="toggleAllFieldsCheckbox">show empty fields</label>
<label
for="toggleAllFieldsCheckbox"
i18n-id="xpack.ml.datavisualizer.showEmptyFieldsLabel"
i18n-default-message="show empty fields"
></label>
</div>
</div>
</div>
@ -143,9 +208,22 @@
<select class="kuiSelect type-input"
ng-model="filterFieldType"
ng-change="filterFieldTypeChanged(filterFieldType)"
aria-label="Select field types">
<option value="*">All field types</option>
<option ng-repeat="type in indexedFieldTypes" value="{{type}}">{{type}} types</option>
aria-label="{{ ::'xpack.ml.datavisualizer.selectFieldTypesAriaLabel' | i18n: {
defaultMessage: 'Select field types'
} }}"
>
<option
value="*"
i18n-id="xpack.ml.datavisualizer.allFieldsTypeOptionLabel"
i18n-default-message="All field types"
></option>
<option
ng-repeat="type in indexedFieldTypes"
value="{{type}}"
i18n-id="xpack.ml.datavisualizer.typesOptionLabel"
i18n-default-message="{type} types"
i18n-values="{ type }"
></option>
</select>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">

View file

@ -59,7 +59,8 @@ module
$window,
Private,
AppState,
config) {
config,
i18n) {
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
@ -108,8 +109,15 @@ module
$scope.searchQueryText = _.get(queryBarQry, 'query', '');
} else {
toastNotifications.addWarning({
title: `${(queryBarQry.language !== undefined) ? queryBarQry.language : ''} syntax not supported`,
text: 'The Data Visualizer currently only supports queries using the lucene query syntax.',
title: i18n('xpack.ml.datavisualizer.languageSyntaxNotSupportedWarningTitle', {
defaultMessage: '{language} syntax not supported',
values: {
language: (queryBarQry.language !== undefined) ? queryBarQry.language : '',
}
}),
text: i18n('xpack.ml.datavisualizer.languageSyntaxNotSupportedWarningDescription', {
defaultMessage: 'The Data Visualizer currently only supports queries using the lucene query syntax.',
}),
});
}
@ -495,12 +503,28 @@ module
// TODO - display error in cards saying data could not be loaded.
console.log('DataVisualizer - error getting stats for metric cards from elasticsearch:', err);
if (err.statusCode === 500) {
notify.error(`Error loading data for metrics in index ${indexPattern.title}. ${err.message}. ` +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.metricInternalServerErrorTitle', {
defaultMessage: 'Error loading data for metrics in index {index}. {message}. ' +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
} else {
notify.error(`Error loading data for metrics in index ${indexPattern.title}. ${err.message}`,
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.loadingMetricDataErrorTitle', {
defaultMessage: 'Error loading data for metrics in index {index}. {message}',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
}
});
@ -546,12 +570,28 @@ module
// TODO - display error in cards saying data could not be loaded.
console.log('DataVisualizer - error getting non metric field stats from elasticsearch:', err);
if (err.statusCode === 500) {
notify.error(`Error loading data for fields in index ${indexPattern.title}. ${err.message}. ` +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.fieldsInternalServerErrorTitle', {
defaultMessage: 'Error loading data for fields in index {index}. {message}. ' +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
} else {
notify.error(`Error loading data for fields in index ${indexPattern.title}. ${err.message}`,
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.loadingFieldsDataErrorTitle', {
defaultMessage: 'Error loading data for fields in index {index}. {message}',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
}
});
} else {
@ -596,12 +636,28 @@ module
// TODO - display error in cards saying data could not be loaded.
console.log('DataVisualizer - error getting overall stats from elasticsearch:', err);
if (err.statusCode === 500) {
notify.error(`Error loading data for fields in index ${indexPattern.title}. ${err.message}. ` +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.overallFieldsInternalServerErrorTitle', {
defaultMessage: 'Error loading data for fields in index {index}. {message}. ' +
'The request may have timed out. Try using a smaller sample size or narrowing the time range.',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
} else {
notify.error(`Error loading data for fields in index ${indexPattern.title}. ${err.message}`,
{ lifetime: 30000 });
notify.error(
i18n('xpack.ml.datavisualizer.loadingOverallFieldsDataErrorTitle', {
defaultMessage: 'Error loading data for fields in index {index}. {message}',
values: {
index: indexPattern.title,
message: err.message,
}
}),
{ lifetime: 30000 }
);
}
});

View file

@ -1,11 +1,15 @@
<div class="kuiPanel kuiVerticalRhythm datavisualizer-panel euiText">
<h2>Create Job</h2>
<h2
i18n-id="xpack.ml.datavisualizer.sidebar.createJobTitle"
i18n-default-message="Create Job"
></h2>
<div class="create-job-content">
<div class="recognized-job-content" ng-show="recognizerResults.count!==0">
<p>
Select known configurations for recognized data:
</p>
<p
i18n-id="xpack.ml.datavisualizer.sidebar.selectKnownConfigurationDescription"
i18n-default-message="Select known configurations for recognized data:"
></p>
<ml-data-recognizer
class-name='"euiFlexGroup euiFlexGrid--gutterLarge euiFlexGroup--responsive euiFlexGroup--wrap"'
@ -13,23 +17,37 @@
results=recognizerResults/>
</div>
<p>
Use the Advanced job wizard to create a job to find anomalies in this data:
</p>
<p
i18n-id="xpack.ml.datavisualizer.sidebar.createJobDescription"
i18n-default-message="Use the Advanced job wizard to create a job to find anomalies in this data:"
></p>
<a ng-click="createJob()" ng-class='{disabled: isTimeBasedIndex===false}' class="euiLink synopsis">
<div class="euiPanel euiPanel--paddingMedium synopsisPanel">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<icon type="'createAdvancedJob'" size="'xl'" aria-label="Advanced job" class="synopsisIcon" />
<icon
type="'createAdvancedJob'"
size="'xl'"
aria-label="{{ ::'xpack.ml.datavisualizer.sidebar.advancedJobAriaLabel' | i18n: {
defaultMessage: 'Advanced job'
} }}"
class="synopsisIcon"
/>
</div>
<div class="euiFlexItem synopsisContent">
<h4 class="euiTitle euiTitle--small synopsisTitle">Advanced</h4>
<h4
class="euiTitle euiTitle--small synopsisTitle"
i18n-id="xpack.ml.datavisualizer.sidebar.advancedTitle"
i18n-default-message="Advanced"
></h4>
<div class="euiText synopsisBody">
<p>
<span class="euiTextColor euiTextColor--subdued">
Use the full range of options to create a job for more advanced use cases
</span>
<span
class="euiTextColor euiTextColor--subdued"
i18n-id="xpack.ml.datavisualizer.sidebar.advancedDescription"
i18n-default-message="Use the full range of options to create a job for more advanced use cases"
></span>
</p>
</div>
</div>

View file

@ -21,24 +21,34 @@ import {
} from '@elastic/eui';
import { isFullLicense } from '../../license/check_license';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
function startTrialDescription() {
return (
<span>
To experience the full Machine Learning features that a {' '}
<EuiLink
href="https://www.elastic.co/subscriptions"
target="_blank"
>
Platinum subscription
</EuiLink>{' '}
offers, start a 30-day trial.
<FormattedMessage
id="xpack.ml.datavisualizer.startTrial.fullMLFeaturesDescription"
defaultMessage="To experience the full Machine Learning features that a {platinumSubscriptionLink} offers, start a 30-day trial."
values={{
platinumSubscriptionLink: (
<EuiLink
href="https://www.elastic.co/subscriptions"
target="_blank"
>
<FormattedMessage
id="xpack.ml.datavisualizer.startTrial.platinumSubscriptionTitle"
defaultMessage="Platinum subscription"
/>
</EuiLink>
)
}}
/>
</span>
);
}
export function DatavisualizerSelector() {
export const DatavisualizerSelector = injectI18n(function (props) {
const startTrialVisible = (isFullLicense() === false);
@ -48,7 +58,12 @@ export function DatavisualizerSelector() {
<EuiFlexGroup gutterSize="xl">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h2>Data Visualizer</h2>
<h2>
<FormattedMessage
id="xpack.ml.datavisualizer.selector.dataVisualizerTitle"
defaultMessage="Data Visualizer"
/>
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
@ -56,8 +71,11 @@ export function DatavisualizerSelector() {
<EuiFlexGroup gutterSize="xl">
<EuiFlexItem grow={false}>
<EuiText color="subdued">
The Machine Learning Data Visualizer tool helps you understand your data, by analyzing the metrics and fields in
a log file or an existing Elasticsearch index.
<FormattedMessage
id="xpack.ml.datavisualizer.selector.dataVisualizerDescription"
defaultMessage="The Machine Learning Data Visualizer tool helps you understand your data,
by analyzing the metrics and fields in a log file or an existing Elasticsearch index."
/>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
@ -66,16 +84,37 @@ export function DatavisualizerSelector() {
<EuiFlexItem>
<EuiCard
icon={<EuiIcon size="xxl" type="addDataApp" />}
title="Import data"
description="Import data from a log file. You can upload files up to 100 MB."
betaBadgeLabel="Experimental"
betaBadgeTooltipContent="Experimental feature. We'd love to hear your feedback."
title={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.importDataTitle"
defaultMessage="Import data"
/>
}
description={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.importDataDescription"
defaultMessage="Import data from a log file. You can upload files up to 100 MB."
/>
}
betaBadgeLabel={props.intl.formatMessage({
id: 'xpack.ml.datavisualizer.selector.experimentalBadgeLabel',
defaultMessage: 'Experimental'
})}
betaBadgeTooltipContent={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.experimentalBadgeTooltipLabel"
defaultMessage="Experimental feature. We'd love to hear your feedback."
/>
}
footer={
<EuiButton
target="_self"
href="#/filedatavisualizer"
>
Upload file
<FormattedMessage
id="xpack.ml.datavisualizer.selector.uploadFileButtonLabel"
defaultMessage="Upload file"
/>
</EuiButton>
}
/>
@ -83,14 +122,27 @@ export function DatavisualizerSelector() {
<EuiFlexItem>
<EuiCard
icon={<EuiIcon size="xxl" type="dataVisualizer" />}
title="Select an index pattern"
description="Visualize the data in an existing Elasticsearch index."
title={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.selectIndexPatternTitle"
defaultMessage="Select an index pattern"
/>
}
description={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.selectIndexPatternDescription"
defaultMessage="Visualize the data in an existing Elasticsearch index."
/>
}
footer={
<EuiButton
target="_self"
href="#datavisualizer_index_select"
>
Select index
<FormattedMessage
id="xpack.ml.datavisualizer.selector.selectIndexButtonLabel"
defaultMessage="Select index"
/>
</EuiButton>
}
/>
@ -103,14 +155,22 @@ export function DatavisualizerSelector() {
<EuiFlexGroup justifyContent="spaceAround" gutterSize="xl">
<EuiFlexItem grow={false} style={{ width: '600px' }}>
<EuiCard
title="Start trial"
title={
<FormattedMessage
id="xpack.ml.datavisualizer.selector.startTrialTitle"
defaultMessage="Start trial"
/>
}
description={startTrialDescription()}
footer={
<EuiButton
target="_blank"
href="kibana#/management/elasticsearch/license_management/home"
>
Start trial
<FormattedMessage
id="xpack.ml.datavisualizer.selector.startTrialButtonLabel"
defaultMessage="Start trial"
/>
</EuiButton>
}
/>
@ -121,4 +181,4 @@ export function DatavisualizerSelector() {
</EuiPageBody>
</EuiPage>
);
}
});

View file

@ -6,6 +6,8 @@
import 'ngreact';
import { injectI18nProvider } from '@kbn/i18n/react';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
@ -35,5 +37,5 @@ import { DatavisualizerSelector } from './datavisualizer_selector';
module.directive('datavisualizerSelector', function ($injector) {
const reactDirective = $injector.get('reactDirective');
return reactDirective(DatavisualizerSelector, undefined, { restrict: 'E' }, { });
return reactDirective(injectI18nProvider(DatavisualizerSelector), undefined, { restrict: 'E' }, { });
});