Translations for Dev Tools (#23951)

translate dev-tools-console
This commit is contained in:
Nox911 2018-10-31 17:54:31 +03:00 committed by pavel06081991
parent e13e47fc4e
commit f8d0604050
27 changed files with 423 additions and 136 deletions

View file

@ -1,6 +1,7 @@
{
"paths": {
"common.ui": "src/ui",
"console": "src/core_plugins/console",
"inputControl":"src/core_plugins/input_control_vis",
"kbn": "src/core_plugins/kibana",
"kbnVislibVisTypes": "src/core_plugins/kbn_vislib_vis_types",
@ -12,10 +13,12 @@
"statusPage": "src/core_plugins/status_page",
"tileMap": "src/core_plugins/tile_map",
"tagCloud": "src/core_plugins/tagcloud",
"xpack.grokDebugger": "x-pack/plugins/grokdebugger",
"xpack.idxMgmt": "x-pack/plugins/index_management",
"xpack.watcher": "x-pack/plugins/watcher",
"xpack.rollupJobs": "x-pack/plugins/rollup",
"xpack.security": "x-pack/plugins/security"
"xpack.searchProfiler": "x-pack/plugins/searchprofiler",
"xpack.security": "x-pack/plugins/security",
"xpack.watcher": "x-pack/plugins/watcher"
},
"exclude": [
"src/ui/ui_render/bootstrap/app_bootstrap.js",

View file

@ -3,7 +3,7 @@
<div class="conApp__editor">
<ul class="conApp__autoComplete" id="autocomplete"></ul>
<div class="conApp__editorActions" id="ConAppEditorActions">
<kbn-tooltip text="click to send request">
<kbn-tooltip text="{{:: 'console.sendRequestButtonTooltip' | i18n: { defaultMessage: 'click to send request' } }}">
<button
class="conApp__editorActionButton conApp__editorActionButton--success"
ng-click="sendSelected()"
@ -17,7 +17,7 @@
class="conApp__editorActionButton"
dropdown-toggle
ng-click="getDocumentation()"
aria-label="Request options"
aria-label="{{:: 'console.requestOptionsButtonAriaLabel' | i18n: { defaultMessage: 'Request options' } }}"
>
<span class="kuiIcon fa-wrench"></span>
</button>
@ -28,13 +28,22 @@
aria-labelledby="consoleRequestOptions"
>
<li role="menuitem">
<button id="ConCopyAsCurl">Copy as cURL</button>
<button
id="ConCopyAsCurl"
i18n-id="console.requestOptions.copyAsUrlButtonLabel"
i18n-default-message="Copy as cURL"></button>
</li>
<li role="menuitem" ng-if="documentation">
<button ng-click="openDocumentation(documentation)">Open documentation</button>
<button
ng-click="openDocumentation(documentation)"
i18n-id="console.requestOptions.openDocumentationButtonLabel"
i18n-default-message="Open documentation"></button>
</li>
<li role="menuitem">
<button ng-click="autoIndent($event)">Auto indent</button>
<button
ng-click="autoIndent($event)"
i18n-id="console.requestOptions.autoIndentButtonLabel"
i18n-default-message="Auto indent"></button>
</li>
</ul>
</span>

View file

@ -29,6 +29,7 @@ import { URL_PATH_END_MARKER } from './autocomplete/components';
import _ from 'lodash';
import ace from 'brace';
import 'brace/ext/language_tools';
import { i18n } from '@kbn/i18n';
const AceRange = ace.acequire('ace/range').Range;
@ -738,7 +739,7 @@ export default function (editor) {
context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({
name: m,
score: -i,
meta: 'method'
meta: i18n.translate('console.autocomplete.addMethodMetaText', { defaultMessage: 'method' }),
}));
}

View file

@ -20,7 +20,7 @@
import { KbnTopNavControllerProvider } from 'ui/kbn_top_nav/kbn_top_nav_controller';
import storage from '../storage';
export function SenseTopNavController(Private) {
export function SenseTopNavController(Private, i18n) {
const KbnTopNavController = Private(KbnTopNavControllerProvider);
const controller = new KbnTopNavController([
@ -32,19 +32,25 @@ export function SenseTopNavController(Private) {
},
{
key: 'history',
description: 'History',
description: i18n('console.topNav.historyTabDescription', {
defaultMessage: 'History',
}),
template: `<sense-history></sense-history>`,
testId: 'consoleHistoryButton',
},
{
key: 'settings',
description: 'Settings',
description: i18n('console.topNav.settingsTabDescription', {
defaultMessage: 'Settings',
}),
template: `<sense-settings></sense-settings>`,
testId: 'consoleSettingsButton',
},
{
key: 'help',
description: 'Help',
description: i18n('console.topNav.helpTabDescription', {
defaultMessage: 'Help',
}),
template: `<sense-help></sense-help>`,
testId: 'consoleHelpButton',
},

View file

@ -1,39 +1,94 @@
<h2 class="euiTitle euiTitle--small">Help</h2>
<h2
class="euiTitle euiTitle--small"
i18n-id="console.helpPage.pageTitle"
i18n-default-message="Help"
></h2>
<div class="euiSpacer euiSpacer--m"></div>
<div class="euiPanel euiPanel--paddingLarge">
<div class="euiFlexGroup euiFlexGroup--gutterExtraLarge">
<div class="euiFlexItem">
<h3 class="euiTitle euiTitle--xsmall">Request format</h3>
<h3
class="euiTitle euiTitle--xsmall"
i18n-id="console.helpPage.requestFormatTitle"
i18n-default-message="Request format"
></h3>
<div class="euiSpacer euiSpacer--l"></div>
You can type one or more requests in the white editor. Console understands requests in a compact format:
<span
i18n-id="console.helpPage.requestFormatDescription"
i18n-default-message="You can type one or more requests in the white editor. Console understands requests in a compact format:"
></span>
<sense-help-example class="conHelp__example"></sense-help-example>
</div>
<div class="euiFlexItem">
<h3 class="euiTitle euiTitle--xsmall">Keyboard commands</h3>
<h3
i18n-id="console.helpPage.keyboardCommandsTitle"
i18n-default-message="Keyboard commands"
class="euiTitle euiTitle--xsmall"
></h3>
<div class="euiSpacer euiSpacer--l"></div>
<dl class="euiDescriptionList euiDescriptionList--row euiDescriptionList--compressed">
<dt class="euiDescriptionList__title">Ctrl/Cmd + I</dt>
<dd class="euiDescriptionList__description">Auto indent current request</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.autoIndentDescription"
i18n-default-message="Auto indent current request"
></dd>
<dt class="euiDescriptionList__title">Ctrl/Cmd + /</dt>
<dd class="euiDescriptionList__description">Open documentation for current request</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.openDocumentationDescription"
i18n-default-message="Open documentation for current request"
></dd>
<dt class="euiDescriptionList__title">Ctrl + Space</dt>
<dd class="euiDescriptionList__description">Open Auto complete (even if not typing)</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.openAutoCompleteDescription"
i18n-default-message="Open Auto complete (even if not typing)"
></dd>
<dt class="euiDescriptionList__title">Ctrl/Cmd + Enter</dt>
<dd class="euiDescriptionList__description">Submit request</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.submitRequestDescription"
i18n-default-message="Submit request"
></dd>
<dt class="euiDescriptionList__title">Ctrl/Cmd + Up/Down</dt>
<dd class="euiDescriptionList__description">Jump to the previous/next request start or end.</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.jumpToPreviousNextRequestDescription"
i18n-default-message="Jump to the previous/next request start or end."
></dd>
<dt class="euiDescriptionList__title">Ctrl/Cmd + Alt + L</dt>
<dd class="euiDescriptionList__description">Collapse/expand current scope.</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.collapseExpandCurrentScopeDescription"
i18n-default-message="Collapse/expand current scope."
></dd>
<dt class="euiDescriptionList__title">Ctrl/Cmd + Option + 0</dt>
<dd class="euiDescriptionList__description">Collapse all scopes but the current one. Expand by adding a shift.</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.collapseAllScopesDescription"
i18n-default-message="Collapse all scopes but the current one. Expand by adding a shift."
></dd>
<dt class="euiDescriptionList__title">Down arrow</dt>
<dd class="euiDescriptionList__description">Switch focus to auto-complete menu. Use arrows to further select a term</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.switchFocusToAutoCompleteMenuDescription"
i18n-default-message="Switch focus to auto-complete menu. Use arrows to further select a term"
></dd>
<dt class="euiDescriptionList__title">Enter/Tab</dt>
<dd class="euiDescriptionList__description">Select the currently selected or the top most term in auto-complete menu</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.selectCurrentlySelectedInAutoCompleteMenuDescription"
i18n-default-message="Select the currently selected or the top most term in auto-complete menu"
></dd>
<dt class="euiDescriptionList__title">Esc</dt>
<dd class="euiDescriptionList__description">Close auto-complete menu</dd>
<dd
class="euiDescriptionList__description"
i18n-id="console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription"
i18n-default-message="Close auto-complete menu"
></dd>
</dl>
</div>
</div>

View file

@ -1,4 +1,8 @@
<h2 class="kuiLocalDropdownTitle">History</h2>
<h2
class="kuiLocalDropdownTitle"
i18n-id="console.historyPage.pageTitle"
i18n-default-message="History"
></h2>
<div class="conHistory__body">
<ul
@ -8,7 +12,7 @@
aria-activedescendant="historyReq{{ history.selectedIndex }}"
scrollto-activedescendant
ng-keydown="history.onKeyDown($event)"
aria-label="History of sent requests"
aria-label="{{:: 'console.historyPage.requestListAriaLabel' | i18n: { defaultMessage: 'History of sent requests' } }}"
>
<li
class="list-group-item conHistory__req"
@ -20,7 +24,7 @@
ng-mouseenter="history.viewingReq = req"
ng-mouseleave="history.viewingReq = history.selectedReq"
ng-dblclick="history.restore(req)"
aria-label="{{:: 'Request: ' + history.describeReq(req) }}"
aria-label="{{:: 'console.historyPage.itemOfRequestListAriaLabel' | i18n: { defaultMessage: 'Request: {historyItem}', values: { historyItem: history.describeReq(req) },} }}"
aria-selected="{{ history.selectedReq === req }}"
>
{{ history.describeReq(req) }}
@ -32,12 +36,18 @@
</div>
<div class="conHistory__footer">
<button class="kuiButton kuiButton--danger" ng-click="history.clear()">Clear</button>
<button
class="kuiButton kuiButton--danger"
ng-click="history.clear()"
i18n-id="console.historyPage.clearHistoryButtonLabel"
i18n-default-message="Clear"
></button>
<button
class="kuiButton kuiButton--primary"
ng-disabled="!history.selectedReq"
ng-click="history.restore()"
i18n-id="console.historyPage.applyHistoryButtonLabel"
i18n-default-message="Apply"
>
Apply
</button>
</div>

View file

@ -23,7 +23,7 @@ import { useResizeChecker } from '../sense_editor_resize';
require('ui/modules')
.get('app/sense')
.directive('senseHistoryViewer', function () {
.directive('senseHistoryViewer', function (i18n) {
return {
restrict: 'E',
scope: {
@ -42,7 +42,9 @@ require('ui/modules')
viewer.setValue(s);
viewer.clearSelection();
} else {
viewer.getSession().setValue('No history available');
viewer.getSession().setValue(
i18n('console.historyPage.noHistoryTextMessage', { defaultMessage: 'No history available' })
);
}
});

View file

@ -23,7 +23,7 @@ const storage = require('../storage');
require('ui/modules')
.get('app/sense')
.directive('senseWelcome', function () {
.directive('senseWelcome', function (i18n) {
return {
restrict: 'E',
template: require('./welcome.html'),
@ -31,6 +31,9 @@ require('ui/modules')
$scope.$on('$destroy', function () {
storage.set('version_welcome_shown', '@@SENSE_REVISION');
});
}
$scope.asWellAsFragmentText = i18n('console.welcomePage.supportedRequestFormatDescription.asWellAsFragmentText', {
defaultMessage: 'as well as'
});
},
};
});

View file

@ -1,4 +1,8 @@
<h2 class="kuiLocalDropdownTitle">Settings</h2>
<h2
class="kuiLocalDropdownTitle"
i18n-id="console.settingsPage.pageTitle"
i18n-default-message="Settings"
></h2>
<form class="form" name="settingsForm" ng-submit="settingsForm.$valid && settings.apply()">
<fieldset
@ -9,9 +13,9 @@
<legend
id="consoleFontSize"
class="kuiLocalDropdownHeader__label"
>
Font Size
</legend>
i18n-id="console.settingsPage.fontSizeLabel"
i18n-default-message="Font Size"
></legend>
</div>
<input
@ -32,9 +36,11 @@
ng-model="settings.vals.wrapMode"
aria-describedby="consoleFontSize"
>
<span class="kuiCheckBoxLabel__text">
Wrap long lines
</span>
<span
class="kuiCheckBoxLabel__text"
i18n-id="console.settingsPage.wrapLongLinesLabelText"
i18n-default-message="Wrap long lines"
></span>
</label>
</fieldset>
@ -46,9 +52,9 @@
<legend
id="consoleAutocomplete"
class="kuiLocalDropdownHeader__label"
>
Autocomplete
</legend>
i18n-id="console.settingsPage.autocompleteLabel"
i18n-default-message="Autocomplete"
></legend>
</div>
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
@ -59,9 +65,11 @@
ng-model="settings.vals.autocomplete.fields"
aria-describedby="consoleAutocomplete"
>
<span class="kuiCheckBoxLabel__text">
Fields
</span>
<span
class="kuiCheckBoxLabel__text"
i18n-id="console.settingsPage.fieldsLabelText"
i18n-default-message="Fields"
></span>
</label>
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
@ -72,9 +80,11 @@
ng-model="settings.vals.autocomplete.indices"
aria-describedby="consoleAutocomplete"
>
<span class="kuiCheckBoxLabel__text">
Indices &amp; Aliases
</span>
<span
class="kuiCheckBoxLabel__text"
i18n-id="console.settingsPage.indicesAndAliasesLabelText"
i18n-default-message="Indices &amp; Aliases"
></span>
</label>
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
@ -85,9 +95,11 @@
ng-model="settings.vals.autocomplete.templates"
aria-describedby="consoleAutocomplete"
>
<span class="kuiCheckBoxLabel__text">
Templates
</span>
<span
class="kuiCheckBoxLabel__text"
i18n-id="console.settingsPage.templatesLabelText"
i18n-default-message="Templates"
></span>
</label>
</fieldset>
@ -95,17 +107,17 @@
<button
ng-click="kbnTopNav.close()"
class="kuiButton kuiButton--hollow"
>
Cancel
</button>
i18n-id="console.settingsPage.cancelButtonLabel"
i18n-default-message="Cancel"
></button>
<button
type="submit"
ng-disabled="settingsForm.$invalid"
class="kuiButton kuiButton--primary"
data-test-subj="settings-save-button"
>
Save
</button>
i18n-id="console.settingsPage.saveButtonLabel"
i18n-default-message="Save"
></button>
</div>
</form>

View file

@ -1,28 +1,66 @@
<div class="euiText">
<h2>Welcome to Console</h2>
<h2
i18n-id="console.welcomePage.pageTitle"
i18n-default-message="Welcome to Console"
></h2>
<p><strong>Quick intro to the UI</strong></p>
<p>The Console UI is split into two panes: an editor pane (left) and a response pane (right).
Use the editor to type requests and submit them to Elasticsearch. The results will be displayed in
the response pane on the right side.
<p>
<strong
i18n-id="console.welcomePage.quickIntroTitle"
i18n-default-message="Quick intro to the UI"
></strong>
</p>
<p>Console understands requests in a compact format, similar to cURL:
<p
i18n-id="console.welcomePage.quickIntroDescription"
i18n-default-message="The Console UI is split into two panes: an editor pane (left) and a response pane (right).
Use the editor to type requests and submit them to Elasticsearch. The results will be displayed in
the response pane on the right side."
></p>
<p
i18n-id="console.welcomePage.supportedRequestFormatTitle"
i18n-default-message="Console understands requests in a compact format, similar to cURL:"
></p>
<sense-help-example></sense-help-example>
<p>While typing a request, Console will make suggestions which you can then accept by hitting Enter/Tab.
These suggestions are made based on the request structure <i>as well as</i> your indices and types.
<p
i18n-id="console.welcomePage.supportedRequestFormatDescription"
i18n-default-message="While typing a request, Console will make suggestions which you can then accept by hitting Enter/Tab.
These suggestions are made based on the request structure {asWellAs} your indices and types."
i18n-values="{ asWellAs: '<i>' + asWellAsFragmentText + '</i>' }"
>
</p>
<p><strong>A few quick tips, while I have your attention</strong></p>
<p>
<strong
i18n-id="console.welcomePage.quickTipsTitle"
i18n-default-message="A few quick tips, while I have your attention"
>
</strong>
</p>
<ul>
<li>Submit requests to ES using the green triangle button.</li>
<li>Use the wrench menu for other useful things.</li>
<li>You can paste requests in cURL format and they will be translated to the Console syntax.</li>
<li>You can resize the editor and output panes by dragging the separator between them.</li>
<li>Study the keyboard shortcuts under the Help button. Good stuff in there!</li>
<li
i18n-id="console.welcomePage.quickTips.submitRequestDescription"
i18n-default-message="Submit requests to ES using the green triangle button."
></li>
<li
i18n-id="console.welcomePage.quickTips.useWrenchMenuDescription"
i18n-default-message="Use the wrench menu for other useful things."
></li>
<li
i18n-id="console.welcomePage.quickTips.cUrlFormatForRequestsDescription"
i18n-default-message="You can paste requests in cURL format and they will be translated to the Console syntax."
></li>
<li
i18n-id="console.welcomePage.quickTips.resizeEditorDescription"
i18n-default-message="You can resize the editor and output panes by dragging the separator between them."
></li>
<li
i18n-id="console.welcomePage.quickTips.keyboardShortcutsDescription"
i18n-default-message="Study the keyboard shortcuts under the Help button. Good stuff in there!"
></li>
</ul>
<button
@ -30,8 +68,9 @@
class="kuiButton kuiButton--primary"
data-test-subj="help-close-button"
ng-click="kbnTopNav.close()"
i18n-id="console.welcomePage.closeButtonLabel"
i18n-default-message="Get to work"
>
Get to work
</button>
</div>

View file

@ -8,11 +8,21 @@
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
FeatureCatalogueRegistryProvider.register(() => {
FeatureCatalogueRegistryProvider.register(i18n => {
return {
id: 'grokdebugger',
title: 'Grok Debugger',
description: 'Simulate and debug grok patterns for data transformation on ingestion.',
title: i18n('xpack.grokDebugger.registryProviderTitle', {
defaultMessage: '{grokLogParsingTool} Debugger',
values: {
grokLogParsingTool: 'Grok'
}
}),
description: i18n('xpack.grokDebugger.registryProviderDescription', {
defaultMessage: 'Simulate and debug {grokLogParsingTool} patterns for data transformation on ingestion.',
values: {
grokLogParsingTool: 'grok'
}
}),
icon: 'grokApp',
path: '/app/kibana#/dev_tools/grokdebugger',
showOnHomePage: false,

View file

@ -15,6 +15,7 @@ import {
EuiSpacer
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { FormattedMessage } from '@kbn/i18n/react';
export function CustomPatternsInput({ value, onChange }) {
const sampleCustomPatterns = `POSTFIX_QUEUEID [0-9A-F]{10,11}
@ -23,14 +24,24 @@ MSG message-id=<%{GREEDYDATA}>`;
return (
<EuiAccordion
id="customPatternsInput"
buttonContent="Custom Patterns"
buttonContent={(
<FormattedMessage
id="xpack.grokDebugger.customPatternsButtonLabel"
defaultMessage="Custom Patterns"
/>
)}
data-test-subj="btnToggleCustomPatternsInput"
>
<EuiSpacer size="m" />
<EuiCallOut
title="Enter one custom pattern per line. For example:"
title={(
<FormattedMessage
id="xpack.grokDebugger.customPatterns.callOutTitle"
defaultMessage="Enter one custom pattern per line. For example:"
/>
)}
>
<EuiCodeBlock>
{ sampleCustomPatterns }

View file

@ -11,11 +11,17 @@ import {
EuiCodeEditor
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { FormattedMessage } from '@kbn/i18n/react';
export function EventInput({ value, onChange }) {
return (
<EuiFormRow
label="Sample Data"
label={(
<FormattedMessage
id="xpack.grokDebugger.sampleDataLabel"
defaultMessage="Sample Data"
/>
)}
fullWidth
data-test-subj="aceEventInput"
>

View file

@ -10,11 +10,17 @@ import {
EuiPanel,
EuiCodeEditor
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export function EventOutput({ value }) {
return (
<EuiFormRow
label="Structured Data"
label={(
<FormattedMessage
id="xpack.grokDebugger.structuredDataLabel"
defaultMessage="Structured Data"
/>
)}
fullWidth
data-test-subj="aceEventOutput"
>

View file

@ -20,6 +20,7 @@ import { CustomPatternsInput } from '../custom_patterns_input';
import { EventOutput } from '../event_output';
import { GrokdebuggerRequest } from '../../../../models/grokdebugger_request';
import { toastNotifications } from 'ui/notify';
import { FormattedMessage } from '@kbn/i18n/react';
export class GrokDebugger extends React.Component {
constructor(props) {
@ -123,7 +124,10 @@ export class GrokDebugger extends React.Component {
isDisabled={this.isSimulateDisabled()}
data-test-subj="btnSimulate"
>
Simulate
<FormattedMessage
id="xpack.grokDebugger.simulateButtonLabel"
defaultMessage="Simulate"
/>
</EuiButton>
<EuiSpacer />
<EventOutput value={this.state.structuredEvent} />

View file

@ -12,11 +12,17 @@ import {
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { GrokMode } from '../../../../lib/ace';
import { FormattedMessage } from '@kbn/i18n/react';
export function PatternInput({ value, onChange }) {
return (
<EuiFormRow
label="Grok Pattern"
label={(
<FormattedMessage
id="xpack.grokDebugger.grokPatternLabel"
defaultMessage="Grok Pattern"
/>
)}
fullWidth
data-test-subj="acePatternInput"
>

View file

@ -9,6 +9,7 @@ import 'plugins/grokdebugger/services/grokdebugger';
import { GrokDebugger } from '../../components/grok_debugger';
import { render } from 'react-dom';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
const app = uiModules.get('xpack/grokdebugger');
@ -18,7 +19,7 @@ app.directive('grokdebugger', function ($injector) {
return {
restrict: 'E',
link: (scope, el) => {
render(<GrokDebugger grokdebuggerService={grokdebuggerService} />, el[0]);
render(<I18nProvider><GrokDebugger grokdebuggerService={grokdebuggerService} /></I18nProvider>, el[0]);
}
};
});

View file

@ -7,12 +7,14 @@
import { DevToolsRegistryProvider } from 'ui/registry/dev_tools';
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
DevToolsRegistryProvider.register((Private) => {
DevToolsRegistryProvider.register((Private, i18n) => {
const xpackInfo = Private(XPackInfoProvider);
return {
order: 6,
name: 'grokdebugger',
display: 'Grok Debugger',
display: i18n('xpack.grokDebugger.displayName', {
defaultMessage: 'Grok Debugger',
}),
url: '#/dev_tools/grokdebugger',
disabled: !xpackInfo.get('features.grokdebugger.enableLink', false),
tooltipContent: xpackInfo.get('features.grokdebugger.message')

View file

@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export function checkLicense(xpackLicenseInfo) {
// If, for some reason, we cannot get the license information
// from Elasticsearch, assume worst case and disable the Watcher UI
@ -11,7 +13,12 @@ export function checkLicense(xpackLicenseInfo) {
return {
enableLink: false,
enableAPIRoute: false,
message: 'You cannot use the Grok Debugger because license information is not available at this time.'
message: i18n.translate('xpack.grokDebugger.unavailableLicenseInformationMessage', {
defaultMessage: 'You cannot use the {grokLogParsingTool} Debugger because license information is not available at this time.',
values: {
grokLogParsingTool: 'Grok'
}
}),
};
}
@ -23,7 +30,13 @@ export function checkLicense(xpackLicenseInfo) {
return {
enableLink: false,
enableAPIRoute: false,
message: `You cannot use the Grok Debugger because your ${licenseType} license has expired.`
message: i18n.translate('xpack.grokDebugger.licenseHasExpiredMessage', {
defaultMessage: 'You cannot use the {grokLogParsingTool} Debugger because your {licenseType} license has expired.',
values: {
licenseType,
grokLogParsingTool: 'Grok'
},
}),
};
}

View file

@ -5,6 +5,7 @@
*/
import { get, isEmpty, omit } from 'lodash';
import { i18n } from '@kbn/i18n';
/**
* This model captures the grok debugger response from upstream to be passed to
@ -21,7 +22,14 @@ export class GrokdebuggerResponse {
const docs = get(upstreamGrokdebuggerResponse, 'docs');
const error = docs[0].error;
if (!isEmpty(error)) {
const opts = { 'error': 'Provided Grok patterns do not match data in the input' };
const opts = { 'error': i18n.translate(
'xpack.grokDebugger.patternsErrorMessage', {
defaultMessage: 'Provided {grokLogParsingTool} patterns do not match data in the input',
values: {
grokLogParsingTool: 'Grok'
}
}
), };
return new GrokdebuggerResponse(opts);
}
const structuredEvent = omit(get(docs, '0.doc._source'), 'rawEvent');

View file

@ -29,7 +29,19 @@ import template from './templates/index.html';
import { defaultQuery } from './templates/default_query';
uiRoutes.when('/dev_tools/searchprofiler', {
template: template
template: template,
controller: ($scope, i18n) => {
$scope.registerLicenseLinkLabel = i18n('xpack.searchProfiler.registerLicenseLinkLabel',
{ defaultMessage: 'register a license' });
$scope.trialLicense = i18n('xpack.searchProfiler.trialLicenseTitle',
{ defaultMessage: 'Trial' });
$scope.basicLicense = i18n('xpack.searchProfiler.basicLicenseTitle',
{ defaultMessage: 'Basic' });
$scope.goldLicense = i18n('xpack.searchProfiler.goldLicenseTitle',
{ defaultMessage: 'Gold' });
$scope.platinumLicense = i18n('xpack.searchProfiler.platinumLicenseTitle',
{ defaultMessage: 'Platinum' });
},
});
uiModules

View file

@ -2,15 +2,38 @@
<b>{{detailRow.indexName}}</b>
<p>[{{detailRow.shardID}}][{{detailRow.shardNumber}}]</p>
<br/>
<b>Type</b>
<b
i18n-id="xpack.searchProfiler.highlightDetails.typeTitle"
i18n-default-message="Type"
></b>
<p>{{detailRow.query_type}}</p>
<b>Description</b>
<b
i18n-id="xpack.searchProfiler.highlightDetails.descriptionTitle"
i18n-default-message="Description"
></b>
<p>{{detailRow.lucene}}</p>
<b><span tooltip="The total time spent at this query component, inclusive of children" tooltip-placement="left">Total Time</span></b>
<b>
<span
tooltip="{{:: 'xpack.searchProfiler.highlightDetails.totalTimeTooltip' | i18n: { defaultMessage: 'The total time spent at this query component, inclusive of children' } }}"
tooltip-placement="left"
i18n-id="xpack.searchProfiler.highlightDetails.totalTimeTitle"
i18n-default-message="Total Time"
></span>
</b>
<p>{{detailRow.time | msToPretty:3 }}</p>
<b><span tooltip="The time spent by this query component alone, exclusive of children" tooltip-placement="left">Self Time</span></b>
<b>
<span
tooltip="{{:: 'xpack.searchProfiler.highlightDetails.selfTimeTooltip' | i18n: { defaultMessage: 'The time spent by this query component alone, exclusive of children' } }}"
tooltip-placement="left"
i18n-id="xpack.searchProfiler.highlightDetails.selfTimeTitle"
i18n-default-message="Self Time"
></span>
</b>
<p>{{detailRow.selfTime | msToPretty:3 }}</p>
<b>Timing Breakdown</b>
<b
i18n-id="xpack.searchProfiler.highlightDetails.timingBreakdownTitle"
i18n-default-message="Timing Breakdown"
></b>
<table class="prfDevTool__breakdown">
<tr style="background-color:{{breakdown.color}}" ng-repeat="breakdown in detailRow.breakdown">
<td><span tooltip="{{breakdown.tip}}" tooltip-placement="left">{{breakdown.key}}</span></td>

View file

@ -2,12 +2,18 @@
<div class="prfDevTool__shardDetails--dim">
<span
tooltip-placement="bottom"
tooltip="The cumulative time of all shards in the index. Note: this is not wall-clock time, as shards can execute in parallel.">
<h3>Cumulative Time: {{index.time[target] | msToPretty: 3}}</h3>
tooltip="{{:: 'xpack.searchProfiler.profileTree.cumulativeTimeTooltip' | i18n: { defaultMessage: 'The cumulative time of all shards in the index. Note: this is not wall-clock time, as shards can execute in parallel.' } }}">
<h3>{{:: 'xpack.searchProfiler.profileTree.cumulativeTimeTitle' | i18n: { defaultMessage: "Cumulative Time:" } }} {{ index.time[target] | msToPretty: 3 }}</h3>
</span><br/>
</div>
<div class="prfDevTool__shardDetails" style="margin-left:5px">
<h3><b>Index:</b> {{index.name}}</h3>
<div class="prfDevTool__shardDetails" style="margin-left:5px">
<h3>
<b
i18n-id="xpack.searchProfiler.profileTree.indexTitle"
i18n-default-message="Index:"
></b>
{{index.name}}
</h3>
</div>
<div ng-repeat="shard in index.shards">
<div class="prfDevTool__panel prfDevTool__shard">
@ -32,10 +38,26 @@
ng-hide="!shardVisibility"
ng-class="{'prfDevTool__panelBody' : shardVisibility}">
<div class="prfDevTool__tvHeader">
<div class="prfDevTool__cell prfDevTool__description">Type</div>
<div class="prfDevTool__cell prfDevTool__time">Self Time</div>
<div class="prfDevTool__cell prfDevTool__totalTime">Total Time</div>
<div class="prfDevTool__cell prfDevTool__percentage">% Time</div>
<div
class="prfDevTool__cell prfDevTool__description"
i18n-id="xpack.searchProfiler.profileTree.header.typeTitle"
i18n-default-message="Type"
></div>
<div
class="prfDevTool__cell prfDevTool__time"
i18n-id="xpack.searchProfiler.profileTree.header.selfTimeTitle"
i18n-default-message="Self Time"
></div>
<div
class="prfDevTool__cell prfDevTool__totalTime"
i18n-id="xpack.searchProfiler.profileTree.header.totalTimeTitle"
i18n-default-message="Total Time"
></div>
<div
class="prfDevTool__cell prfDevTool__percentage"
i18n-id="xpack.searchProfiler.profileTree.header.percentageTimeTitle"
i18n-default-message="% Time"
></div>
</div>
<div class="prfDevTool__tvRow"
ng-repeat="row in search.flat"

View file

@ -6,9 +6,11 @@
import { DevToolsRegistryProvider } from 'ui/registry/dev_tools';
DevToolsRegistryProvider.register(() => ({
DevToolsRegistryProvider.register(i18n => ({
order: 5,
name: 'searchprofiler',
display: 'Search Profiler',
display: i18n('xpack.searchProfiler.pageDisplayName', {
defaultMessage: 'Search Profiler',
}),
url: '#/dev_tools/searchprofiler'
}));

View file

@ -8,11 +8,15 @@
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
FeatureCatalogueRegistryProvider.register(() => {
FeatureCatalogueRegistryProvider.register(i18n => {
return {
id: 'searchprofiler',
title: 'Search Profiler',
description: 'Quickly check the performance of any Elasticsearch query.',
title: i18n('xpack.searchProfiler.registryProviderTitle', {
defaultMessage: 'Search Profiler',
}),
description: i18n('xpack.searchProfiler.registryProviderDescription', {
defaultMessage: 'Quickly check the performance of any Elasticsearch query.',
}),
icon: 'searchProfilerApp',
path: '/app/kibana#/dev_tools/searchprofiler',
showOnHomePage: false,

View file

@ -3,14 +3,14 @@
<div class="prfDevTool__wrapper">
<div class="prfDevTool__main">
<tabset ng-show="profileResponse.length > 0">
<tab heading="Query Profile"
<tab
heading="{{ 'xpack.searchProfiler.queryProfileTabTitle' | i18n: { defaultMessage: 'Query Profile' } }}"
active="activeTab.search"
ng-click="activateTab('search')"
disabled="!hasSearch">
<profileTree data="profileResponse" target="searches"></profileTree>
</tab>
<tab heading="Aggregation Profile"
active="activeTab.aggregations"
<tab heading="{{ 'xpack.searchProfiler.aggregationProfileTabTitle' | i18n: { defaultMessage: 'Aggregation Profile' } }}"
ng-click="activateTab('aggregations')"
disabled="!hasAggregations">
<profileTree data="profileResponse" target="aggregations"></profileTree>
@ -18,21 +18,27 @@
</tabset>
<!-- License error notice -->
<div class="kuiNotice" ng-hide="licenseEnabled">
<h2 class="kuiTitle kuiVerticalRhythmSmall">
<span class="kuiIcon fa-warning kuiIcon--error"></span>
License error
</h1>
<div class="kuiNotice" ng-hide="!licenseEnabled">
<h2
class="kuiTitle kuiVerticalRhythmSmall"
i18n-id="xpack.searchProfiler.licenseErrorMessageTitle"
i18n-default-message="{warningIcon} License error"
i18n-values="{ warningIcon: '<span class=\'kuiIcon fa-warning kuiIcon--error\'></span>' }"
></h2>
<p class="kuiText kuiVerticalRhythmSmall">
The Profiler Visualization requires an active license (<code>Trial</code>,
<code>Basic</code>, <code>Gold</code> or <code>Platinum</code>), but none were found in your cluster.
</p>
<p
class="kuiText kuiVerticalRhythmSmall"
i18n-id="xpack.searchProfiler.licenseErrorMessageDescription"
i18n-default-message="The Profiler Visualization requires an active license ({licenseTypeList} or {platinumLicenseType}), but none were found in your cluster."
i18n-values="{ licenseTypeList: '<code>' + trialLicense + '</code>, <code>' + basicLicense + '</code>, <code>' + goldLicense + '</code>', platinumLicenseType: '<code>' + platinumLicense + '</code>' }"
></p>
<p class="kuiText kuiVerticalRhythmSmall">
Please <a class="kuiLink" href="https://www.elastic.co/subscriptions" rel="noopener noreferrer">register a license</a>
to continue using the Search Profiler.
</p>
<p
class="kuiText kuiVerticalRhythmSmall"
i18n-id="xpack.searchProfiler.registerLicenseDescription"
i18n-default-message="Please {registerLicenseLink} to continue using the Search Profiler"
i18n-values="{ registerLicenseLink: '<a class=\'kuiLink\' href=\'https://www.elastic.co/subscriptions\' rel=\'noopener noreferrer\'>' + registerLicenseLinkLabel + '</a>' }"
></p>
</div>
</div>
@ -44,9 +50,9 @@
<label
class="kuiLabel"
for="searchProfilerIndexInput"
>
Index
</label>
i18n-id="xpack.searchProfiler.formIndexLabel"
i18n-default-message="Index"
></label>
</div>
<div class="kuiVerticalRhythmSmall">
@ -66,9 +72,9 @@
<label
class="kuiLabel"
for="searchProfilerTypeInput"
>
Type
</label>
i18n-id="xpack.searchProfiler.formTypeLabel"
i18n-default-message="Type"
></label>
</div>
<div class="kuiVerticalRhythmSmall">
@ -94,8 +100,9 @@
style="float:right;"
ng-click="profile()"
ng-disabled="!licenseEnabled || !query"
i18n-id="xpack.searchProfiler.formProfileButtonLabel"
i18n-default-message="Profile"
>
Profile
</button>
</div>
<aside class="prfDevTool__details">

View file

@ -4,20 +4,26 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export function checkLicense(xpackLicenseInfo) {
if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) {
return {
showAppLink: true,
enableAppLink: false,
message: 'Search Profiler is unavailable - license information is not available at this time.'
message: i18n.translate('xpack.searchProfiler.unavailableLicenseInformationMessage', {
defaultMessage: 'Search Profiler is unavailable - license information is not available at this time.',
}),
};
}
const isLicenseActive = xpackLicenseInfo.license.isActive();
let message;
if (!isLicenseActive) {
message = `Search Profiler is unavailable - license has expired.`;
message = i18n.translate('xpack.searchProfiler.licenseHasExpiredMessage', {
defaultMessage: 'Search Profiler is unavailable - license has expired.',
});
}
if (xpackLicenseInfo.license.isOneOf([ 'trial', 'basic', 'standard', 'gold', 'platinum' ])) {
@ -28,7 +34,11 @@ export function checkLicense(xpackLicenseInfo) {
};
}
message = `Search Profiler is unavailable for the current ${xpackLicenseInfo.license.getType()} license. Please upgrade your license.`;
message = i18n.translate('xpack.searchProfiler.upgradeLicenseMessage', {
defaultMessage:
'Search Profiler is unavailable for the current {licenseInfo} license. Please upgrade your license.',
values: { licenseInfo: xpackLicenseInfo.license.getType() }
});
return {
showAppLink: false,
enableAppLink: false,