From 9caab5858d62dd662321049e0d6bd0b13d597614 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 19 Oct 2021 19:05:53 +0300 Subject: [PATCH] [i18n] remove i18n html extractor (#115004) --- .../test_plugin_1/test_file_1.jsx | 13 +- .../test_plugin_1/test_file_4.html | 8 - .../test_plugin_2/test_file.html | 1 - .../test_plugin_2/test_file.jsx | 8 + .../test_file.jsx | 0 .../test_file.jsx | 8 - .../extract_default_translations.test.js.snap | 22 +- src/dev/i18n/extract_default_translations.js | 27 +- .../i18n/extract_default_translations.test.js | 22 +- .../__snapshots__/html.test.js.snap | 77 ------ src/dev/i18n/extractors/html.js | 252 ------------------ src/dev/i18n/extractors/html.test.js | 103 ------- src/dev/i18n/extractors/index.js | 1 - x-pack/.i18nrc.json | 2 +- 14 files changed, 36 insertions(+), 508 deletions(-) delete mode 100644 src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_4.html delete mode 100644 src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.html create mode 100644 src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx rename src/dev/i18n/__fixtures__/extract_default_translations/{test_plugin_3 => test_plugin_2_additional_path}/test_file.jsx (100%) delete mode 100644 src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3_additional_path/test_file.jsx delete mode 100644 src/dev/i18n/extractors/__snapshots__/html.test.js.snap delete mode 100644 src/dev/i18n/extractors/html.js delete mode 100644 src/dev/i18n/extractors/html.test.js diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_1.jsx b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_1.jsx index a52047f00feb0..8dc47a53da421 100644 --- a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_1.jsx +++ b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_1.jsx @@ -1,11 +1,8 @@ /* eslint-disable */ -// Angular service -i18n('plugin_1.id_1', { defaultMessage: 'Message 1' }); - // @kbn/i18n -i18n.translate('plugin_1.id_2', { - defaultMessage: 'Message 2', +i18n.translate('plugin_1.id_1', { + defaultMessage: 'Message 1', description: 'Message description', }); @@ -15,10 +12,10 @@ class Component extends PureComponent { return (
- {intl.formatMessage({ id: 'plugin_1.id_4', defaultMessage: 'Message 4' })} + {intl.formatMessage({ id: 'plugin_1.id_3', defaultMessage: 'Message 3' })}
); } diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_4.html b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_4.html deleted file mode 100644 index f9c8a8383d647..0000000000000 --- a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1/test_file_4.html +++ /dev/null @@ -1,8 +0,0 @@ - -
-
-
-
diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.html b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.html deleted file mode 100644 index c12843602b13b..0000000000000 --- a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.html +++ /dev/null @@ -1 +0,0 @@ -

{{ ::'plugin_2.message-id' | i18n: { defaultMessage: 'Message text' } }}

diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx new file mode 100644 index 0000000000000..8f41a58bf82d1 --- /dev/null +++ b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx @@ -0,0 +1,8 @@ +/* eslint-disable */ + +i18n.translate('plugin_2.duplicate_id', { defaultMessage: 'Message 1' }); + +i18n.translate('plugin_2.duplicate_id', { + defaultMessage: 'Message 2', + description: 'Message description', +}); diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3/test_file.jsx b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2_additional_path/test_file.jsx similarity index 100% rename from src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3/test_file.jsx rename to src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2_additional_path/test_file.jsx diff --git a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3_additional_path/test_file.jsx b/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3_additional_path/test_file.jsx deleted file mode 100644 index 7fa370dec5ebb..0000000000000 --- a/src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3_additional_path/test_file.jsx +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable */ - -i18n('plugin_3.duplicate_id', { defaultMessage: 'Message 1' }); - -i18n.translate('plugin_3.duplicate_id', { - defaultMessage: 'Message 2', - description: 'Message description', -}); diff --git a/src/dev/i18n/__snapshots__/extract_default_translations.test.js.snap b/src/dev/i18n/__snapshots__/extract_default_translations.test.js.snap index b19b366a8db7b..c9215b9aed98b 100644 --- a/src/dev/i18n/__snapshots__/extract_default_translations.test.js.snap +++ b/src/dev/i18n/__snapshots__/extract_default_translations.test.js.snap @@ -5,14 +5,14 @@ Array [ Array [ "plugin_1.id_1", Object { - "description": undefined, + "description": "Message description", "message": "Message 1", }, ], Array [ "plugin_1.id_2", Object { - "description": "Message description", + "description": undefined, "message": "Message 2", }, ], @@ -23,27 +23,13 @@ Array [ "message": "Message 3", }, ], - Array [ - "plugin_1.id_4", - Object { - "description": undefined, - "message": "Message 4", - }, - ], - Array [ - "plugin_1.id_7", - Object { - "description": undefined, - "message": "Message 7", - }, - ], ] `; exports[`dev/i18n/extract_default_translations throws on id collision 1`] = ` Array [ - " I18N ERROR  Error in src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3/test_file.jsx -Error: There is more than one default message for the same id \\"plugin_3.duplicate_id\\": + " I18N ERROR  Error in src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx +Error: There is more than one default message for the same id \\"plugin_2.duplicate_id\\": \\"Message 1\\" and \\"Message 2\\"", ] `; diff --git a/src/dev/i18n/extract_default_translations.js b/src/dev/i18n/extract_default_translations.js index 97554704edc7f..a453b0bbae2fb 100644 --- a/src/dev/i18n/extract_default_translations.js +++ b/src/dev/i18n/extract_default_translations.js @@ -8,7 +8,7 @@ import path from 'path'; -import { extractHtmlMessages, extractCodeMessages } from './extractors'; +import { extractCodeMessages } from './extractors'; import { globAsync, readFileAsync, normalizePath } from './utils'; import { createFailError, isFailError } from '@kbn/dev-utils'; @@ -59,7 +59,7 @@ export async function matchEntriesWithExctractors(inputPath, options = {}) { '**/*.d.ts', ].concat(additionalIgnore); - const entries = await globAsync('*.{js,jsx,ts,tsx,html}', { + const entries = await globAsync('*.{js,jsx,ts,tsx}', { cwd: inputPath, matchBase: true, ignore, @@ -67,25 +67,14 @@ export async function matchEntriesWithExctractors(inputPath, options = {}) { absolute, }); - const { htmlEntries, codeEntries } = entries.reduce( - (paths, entry) => { - const resolvedPath = path.resolve(inputPath, entry); + const codeEntries = entries.reduce((paths, entry) => { + const resolvedPath = path.resolve(inputPath, entry); + paths.push(resolvedPath); - if (resolvedPath.endsWith('.html')) { - paths.htmlEntries.push(resolvedPath); - } else { - paths.codeEntries.push(resolvedPath); - } - - return paths; - }, - { htmlEntries: [], codeEntries: [] } - ); + return paths; + }, []); - return [ - [htmlEntries, extractHtmlMessages], - [codeEntries, extractCodeMessages], - ]; + return [[codeEntries, extractCodeMessages]]; } export async function extractMessagesFromPathToMap(inputPath, targetMap, config, reporter) { diff --git a/src/dev/i18n/extract_default_translations.test.js b/src/dev/i18n/extract_default_translations.test.js index 4b0da570ca551..e5b33eba7a4db 100644 --- a/src/dev/i18n/extract_default_translations.test.js +++ b/src/dev/i18n/extract_default_translations.test.js @@ -18,17 +18,15 @@ const fixturesPath = path.resolve(__dirname, '__fixtures__', 'extract_default_tr const pluginsPaths = [ path.join(fixturesPath, 'test_plugin_1'), path.join(fixturesPath, 'test_plugin_2'), - path.join(fixturesPath, 'test_plugin_3'), - path.join(fixturesPath, 'test_plugin_3_additional_path'), + path.join(fixturesPath, 'test_plugin_2_additional_path'), ]; const config = { paths: { plugin_1: ['src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_1'], - plugin_2: ['src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2'], - plugin_3: [ - 'src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3', - 'src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_3_additional_path', + plugin_2: [ + 'src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2', + 'src/dev/i18n/__fixtures__/extract_default_translations/test_plugin_2_additional_path', ], }, exclude: [], @@ -44,7 +42,7 @@ describe('dev/i18n/extract_default_translations', () => { }); test('throws on id collision', async () => { - const [, , pluginPath] = pluginsPaths; + const [, pluginPath] = pluginsPaths; const reporter = new ErrorReporter(); await expect( @@ -57,20 +55,20 @@ describe('dev/i18n/extract_default_translations', () => { const id = 'plugin_2.message-id'; const filePath = path.resolve( __dirname, - '__fixtures__/extract_default_translations/test_plugin_2/test_file.html' + '__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx' ); expect(() => validateMessageNamespace(id, filePath, config.paths)).not.toThrow(); }); test('validates message namespace with multiple paths', () => { - const id = 'plugin_3.message-id'; + const id = 'plugin_2.message-id'; const filePath1 = path.resolve( __dirname, - '__fixtures__/extract_default_translations/test_plugin_3/test_file.html' + '__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx' ); const filePath2 = path.resolve( __dirname, - '__fixtures__/extract_default_translations/test_plugin_3_additional_path/test_file.html' + '__fixtures__/extract_default_translations/test_plugin_2_additional_path/test_file.jsx' ); expect(() => validateMessageNamespace(id, filePath1, config.paths)).not.toThrow(); expect(() => validateMessageNamespace(id, filePath2, config.paths)).not.toThrow(); @@ -81,7 +79,7 @@ describe('dev/i18n/extract_default_translations', () => { const id = 'wrong_plugin_namespace.message-id'; const filePath = path.resolve( __dirname, - '__fixtures__/extract_default_translations/test_plugin_2/test_file.html' + '__fixtures__/extract_default_translations/test_plugin_2/test_file.jsx' ); expect(() => validateMessageNamespace(id, filePath, config.paths, { report })).not.toThrow(); diff --git a/src/dev/i18n/extractors/__snapshots__/html.test.js.snap b/src/dev/i18n/extractors/__snapshots__/html.test.js.snap deleted file mode 100644 index f911674400d45..0000000000000 --- a/src/dev/i18n/extractors/__snapshots__/html.test.js.snap +++ /dev/null @@ -1,77 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`dev/i18n/extractors/html extracts default messages from HTML 1`] = ` -Array [ - Array [ - "kbn.dashboard.id-1", - Object { - "description": "Message description 1", - "message": "Message text 1 {value}", - }, - ], - Array [ - "kbn.dashboard.id-2", - Object { - "description": undefined, - "message": "Message text 2", - }, - ], - Array [ - "kbn.dashboard.id-3", - Object { - "description": "Message description 3", - "message": "Message text 3", - }, - ], -] -`; - -exports[`dev/i18n/extractors/html extracts default messages from HTML with one-time binding 1`] = ` -Array [ - Array [ - "kbn.id", - Object { - "description": undefined, - "message": "Message text with {value}", - }, - ], -] -`; - -exports[`dev/i18n/extractors/html extracts message from i18n filter in interpolating directive 1`] = ` -Array [ - Array [ - "namespace.messageId", - Object { - "description": undefined, - "message": "Message", - }, - ], -] -`; - -exports[`dev/i18n/extractors/html throws on empty i18n-id 1`] = ` -Array [ - Array [ - [Error: Empty "i18n-id" value in angular directive is not allowed.], - ], -] -`; - -exports[`dev/i18n/extractors/html throws on i18n filter usage in complex angular expression 1`] = ` -Array [ - Array [ - [Error: Couldn't parse angular i18n expression: -Missing semicolon. (1:5): - mode as ('metricVis.colorModes.' + mode], - ], -] -`; - -exports[`dev/i18n/extractors/html throws on missing i18n-default-message attribute 1`] = ` -Array [ - Array [ - [Error: Empty defaultMessage in angular directive is not allowed ("message-id").], - ], -] -`; diff --git a/src/dev/i18n/extractors/html.js b/src/dev/i18n/extractors/html.js deleted file mode 100644 index 922f67ac2fb09..0000000000000 --- a/src/dev/i18n/extractors/html.js +++ /dev/null @@ -1,252 +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 cheerio from 'cheerio'; -import { parse } from '@babel/parser'; -import { isObjectExpression, isStringLiteral } from '@babel/types'; - -import { - isPropertyWithKey, - formatHTMLString, - formatJSString, - traverseNodes, - checkValuesProperty, - createParserErrorMessage, - extractMessageValueFromNode, - extractValuesKeysFromNode, - extractDescriptionValueFromNode, -} from '../utils'; -import { DEFAULT_MESSAGE_KEY, DESCRIPTION_KEY, VALUES_KEY } from '../constants'; -import { createFailError, isFailError } from '@kbn/dev-utils'; - -/** - * Find all substrings of "{{ any text }}" pattern allowing '{' and '}' chars in single quote strings - * - * Example: `{{ ::'message.id' | i18n: { defaultMessage: 'Message with {{curlyBraces}}' } }}` - */ -const ANGULAR_EXPRESSION_REGEX = /{{([^{}]|({([^']|('([^']|(\\'))*'))*?}))*}}+/g; - -const LINEBREAK_REGEX = /\n/g; -const I18N_FILTER_MARKER = '| i18n: '; - -function parseExpression(expression) { - let ast; - - try { - ast = parse(`+${expression}`.replace(LINEBREAK_REGEX, ' ')); - } catch (error) { - if (error instanceof SyntaxError) { - const errorWithContext = createParserErrorMessage(` ${expression}`, error); - throw createFailError(`Couldn't parse angular i18n expression:\n${errorWithContext}`); - } - } - - return ast; -} - -/** - * Extract default message from an angular filter expression argument - * @param {string} expression JavaScript code containing a filter object - * @param {string} messageId id of the message - * @returns {{ message?: string, description?: string, valuesKeys: string[]] }} - */ -function parseFilterObjectExpression(expression, messageId) { - const ast = parseExpression(expression); - const objectExpressionNode = [...traverseNodes(ast.program.body)].find((node) => - isObjectExpression(node) - ); - - if (!objectExpressionNode) { - return {}; - } - - const [messageProperty, descriptionProperty, valuesProperty] = [ - DEFAULT_MESSAGE_KEY, - DESCRIPTION_KEY, - VALUES_KEY, - ].map((key) => - objectExpressionNode.properties.find((property) => isPropertyWithKey(property, key)) - ); - - const message = messageProperty - ? formatJSString(extractMessageValueFromNode(messageProperty.value, messageId)) - : undefined; - - const description = descriptionProperty - ? formatJSString(extractDescriptionValueFromNode(descriptionProperty.value, messageId)) - : undefined; - - const valuesKeys = valuesProperty - ? extractValuesKeysFromNode(valuesProperty.value, messageId) - : []; - - return { message, description, valuesKeys }; -} - -function parseIdExpression(expression) { - const ast = parseExpression(expression); - const stringNode = [...traverseNodes(ast.program.body)].find((node) => isStringLiteral(node)); - - if (!stringNode) { - throw createFailError(`Message id should be a string literal, but got: \n${expression}`); - } - - return stringNode ? formatJSString(stringNode.value) : null; -} - -function trimCurlyBraces(string) { - if (string.startsWith('{{') && string.endsWith('}}')) { - return string.slice(2, -2).trim(); - } - - return string; -} - -/** - * Removes one-time binding operator `::` from the start of a string. - * - * Example: `::'id' | i18n: { defaultMessage: 'Message' }` - * @param {string} string string to trim - */ -function trimOneTimeBindingOperator(string) { - if (string.startsWith('::')) { - return string.slice(2); - } - - return string; -} - -function* extractExpressions(htmlContent) { - const elements = cheerio.load(htmlContent)('*').toArray(); - - for (const element of elements) { - for (const node of element.children) { - if (node.type === 'text') { - yield* (node.data.match(ANGULAR_EXPRESSION_REGEX) || []) - .filter((expression) => expression.includes(I18N_FILTER_MARKER)) - .map(trimCurlyBraces); - } - } - - for (const attribute of Object.values(element.attribs)) { - if (attribute.includes(I18N_FILTER_MARKER)) { - yield trimCurlyBraces(attribute); - } - } - } -} - -function* getFilterMessages(htmlContent, reporter) { - for (const expression of extractExpressions(htmlContent)) { - const filterStart = expression.indexOf(I18N_FILTER_MARKER); - - const idExpression = trimOneTimeBindingOperator(expression.slice(0, filterStart).trim()); - const filterObjectExpression = expression.slice(filterStart + I18N_FILTER_MARKER.length).trim(); - - try { - if (!filterObjectExpression || !idExpression) { - throw createFailError(`Cannot parse i18n filter expression: ${expression}`); - } - - const messageId = parseIdExpression(idExpression); - - if (!messageId) { - throw createFailError('Empty "id" value in angular filter expression is not allowed.'); - } - - const { message, description, valuesKeys } = parseFilterObjectExpression( - filterObjectExpression, - messageId - ); - - if (!message) { - throw createFailError( - `Empty defaultMessage in angular filter expression is not allowed ("${messageId}").` - ); - } - - checkValuesProperty(valuesKeys, message, messageId); - - yield [messageId, { message, description }]; - } catch (error) { - if (!isFailError(error)) { - throw error; - } - - reporter.report(error); - } - } -} - -function* getDirectiveMessages(htmlContent, reporter) { - const $ = cheerio.load(htmlContent); - - const elements = $('[i18n-id]') - .map((idx, el) => { - const $el = $(el); - - return { - id: $el.attr('i18n-id'), - defaultMessage: $el.attr('i18n-default-message'), - description: $el.attr('i18n-description'), - values: $el.attr('i18n-values'), - }; - }) - .toArray(); - - for (const element of elements) { - const messageId = formatHTMLString(element.id); - if (!messageId) { - reporter.report( - createFailError('Empty "i18n-id" value in angular directive is not allowed.') - ); - continue; - } - - const message = formatHTMLString(element.defaultMessage); - if (!message) { - reporter.report( - createFailError( - `Empty defaultMessage in angular directive is not allowed ("${messageId}").` - ) - ); - continue; - } - - try { - if (element.values) { - const ast = parseExpression(element.values); - const valuesObjectNode = [...traverseNodes(ast.program.body)].find((node) => - isObjectExpression(node) - ); - const valuesKeys = extractValuesKeysFromNode(valuesObjectNode); - - checkValuesProperty(valuesKeys, message, messageId); - } else { - checkValuesProperty([], message, messageId); - } - - yield [ - messageId, - { message, description: formatHTMLString(element.description) || undefined }, - ]; - } catch (error) { - if (!isFailError(error)) { - throw error; - } - - reporter.report(error); - } - } -} - -export function* extractHtmlMessages(buffer, reporter) { - const content = buffer.toString(); - yield* getDirectiveMessages(content, reporter); - yield* getFilterMessages(content, reporter); -} diff --git a/src/dev/i18n/extractors/html.test.js b/src/dev/i18n/extractors/html.test.js deleted file mode 100644 index 5f0c7ac39e8f6..0000000000000 --- a/src/dev/i18n/extractors/html.test.js +++ /dev/null @@ -1,103 +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 { extractHtmlMessages } from './html'; - -const htmlSourceBuffer = Buffer.from(` -
-
-

-
-
- {{ 'kbn.dashboard.id-2' | i18n: { defaultMessage: 'Message text 2' } }} -
-
- {{ 'kbn.dashboard.id-3' | i18n: { defaultMessage: 'Message text 3', description: 'Message description 3' } }} -
-
-`); - -const report = jest.fn(); - -describe('dev/i18n/extractors/html', () => { - beforeEach(() => { - report.mockClear(); - }); - - test('extracts default messages from HTML', () => { - const actual = Array.from(extractHtmlMessages(htmlSourceBuffer)); - expect(actual.sort()).toMatchSnapshot(); - }); - - test('extracts default messages from HTML with one-time binding', () => { - const actual = Array.from( - extractHtmlMessages(` -
- {{::'kbn.id' | i18n: { defaultMessage: 'Message text with {value}', values: { value: 'value' } }}} -
-`) - ); - expect(actual.sort()).toMatchSnapshot(); - }); - - test('throws on empty i18n-id', () => { - const source = Buffer.from(`\ -

-`); - - expect(() => extractHtmlMessages(source, { report }).next()).not.toThrow(); - expect(report.mock.calls).toMatchSnapshot(); - }); - - test('throws on missing i18n-default-message attribute', () => { - const source = Buffer.from(`\ -

-`); - - expect(() => extractHtmlMessages(source, { report }).next()).not.toThrow(); - expect(report.mock.calls).toMatchSnapshot(); - }); - - test('throws on i18n filter usage in complex angular expression', () => { - const source = Buffer.from(`\ -
-`); - - expect(() => extractHtmlMessages(source, { report }).next()).not.toThrow(); - expect(report.mock.calls).toMatchSnapshot(); - }); - - test('extracts message from i18n filter in interpolating directive', () => { - const source = Buffer.from(` - -`); - - expect(Array.from(extractHtmlMessages(source))).toMatchSnapshot(); - }); -}); diff --git a/src/dev/i18n/extractors/index.js b/src/dev/i18n/extractors/index.js index dc269586f5abe..601a080c80b1b 100644 --- a/src/dev/i18n/extractors/index.js +++ b/src/dev/i18n/extractors/index.js @@ -7,4 +7,3 @@ */ export { extractCodeMessages } from './code'; -export { extractHtmlMessages } from './html'; diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 372812d4d0dc1..b51363f1b7006 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -64,7 +64,7 @@ "xpack.observability": "plugins/observability", "xpack.banners": "plugins/banners" }, - "exclude": ["examples", "plugins/monitoring/public/angular/angular_i18n"], + "exclude": ["examples"], "translations": [ "plugins/translations/translations/zh-CN.json", "plugins/translations/translations/ja-JP.json"