[i18n] APM translations (Part 1) (#27384)

* Translation for APM utils, intex.js and register_feature.js

* Fix a typo
This commit is contained in:
Maryia Lapata 2018-12-18 18:30:26 +03:00 committed by GitHub
parent d19cafb397
commit d555241ca7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 47 deletions

View file

@ -16,6 +16,7 @@
"timelion": "src/legacy/core_plugins/timelion",
"tagCloud": "src/legacy/core_plugins/tagcloud",
"tsvb": "src/legacy/core_plugins/metrics",
"xpack.apm": "x-pack/plugins/apm",
"xpack.beatsManagement": "x-pack/plugins/beats_management",
"xpack.graph": "x-pack/plugins/graph",
"xpack.grokDebugger": "x-pack/plugins/grokdebugger",

View file

@ -13,6 +13,7 @@ import { initStatusApi } from './server/routes/status_check';
import { initTracesApi } from './server/routes/traces';
import mappings from './mappings';
import { makeApmUsageCollector } from './server/lib/apm_telemetry';
import { i18n } from '@kbn/i18n';
export function apm(kibana) {
return new kibana.Plugin({
@ -24,7 +25,9 @@ export function apm(kibana) {
uiExports: {
app: {
title: 'APM',
description: 'APM for the Elastic Stack',
description: i18n.translate('xpack.apm.apmForESDescription', {
defaultMessage: 'APM for the Elastic Stack'
}),
main: 'plugins/apm/index',
icon: 'plugins/apm/icon.svg',
euiIconType: 'apmApp',

View file

@ -11,13 +11,15 @@ import {
} from 'ui/registry/feature_catalogue';
if (chrome.getInjected('apmUiEnabled')) {
FeatureCatalogueRegistryProvider.register(() => {
FeatureCatalogueRegistryProvider.register(i18n => {
return {
id: 'apm',
title: 'APM',
description:
'Automatically collect in-depth performance metrics and ' +
'errors from inside your applications.',
description: i18n('xpack.apm.apmDescription', {
defaultMessage:
'Automatically collect in-depth performance metrics and ' +
'errors from inside your applications.'
}),
icon: 'apmApp',
path: '/app/apm',
showOnHomePage: true,

View file

@ -5,10 +5,18 @@
*/
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';
import { memoize } from 'lodash';
const SECONDS_CUT_OFF = 10 * 1000000; // 10 seconds (in microseconds)
const MILLISECONDS_CUT_OFF = 10 * 1000; // 10 milliseconds (in microseconds)
const SPACE = ' ';
const notAvailableLabel: string = i18n.translate(
'xpack.apm.formatters.notAvailableLabel',
{
defaultMessage: 'N/A'
}
);
/*
* value: time in microseconds
@ -23,45 +31,57 @@ interface FormatterOptions {
export function asSeconds(
value: FormatterValue,
{ withUnit = true, defaultValue = 'N/A' }: FormatterOptions = {}
{ withUnit = true, defaultValue = notAvailableLabel }: FormatterOptions = {}
) {
if (value == null) {
return defaultValue;
}
const secondsLabel =
SPACE +
i18n.translate('xpack.apm.formatters.secondsTimeUnitLabel', {
defaultMessage: 's'
});
const formatted = asDecimal(value / 1000000);
return `${formatted}${withUnit ? ' s' : ''}`;
return `${formatted}${withUnit ? secondsLabel : ''}`;
}
export function asMillis(
value: FormatterValue,
{ withUnit = true, defaultValue = 'N/A' }: FormatterOptions = {}
{ withUnit = true, defaultValue = notAvailableLabel }: FormatterOptions = {}
) {
if (value == null) {
return defaultValue;
}
const millisLabel =
SPACE +
i18n.translate('xpack.apm.formatters.millisTimeUnitLabel', {
defaultMessage: 'ms'
});
const formatted = asInteger(value / 1000);
return `${formatted}${withUnit ? ' ms' : ''}`;
return `${formatted}${withUnit ? millisLabel : ''}`;
}
export function asMicros(
value: FormatterValue,
{ withUnit = true, defaultValue = 'N/A' }: FormatterOptions = {}
{ withUnit = true, defaultValue = notAvailableLabel }: FormatterOptions = {}
) {
if (value == null) {
return defaultValue;
}
const microsLabel =
SPACE +
i18n.translate('xpack.apm.formatters.microsTimeUnitLabel', {
defaultMessage: 'μs'
});
const formatted = asInteger(value);
return `${formatted}${withUnit ? ' μs' : ''}`;
return `${formatted}${withUnit ? microsLabel : ''}`;
}
type TimeFormatter = (
max: number
) => (
value: FormatterValue,
{ withUnit, defaultValue }: FormatterOptions
) => string;
) => (value: FormatterValue, options: FormatterOptions) => string;
export const getTimeFormatter: TimeFormatter = memoize((max: number) => {
const unit = timeUnit(max);
@ -87,7 +107,7 @@ export function timeUnit(max: number) {
export function asTime(
value: FormatterValue,
{ withUnit = true, defaultValue = 'N/A' }: FormatterOptions = {}
{ withUnit = true, defaultValue = notAvailableLabel }: FormatterOptions = {}
) {
if (value == null) {
return defaultValue;
@ -105,7 +125,13 @@ export function asInteger(value: number) {
}
export function tpmUnit(type: string) {
return type === 'request' ? 'rpm' : 'tpm';
return type === 'request'
? i18n.translate('xpack.apm.formatters.requestsPerMinLabel', {
defaultMessage: 'rpm'
})
: i18n.translate('xpack.apm.formatters.transactionsPerMinLabel', {
defaultMessage: 'tpm'
});
}
export function asPercent(

View file

@ -37,38 +37,48 @@ export function initTimepicker(history, dispatch) {
uiModules
.get('app/apm', [])
.controller('TimePickerController', ($scope, globalState, $rootScope) => {
// Add APM feedback menu
// TODO: move this somewhere else
$scope.topNavMenu = [];
$scope.topNavMenu.push({
key: 'APM feedback',
description: 'APM feedback',
tooltip: 'Provide feedback on APM',
template: require('../../templates/feedback_menu.html')
});
.controller(
'TimePickerController',
($scope, globalState, $rootScope, i18n) => {
// Add APM feedback menu
// TODO: move this somewhere else
$scope.topNavMenu = [];
$scope.topNavMenu.push({
key: 'APM feedback',
label: i18n('xpack.apm.topNav.apmFeedbackLabel', {
defaultMessage: 'APM feedback'
}),
description: i18n('xpack.apm.topNav.apmFeedbackDescription', {
defaultMessage: 'APM feedback'
}),
tooltip: i18n('xpack.apm.topNav.apmFeedbackTooltip', {
defaultMessage: 'Provide feedback on APM'
}),
template: require('../../templates/feedback_menu.html')
});
history.listen(() => {
history.listen(() => {
updateRefreshRate(dispatch);
globalState.fetch(); // ensure global state is updated when url changes
});
// ensure that redux is notified after timefilter has updated
$scope.$listen(timefilter, 'timeUpdate', () =>
dispatch(updateTimePickerAction())
);
// ensure that timepicker updates when global state changes
registerTimefilterWithGlobalState(globalState, $rootScope);
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
dispatch(updateTimePickerAction());
updateRefreshRate(dispatch);
globalState.fetch(); // ensure global state is updated when url changes
});
// ensure that redux is notified after timefilter has updated
$scope.$listen(timefilter, 'timeUpdate', () =>
dispatch(updateTimePickerAction())
);
// ensure that timepicker updates when global state changes
registerTimefilterWithGlobalState(globalState, $rootScope);
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
dispatch(updateTimePickerAction());
updateRefreshRate(dispatch);
Promise.all([waitForAngularReady]).then(resolve);
});
Promise.all([waitForAngularReady]).then(resolve);
}
);
});
}

View file

@ -5,6 +5,7 @@
*/
import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import createHistory from 'history/createHashHistory';
import { get, isPlainObject, mapValues } from 'lodash';
import qs from 'querystring';
@ -26,6 +27,13 @@ const DEFAULT_KIBANA_TIME_RANGE = {
}
};
const viewJobLabel: string = i18n.translate(
'xpack.apm.viewMLJob.viewJobLabel',
{
defaultMessage: 'View Job'
}
);
interface ViewMlJobArgs {
serviceName: string;
transactionType: string;
@ -36,7 +44,7 @@ export const ViewMLJob: React.SFC<ViewMlJobArgs> = ({
serviceName,
transactionType,
location,
children = 'View Job'
children = viewJobLabel
}) => {
const pathname = '/app/ml';
const hash = '/timeseriesexplorer';