mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[i18n] remove angular i18n and move the remains to monitoring plugin (#115003)
This commit is contained in:
parent
c11b38de7b
commit
d19510535a
20 changed files with 23 additions and 538 deletions
|
@ -135,27 +135,6 @@ export const Component = () => {
|
|||
|
||||
Full details are {kib-repo}tree/master/packages/kbn-i18n#react[here].
|
||||
|
||||
|
||||
|
||||
[discrete]
|
||||
==== i18n for Angular
|
||||
|
||||
You are encouraged to use `i18n.translate()` by statically importing `i18n` from `@kbn/i18n` wherever possible in your Angular code. Angular wrappers use the translation `service` with the i18n engine under the hood.
|
||||
|
||||
The translation directive has the following syntax:
|
||||
["source","js"]
|
||||
-----------
|
||||
<ANY
|
||||
i18n-id="{string}"
|
||||
i18n-default-message="{string}"
|
||||
[i18n-values="{object}"]
|
||||
[i18n-description="{string}"]
|
||||
></ANY>
|
||||
-----------
|
||||
|
||||
Full details are {kib-repo}tree/master/packages/kbn-i18n#angularjs[here].
|
||||
|
||||
|
||||
[discrete]
|
||||
=== Resources
|
||||
|
||||
|
|
|
@ -489,7 +489,6 @@
|
|||
"@testing-library/react-hooks": "^5.1.1",
|
||||
"@testing-library/user-event": "^13.1.1",
|
||||
"@types/angular": "^1.6.56",
|
||||
"@types/angular-mocks": "^1.7.0",
|
||||
"@types/apidoc": "^0.22.3",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/babel__core": "^7.1.16",
|
||||
|
@ -644,7 +643,6 @@
|
|||
"@yarnpkg/lockfile": "^1.1.0",
|
||||
"abab": "^2.0.4",
|
||||
"aggregate-error": "^3.1.0",
|
||||
"angular-mocks": "^1.7.9",
|
||||
"antlr4ts-cli": "^0.5.0-alpha.3",
|
||||
"apidoc": "^0.29.0",
|
||||
"apidoc-markdown": "^6.0.0",
|
||||
|
|
|
@ -27,7 +27,6 @@ filegroup(
|
|||
)
|
||||
|
||||
NPM_MODULE_EXTRA_FILES = [
|
||||
"angular/package.json",
|
||||
"react/package.json",
|
||||
"package.json",
|
||||
"GUIDELINE.md",
|
||||
|
@ -47,7 +46,6 @@ TYPES_DEPS = [
|
|||
"//packages/kbn-babel-preset",
|
||||
"@npm//intl-messageformat",
|
||||
"@npm//tslib",
|
||||
"@npm//@types/angular",
|
||||
"@npm//@types/intl-relativeformat",
|
||||
"@npm//@types/jest",
|
||||
"@npm//@types/prop-types",
|
||||
|
|
|
@ -93,17 +93,6 @@ The long term plan is to rely on using `FormattedMessage` and `i18n.translate()`
|
|||
Currently, we support the following ReactJS `i18n` tools, but they will be removed in future releases:
|
||||
- Usage of `props.intl.formatmessage()` (where `intl` is passed to `props` by `injectI18n` HOC).
|
||||
|
||||
#### In AngularJS
|
||||
|
||||
The long term plan is to rely on using `i18n.translate()` by statically importing `i18n` from the `@kbn/i18n` package. **Avoid using the `i18n` filter and the `i18n` service injected in controllers, directives, services.**
|
||||
|
||||
- Call JS function `i18n.translate()` from the `@kbn/i18n` package.
|
||||
- Use `i18nId` directive in template.
|
||||
|
||||
Currently, we support the following AngluarJS `i18n` tools, but they will be removed in future releases:
|
||||
- Usage of `i18n` service in controllers, directives, services by injecting it.
|
||||
- Usage of `i18n` filter in template for attribute translation. Note: Use one-time binding ("{{:: ... }}") in filters wherever it's possible to prevent unnecessary expression re-evaluation.
|
||||
|
||||
#### In JavaScript
|
||||
|
||||
- Use `i18n.translate()` in NodeJS or any other framework agnostic code, where `i18n` is the I18n engine from `@kbn/i18n` package.
|
||||
|
@ -223,7 +212,6 @@ For example:
|
|||
- for button:
|
||||
|
||||
```js
|
||||
|
||||
<EuiButton data-test-subj="addScriptedFieldLink" href={addScriptedFieldUrl}>
|
||||
<FormattedMessage id="kbn.management.editIndexPattern.scripted.addFieldButtonLabel" defaultMessage="Add scripted field"/>
|
||||
</EuiButton>
|
||||
|
@ -232,11 +220,11 @@ For example:
|
|||
- for dropDown:
|
||||
|
||||
```js
|
||||
<select ng-model="indexedFieldTypeFilter" ng-options="o for o in indexedFieldTypes">
|
||||
<option value=""
|
||||
i18n-id="kbn.management.editIndexPattern.fields.allTypesDropDown"
|
||||
i18n-default-message="All field types"></option>
|
||||
</select>
|
||||
<option value={
|
||||
i18n.translate('kbn.management.editIndexPattern.fields.allTypesDropDown', {
|
||||
defaultMessage: 'All field types',
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
- for placeholder:
|
||||
|
@ -309,12 +297,6 @@ For example:
|
|||
|
||||
- Variables
|
||||
|
||||
```html
|
||||
<span i18n-id="kbn.management.editIndexPattern.timeFilterHeader"
|
||||
i18n-default-message="Time Filter field name: {timeFieldName}"
|
||||
i18n-values="{ timeFieldName: indexPattern.timeFieldName }"></span>
|
||||
```
|
||||
|
||||
```html
|
||||
<FormattedMessage
|
||||
id="kbn.management.createIndexPatternHeader"
|
||||
|
@ -327,25 +309,6 @@ For example:
|
|||
|
||||
- Labels and variables in tag
|
||||
|
||||
```html
|
||||
<span i18n-id="kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail"
|
||||
i18n-default-message="This page lists every field in the {indexPatternTitle} index"
|
||||
i18n-values="{ indexPatternTitle: '<strong>' + indexPattern.title + '</strong>' }"></span>
|
||||
```
|
||||
|
||||
-----------------------------------------------------------
|
||||
**BUT** we can not use tags that should be compiled:
|
||||
|
||||
```html
|
||||
<span i18n-id="kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail"
|
||||
i18n-default-message="This page lists every field in the {indexPatternTitle} index"
|
||||
i18n-values="{ indexPatternTitle: '<div my-directive>' + indexPattern.title + '</div>' }"></span>
|
||||
```
|
||||
|
||||
To void injections vulnerability, `i18nId` directive doesn't compile its values.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
```html
|
||||
<FormattedMessage
|
||||
id="kbn.management.createIndexPattern.step.indexPattern.disallowLabel"
|
||||
|
@ -388,10 +351,12 @@ The numeric input is mapped to a plural category, some subset of "zero", "one",
|
|||
|
||||
Here is an example of message translation depending on a plural category:
|
||||
|
||||
```html
|
||||
<span i18n-id="kbn.management.editIndexPattern.mappingConflictLabel"
|
||||
i18n-default-message="{conflictFieldsLength, plural, one {A field is} other {# fields are}} defined as several types (string, integer, etc) across the indices that match this pattern."
|
||||
i18n-values="{ conflictFieldsLength: conflictFields.length }"></span>
|
||||
```jsx
|
||||
<FormattedMessage
|
||||
id="kbn.management.editIndexPattern.mappingConflictLabel"
|
||||
defaultMessage="{conflictFieldsLength, plural, one {A field is} other {# fields are}} defined as several types (string, integer, etc) across the indices that match this pattern."
|
||||
values={{ conflictFieldsLength: conflictFields.length }}
|
||||
/>
|
||||
```
|
||||
|
||||
When `conflictFieldsLength` equals 1, the result string will be `"A field is defined as several types (string, integer, etc) across the indices that match this pattern."`. In cases when `conflictFieldsLength` has value of 2 or more, the result string - `"2 fields are defined as several types (string, integer, etc) across the indices that match this pattern."`.
|
||||
|
|
|
@ -343,98 +343,6 @@ export const MyComponent = injectI18n(
|
|||
);
|
||||
```
|
||||
|
||||
## AngularJS
|
||||
|
||||
The long term plan is to rely on using `i18n.translate()` by statically importing `i18n` from the `@kbn/i18n` package. **Avoid using the `i18n` filter and the `i18n` service injected in controllers, directives, services.**
|
||||
|
||||
AngularJS wrapper has 4 entities: translation `provider`, `service`, `directive`
|
||||
and `filter`. Both the directive and the filter use the translation `service`
|
||||
with i18n engine under the hood.
|
||||
|
||||
The translation `provider` is used for `service` configuration and
|
||||
has the following methods:
|
||||
- `addMessages(messages: Map<string, string>, [locale: string])` - provides a way to register
|
||||
translations with the library
|
||||
- `setLocale(locale: string)` - tells the library which language to use by given
|
||||
language key
|
||||
- `getLocale()` - returns the current locale
|
||||
- `setDefaultLocale(locale: string)` - tells the library which language to fallback
|
||||
when missing translations
|
||||
- `getDefaultLocale()` - returns the default locale
|
||||
- `setFormats(formats: object)` - supplies a set of options to the underlying formatter
|
||||
- `getFormats()` - returns current formats
|
||||
- `getRegisteredLocales()` - returns array of locales having translations
|
||||
- `init(messages: Map<string, string>)` - initializes the engine
|
||||
|
||||
The translation `service` provides only one method:
|
||||
- `i18n(id: string, { values: object, defaultMessage: string, description: string })` –
|
||||
translate message by id
|
||||
|
||||
The translation `filter` is used for attributes translation and has
|
||||
the following syntax:
|
||||
```
|
||||
{{ ::'translationId' | i18n: { values: object, defaultMessage: string, description: string } }}
|
||||
```
|
||||
|
||||
Where:
|
||||
- `translationId` - translation id to be translated
|
||||
- `values` - values to pass into translation
|
||||
- `defaultMessage` - will be used unless translation was successful (the final
|
||||
fallback in english, will be used for generating `en.json`)
|
||||
- `description` - optional context comment that will be extracted by i18n tools
|
||||
and added as a comment next to translation message at `defaultMessages.json`
|
||||
|
||||
The translation `directive` has the following syntax:
|
||||
```html
|
||||
<ANY
|
||||
i18n-id="{string}"
|
||||
i18n-default-message="{string}"
|
||||
[i18n-values="{object}"]
|
||||
[i18n-description="{string}"]
|
||||
></ANY>
|
||||
```
|
||||
|
||||
Where:
|
||||
- `i18n-id` - translation id to be translated
|
||||
- `i18n-default-message` - will be used unless translation was successful
|
||||
- `i18n-values` - values to pass into translation
|
||||
- `i18n-description` - optional context comment that will be extracted by i18n tools
|
||||
and added as a comment next to translation message at `defaultMessages.json`
|
||||
|
||||
If HTML rendering in `i18n-values` is required then value key in `i18n-values` object
|
||||
should have `html_` prefix. Otherwise the value will be inserted to the message without
|
||||
HTML rendering.\
|
||||
Example:
|
||||
```html
|
||||
<p
|
||||
i18n-id="namespace.id"
|
||||
i18n-default-message="Text with an emphasized {text}."
|
||||
i18n-values="{
|
||||
html_text: '<em>text</em>',
|
||||
}"
|
||||
></p>
|
||||
```
|
||||
|
||||
Angular `I18n` module is placed into `autoload` module, so it will be
|
||||
loaded automatically. After that we can use i18n directive in Angular templates:
|
||||
```html
|
||||
<span
|
||||
i18n-id="welcome"
|
||||
i18n-default-message="Hello!"
|
||||
></span>
|
||||
```
|
||||
|
||||
In order to translate attributes in AngularJS we should use `i18nFilter`:
|
||||
```html
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{{ ::'kbn.management.objects.searchAriaLabel' | i18n: {
|
||||
defaultMessage: 'Search { title } Object',
|
||||
values: { title }
|
||||
} }}"
|
||||
>
|
||||
```
|
||||
|
||||
## I18n tools
|
||||
|
||||
In order to simplify localization process, some additional tools were implemented:
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"browser": "../target_web/angular",
|
||||
"main": "../target_node/angular",
|
||||
"types": "../target_types/angular/index.d.ts"
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`i18nDirective doesn't render html in result message with text-only values 1`] = `
|
||||
<div
|
||||
class="ng-scope ng-isolate-scope"
|
||||
i18n-default-message="Default {one} onclick=alert(1) {two} message"
|
||||
i18n-id="id"
|
||||
i18n-values="{ one: '<span', two: '>Press</span>' }"
|
||||
>
|
||||
Default <span onclick=alert(1) >Press</span> message
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`i18nDirective doesn't render html in text-only value 1`] = `
|
||||
<div
|
||||
class="ng-scope ng-isolate-scope"
|
||||
i18n-default-message="Default {value}"
|
||||
i18n-id="id"
|
||||
i18n-values="{ value: '<strong>message</strong>' }"
|
||||
>
|
||||
Default <strong>message</strong>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`i18nDirective inserts correct translation html content with values 1`] = `"default-message word"`;
|
||||
|
||||
exports[`i18nDirective inserts correct translation html content with values 2`] = `"default-message anotherWord"`;
|
||||
|
||||
exports[`i18nDirective sanitizes message before inserting it to DOM 1`] = `
|
||||
<div
|
||||
class="ng-scope ng-isolate-scope"
|
||||
i18n-default-message="Default message, {value}"
|
||||
i18n-id="id"
|
||||
i18n-values="{ html_value: '<div ng-click=\\"dangerousAction()\\"></div>' }"
|
||||
>
|
||||
Default message,
|
||||
<div />
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`i18nDirective sanitizes onclick attribute 1`] = `
|
||||
<div
|
||||
class="ng-scope ng-isolate-scope"
|
||||
i18n-default-message="Default {value} message"
|
||||
i18n-id="id"
|
||||
i18n-values="{ html_value: '<span onclick=alert(1)>Press</span>' }"
|
||||
>
|
||||
Default
|
||||
<span>
|
||||
Press
|
||||
</span>
|
||||
message
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`i18nDirective sanitizes onmouseover attribute 1`] = `
|
||||
<div
|
||||
class="ng-scope ng-isolate-scope"
|
||||
i18n-default-message="Default {value} message"
|
||||
i18n-id="id"
|
||||
i18n-values="{ html_value: '<span onmouseover=\\"alert(1)\\">Press</span>' }"
|
||||
>
|
||||
Default
|
||||
<span>
|
||||
Press
|
||||
</span>
|
||||
message
|
||||
</div>
|
||||
`;
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import angular from 'angular';
|
||||
import 'angular-mocks';
|
||||
import 'angular-sanitize';
|
||||
|
||||
import { i18nDirective } from './directive';
|
||||
import { I18nProvider } from './provider';
|
||||
|
||||
angular
|
||||
.module('app', ['ngSanitize'])
|
||||
.provider('i18n', I18nProvider)
|
||||
.directive('i18nId', i18nDirective);
|
||||
|
||||
describe('i18nDirective', () => {
|
||||
let compile: angular.ICompileService;
|
||||
let scope: angular.IRootScopeService & { word?: string };
|
||||
|
||||
beforeEach(angular.mock.module('app'));
|
||||
beforeEach(
|
||||
angular.mock.inject(
|
||||
($compile: angular.ICompileService, $rootScope: angular.IRootScopeService) => {
|
||||
compile = $compile;
|
||||
scope = $rootScope.$new();
|
||||
scope.word = 'word';
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
test('inserts correct translation html content', () => {
|
||||
const id = 'id';
|
||||
const defaultMessage = 'default-message';
|
||||
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="${id}"
|
||||
i18n-default-message="${defaultMessage}"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).toEqual(defaultMessage);
|
||||
});
|
||||
|
||||
test('inserts correct translation html content with values', () => {
|
||||
const id = 'id';
|
||||
const defaultMessage = 'default-message {word}';
|
||||
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="${id}"
|
||||
i18n-default-message="${defaultMessage}"
|
||||
i18n-values="{ word }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).toMatchSnapshot();
|
||||
|
||||
scope.word = 'anotherWord';
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sanitizes message before inserting it to DOM', () => {
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="id"
|
||||
i18n-default-message="Default message, {value}"
|
||||
i18n-values="{ html_value: '<div ng-click="dangerousAction()"></div>' }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element[0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test(`doesn't render html in result message with text-only values`, () => {
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="id"
|
||||
i18n-default-message="Default {one} onclick=alert(1) {two} message"
|
||||
i18n-values="{ one: '<span', two: '>Press</span>' }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element[0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sanitizes onclick attribute', () => {
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="id"
|
||||
i18n-default-message="Default {value} message"
|
||||
i18n-values="{ html_value: '<span onclick=alert(1)>Press</span>' }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element[0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sanitizes onmouseover attribute', () => {
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="id"
|
||||
i18n-default-message="Default {value} message"
|
||||
i18n-values="{ html_value: '<span onmouseover="alert(1)">Press</span>' }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element[0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test(`doesn't render html in text-only value`, () => {
|
||||
const element = angular.element(
|
||||
`<div
|
||||
i18n-id="id"
|
||||
i18n-default-message="Default {value}"
|
||||
i18n-values="{ value: '<strong>message</strong>' }"
|
||||
/>`
|
||||
);
|
||||
|
||||
compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element[0]).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
jest.mock('../core/i18n', () => ({
|
||||
translate: jest.fn().mockImplementation(() => 'translation'),
|
||||
}));
|
||||
|
||||
import angular from 'angular';
|
||||
import 'angular-mocks';
|
||||
|
||||
import * as i18n from '../core/i18n';
|
||||
import { i18nFilter as angularI18nFilter } from './filter';
|
||||
import { I18nProvider, I18nServiceType } from './provider';
|
||||
|
||||
angular.module('app', []).provider('i18n', I18nProvider).filter('i18n', angularI18nFilter);
|
||||
|
||||
describe('i18nFilter', () => {
|
||||
let filter: I18nServiceType;
|
||||
|
||||
beforeEach(angular.mock.module('app'));
|
||||
beforeEach(
|
||||
angular.mock.inject((i18nFilter) => {
|
||||
filter = i18nFilter;
|
||||
})
|
||||
);
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
test('provides wrapper around i18n engine', () => {
|
||||
const id = 'id';
|
||||
const defaultMessage = 'default-message';
|
||||
const values = {};
|
||||
|
||||
const result = filter(id, { defaultMessage, values });
|
||||
|
||||
expect(result).toEqual('translation');
|
||||
expect(i18n.translate).toHaveBeenCalledTimes(1);
|
||||
expect(i18n.translate).toHaveBeenCalledWith(id, { defaultMessage, values });
|
||||
});
|
||||
});
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import angular from 'angular';
|
||||
import 'angular-mocks';
|
||||
|
||||
import * as i18nCore from '../core/i18n';
|
||||
import { I18nProvider, I18nServiceType } from './provider';
|
||||
|
||||
angular.module('app', []).provider('i18n', I18nProvider);
|
||||
|
||||
describe('i18nProvider', () => {
|
||||
let provider: I18nProvider;
|
||||
let service: I18nServiceType;
|
||||
|
||||
beforeEach(
|
||||
angular.mock.module('app', [
|
||||
'i18nProvider',
|
||||
(i18n: I18nProvider) => {
|
||||
provider = i18n;
|
||||
},
|
||||
])
|
||||
);
|
||||
beforeEach(
|
||||
angular.mock.inject((i18n: I18nServiceType) => {
|
||||
service = i18n;
|
||||
})
|
||||
);
|
||||
|
||||
test('provides wrapper around i18n engine', () => {
|
||||
expect(service).toEqual(i18nCore.translate);
|
||||
});
|
||||
|
||||
test('provides service wrapper around i18n engine', () => {
|
||||
const serviceMethodNames = Object.keys(provider);
|
||||
const pluginMethodNames = Object.keys(i18nCore);
|
||||
|
||||
expect([...serviceMethodNames, 'translate'].sort()).toEqual(
|
||||
[...pluginMethodNames, '$get'].sort()
|
||||
);
|
||||
});
|
||||
});
|
|
@ -15,7 +15,6 @@ require('./flot_charts');
|
|||
|
||||
// stateful deps
|
||||
export const KbnI18n = require('@kbn/i18n');
|
||||
export const KbnI18nAngular = require('@kbn/i18n/angular');
|
||||
export const KbnI18nReact = require('@kbn/i18n/react');
|
||||
export const Angular = require('angular');
|
||||
export const EmotionReact = require('@emotion/react');
|
||||
|
|
|
@ -32,7 +32,6 @@ exports.externals = {
|
|||
*/
|
||||
angular: '__kbnSharedDeps__.Angular',
|
||||
'@kbn/i18n': '__kbnSharedDeps__.KbnI18n',
|
||||
'@kbn/i18n/angular': '__kbnSharedDeps__.KbnI18nAngular',
|
||||
'@kbn/i18n/react': '__kbnSharedDeps__.KbnI18nReact',
|
||||
'@emotion/react': '__kbnSharedDeps__.EmotionReact',
|
||||
jquery: '__kbnSharedDeps__.Jquery',
|
||||
|
|
|
@ -18,34 +18,6 @@ The `defaultMessage` must contain ICU references to all keys in the `values` and
|
|||
|
||||
The `description` is optional, `values` is optional too unless `defaultMessage` references to it.
|
||||
|
||||
* **Angular (.html)**
|
||||
|
||||
* **Filter**
|
||||
|
||||
```
|
||||
{{ ::'pluginNamespace.messageId' | i18n: {
|
||||
defaultMessage: 'Default message string literal, {key}',
|
||||
values: { key: 'value' },
|
||||
description: 'Message context or description'
|
||||
} }}
|
||||
```
|
||||
|
||||
* Don't break `| i18n: {` with line breaks, and don't skip whitespaces around `i18n:`.
|
||||
* `::` operator is optional. Omit it if you need data binding for the `values`.
|
||||
|
||||
* **Directive**
|
||||
|
||||
```html
|
||||
<p
|
||||
i18n-id="pluginNamespace.messageId"
|
||||
i18n-default-message="Default message string literal, {key}. {emphasizedText}"
|
||||
i18n-values="{ key: value, html_emphasizedText: htmlString }"
|
||||
i18n-description="Message context or description"
|
||||
></p>
|
||||
```
|
||||
|
||||
* `html_` prefixes will be removed from `i18n-values` keys before validation.
|
||||
|
||||
* **React (.jsx, .tsx)**
|
||||
|
||||
* **\<FormattedMessage\>**
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
"xpack.observability": "plugins/observability",
|
||||
"xpack.banners": "plugins/banners"
|
||||
},
|
||||
"exclude": ["examples"],
|
||||
"exclude": ["examples", "plugins/monitoring/public/angular/angular_i18n"],
|
||||
"translations": [
|
||||
"plugins/translations/translations/zh-CN.json",
|
||||
"plugins/translations/translations/ja-JP.json"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IDirective, IRootElementService, IScope } from 'angular';
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { I18nServiceType } from './provider';
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export { I18nProvider } from './provider';
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as i18n from '../core';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export type I18nServiceType = ReturnType<I18nProvider['$get']>;
|
||||
|
|
@ -12,8 +12,8 @@ import 'angular-sanitize';
|
|||
import 'angular-route';
|
||||
import '../index.scss';
|
||||
import { upperFirst } from 'lodash';
|
||||
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { i18nDirective, i18nFilter, I18nProvider } from './angular_i18n';
|
||||
import { Storage } from '../../../../../src/plugins/kibana_utils/public';
|
||||
import {
|
||||
createTopNavDirective,
|
||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -5782,14 +5782,7 @@
|
|||
dependencies:
|
||||
"@turf/helpers" "6.x"
|
||||
|
||||
"@types/angular-mocks@^1.7.0":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/angular-mocks/-/angular-mocks-1.7.0.tgz#310d999a3c47c10ecd8eef466b5861df84799429"
|
||||
integrity sha512-MeT5vxWBx4Ny5/sNZJjpZdv4K2KGwqQYiRQQZctan1TTaNyiVlFRYbcmheolhM4KKbTWmoxTVeuvGzniTDg1kw==
|
||||
dependencies:
|
||||
"@types/angular" "*"
|
||||
|
||||
"@types/angular@*", "@types/angular@^1.6.56":
|
||||
"@types/angular@^1.6.56":
|
||||
version "1.6.56"
|
||||
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.56.tgz#20124077bd44061e018c7283c0bb83f4b00322dd"
|
||||
integrity sha512-HxtqilvklZ7i6XOaiP7uIJIrFXEVEhfbSY45nfv2DeBRngncI58Y4ZOUMiUkcT8sqgLL1ablmbfylChUg7A3GA==
|
||||
|
@ -7873,11 +7866,6 @@ angular-aria@^1.8.0:
|
|||
resolved "https://registry.yarnpkg.com/angular-aria/-/angular-aria-1.8.0.tgz#97aec9b1e8bafd07d5fab30f98d8ec832e18e25d"
|
||||
integrity sha512-eCQI6EwgY6bYHdzIUfDABHnZjoZ3bNYpCsnceQF4bLfbq1QtZ7raRPNca45sj6C9Pfjde6PNcEDvuLozFPYnrQ==
|
||||
|
||||
angular-mocks@^1.7.9:
|
||||
version "1.7.9"
|
||||
resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.7.9.tgz#0a3b7e28b9a493b4e3010ed2b0f69a68e9b4f79b"
|
||||
integrity sha512-LQRqqiV3sZ7NTHBnNmLT0bXtE5e81t97+hkJ56oU0k3dqKv1s6F+nBWRlOVzqHWPGFOiPS8ZJVdrS8DFzHyNIA==
|
||||
|
||||
angular-recursion@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/angular-recursion/-/angular-recursion-1.0.5.tgz#cd405428a0bf55faf52eaa7988c1fe69cd930543"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue