Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 26 additions & 15 deletions packages/kbn-i18n/src/angular/directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,37 @@ import { IDirective, IRootElementService, IScope } from 'angular';

import { I18nServiceType } from './provider';

export function i18nDirective(i18n: I18nServiceType): IDirective {
interface I18nScope extends IScope {
values: any;
defaultMessage: string;
id: string;
}

export function i18nDirective(i18n: I18nServiceType): IDirective<I18nScope> {
return {
restrict: 'A',
scope: {
id: '@i18nId',
defaultMessage: '@i18nDefaultMessage',
values: '=i18nValues',
values: '<i18nValues',
},
link($scope: IScope, $element: IRootElementService) {
$scope.$watchGroup(
['id', 'defaultMessage', 'values'],
([id, defaultMessage = '', values = {}]) => {
$element.html(
i18n(id, {
values,
defaultMessage,
})
);
}
);
link: function ($scope, $element) {
if ($scope.values) {
$scope.$watch('values', () => {
setHtmlContent($element, $scope, i18n);
});
} else {
setHtmlContent($element, $scope, i18n);
}
},
};
}
}

function setHtmlContent($element: IRootElementService, $scope: I18nScope, i18n: I18nServiceType) {
$element.html(
i18n($scope.id, {
values: $scope.values,
defaultMessage: $scope.defaultMessage,
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
data-test-subj="editIndexPattern"
class="kuiViewContent"
role="region"
aria-label="{{'kbn.management.editIndexPattern.detailsAria' | i18n: { defaultMessage: 'Index pattern details' } }}"
aria-label="{{::'kbn.management.editIndexPattern.detailsAria' | i18n: { defaultMessage: 'Index pattern details' } }}"
>
<!-- Header -->
<kbn-management-index-header
Expand Down Expand Up @@ -103,9 +103,9 @@
<input
class="kuiSearchInput__input"
type="text"
aria-label="{{'kbn.management.editIndexPattern.fields.filterAria' | i18n: {defaultMessage: 'Filter'} }}"
aria-label="{{::'kbn.management.editIndexPattern.fields.filterAria' | i18n: {defaultMessage: 'Filter'} }}"
ng-model="fieldFilter"
placeholder="{{'kbn.management.editIndexPattern.fields.filterPlaceholder' | i18n: {defaultMessage: 'Filter'} }}"
placeholder="{{::'kbn.management.editIndexPattern.fields.filterPlaceholder' | i18n: {defaultMessage: 'Filter'} }}"
data-test-subj="indexPatternFieldFilter"
>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<a
data-test-subj="indexPatternFieldEditButton"
ng-href="{{ kbnUrl.getRouteHref(field, 'edit') }}"
aria-label="{{'kbn.management.editIndexPattern.editFieldButton' | i18n: { defaultMessage: 'Edit' } }}"
aria-label="{{::'kbn.management.editIndexPattern.editFieldButton' | i18n: { defaultMessage: 'Edit' } }}"
class="kuiButton kuiButton--basic kuiButton--small"
>
<span aria-hidden="true" class="kuiIcon fa-pencil"></span>
Expand All @@ -12,7 +12,7 @@
ng-if="field.scripted"
ng-click="remove(field)"
class="kuiButton kuiButton--danger kuiButton--small"
aria-label="{{'kbn.management.editIndexPattern.deleteFieldButton' | i18n: { defaultMessage: 'Delete' } }}"
aria-label="{{::'kbn.management.editIndexPattern.deleteFieldButton' | i18n: { defaultMessage: 'Delete' } }}"
>
<span aria-hidden="true" class="kuiIcon fa-trash"></span>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<button
ng-if="setDefault"
ng-click="setDefault()"
aria-label="{{'kbn.management.editIndexPattern.setDefaultAria' | i18n: { defaultMessage: 'Set as default index' } }}"
tooltip="{{'kbn.management.editIndexPattern.setDefaultTooltip' | i18n: { defaultMessage: 'Set as default index' } }}"
aria-label="{{::'kbn.management.editIndexPattern.setDefaultAria' | i18n: { defaultMessage: 'Set as default index' } }}"
tooltip="{{::'kbn.management.editIndexPattern.setDefaultTooltip' | i18n: { defaultMessage: 'Set as default index' } }}"
class="kuiButton kuiButton--basic"
data-test-subj="setDefaultIndexPatternButton"
>
Expand All @@ -32,8 +32,8 @@
<button
ng-if="refreshFields"
ng-click="refreshFields()"
aria-label="{{'kbn.management.editIndexPattern.refreshAria' | i18n: { defaultMessage: 'Reload field list' } }}"
tooltip="{{'kbn.management.editIndexPattern.refreshTooltip' | i18n: { defaultMessage: 'Refresh field list' } }}"
aria-label="{{::'kbn.management.editIndexPattern.refreshAria' | i18n: { defaultMessage: 'Reload field list' } }}"
tooltip="{{::'kbn.management.editIndexPattern.refreshTooltip' | i18n: { defaultMessage: 'Refresh field list' } }}"
class="kuiButton kuiButton--basic"
>
<span
Expand All @@ -45,8 +45,8 @@
<button
ng-if="delete"
ng-click="delete()"
aria-label="{{'kbn.management.editIndexPattern.removeAria' | i18n: { defaultMessage: 'Remove index pattern' } }}"
tooltip="{{'kbn.management.editIndexPattern.removeTooltip' | i18n: { defaultMessage: 'Remove index pattern' } }}"
aria-label="{{::'kbn.management.editIndexPattern.removeAria' | i18n: { defaultMessage: 'Remove index pattern' } }}"
tooltip="{{::'kbn.management.editIndexPattern.removeTooltip' | i18n: { defaultMessage: 'Remove index pattern' } }}"
class="kuiButton kuiButton--danger"
data-test-subj="deleteIndexPatternButton"
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="col-md-2 sidebar-container" role="region" aria-label="{{'kbn.management.editIndexPatternAria' | i18n: { defaultMessage: 'Index patterns' } }}">
<div class="col-md-2 sidebar-container" role="region" aria-label="{{::'kbn.management.editIndexPatternAria' | i18n: { defaultMessage: 'Index patterns' } }}">
<div class="sidebar-list">
<div class="sidebar-item-title full-title">
<h5 data-test-subj="createIndexPatternParent">
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<p>{{ 'plugin_2.message-id' | i18n: { defaultMessage: 'Message text' } }}</p>
<p>{{ ::'plugin_2.message-id' | i18n: { defaultMessage: 'Message text' } }}</p>
12 changes: 12 additions & 0 deletions src/dev/i18n/extractors/__snapshots__/html.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ Array [
]
`;

exports[`dev/i18n/extractors/html extracts default messages from HTML with one-time binding 1`] = `
Array [
Array [
"kbn.id",
Object {
"context": undefined,
"message": "Message text with {value}",
},
],
]
`;

exports[`dev/i18n/extractors/html throws on empty i18n-id 1`] = `"Empty \\"i18n-id\\" value in angular directive is not allowed."`;

exports[`dev/i18n/extractors/html throws on missing i18n-default-message attribute 1`] = `"Empty defaultMessage in angular directive is not allowed (\\"message-id\\")."`;
21 changes: 20 additions & 1 deletion src/dev/i18n/extractors/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,33 @@ function trimCurlyBraces(string) {
return string.slice(2, -2).trim();
}

function trimParentheses(string) {
if (string.startsWith('(') && string.endsWith(')')) {
return string.slice(1, -1);
}

return string;
}

function trimOneTimeBindingOperator(string) {
if (string.startsWith('::')) {
return string.slice(2);
}

return string;
}

function* getFilterMessages(htmlContent) {
const expressions = (htmlContent.match(ANGULAR_EXPRESSION_REGEX) || [])
.filter(expression => expression.includes(I18N_FILTER_MARKER))
.map(trimCurlyBraces);

for (const expression of expressions) {
const filterStart = expression.indexOf(I18N_FILTER_MARKER);
const idExpression = expression.slice(0, filterStart).trim();
const idExpression = trimParentheses(
trimOneTimeBindingOperator(expression.slice(0, filterStart).trim())
);

const filterObjectExpression = expression.slice(filterStart + I18N_FILTER_MARKER.length).trim();

if (!filterObjectExpression || !idExpression) {
Expand Down
11 changes: 11 additions & 0 deletions src/dev/i18n/extractors/html.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ describe('dev/i18n/extractors/html', () => {
expect(actual.sort()).toMatchSnapshot();
});

test('extracts default messages from HTML with one-time binding', () => {
const actual = Array.from(
extractHtmlMessages(`
<div>
{{::'kbn.id' | i18n: { defaultMessage: 'Message text with {value}', values: { value: 'value' } }}}
</div>
`)
);
expect(actual.sort()).toMatchSnapshot();
});

test('throws on empty i18n-id', () => {
const source = Buffer.from(`\
<p
Expand Down