mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* [i18n] extract untracked translations and prettier logging (#35171) * extract untracked translations and prettier logging * self code review * Update src/dev/run_i18n_check.ts Co-Authored-By: Bamieh <ahmadbamieh@gmail.com> * updating listR * run new i18n_check and fix errors * kbnEmbeddables -> embeddableApi * remove any type * Update src/legacy/core_plugins/embeddable_api/public/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx Co-Authored-By: Stacey Gammon <gammon@elastic.co> * Update src/legacy/core_plugins/embeddable_api/public/panel/panel_header/panel_actions/add_panel/add_panel_action.tsx Co-Authored-By: Stacey Gammon <gammon@elastic.co> * self code review fixes * fix extract and integrate scripts * ts-ignore js file * run i18n_check
This commit is contained in:
parent
6004459a1e
commit
f7f64792f8
26 changed files with 377 additions and 142 deletions
|
@ -10,6 +10,7 @@
|
|||
"interpreter": "src/legacy/core_plugins/interpreter",
|
||||
"kbn": "src/legacy/core_plugins/kibana",
|
||||
"kbnDocViews": "src/legacy/core_plugins/kbn_doc_views",
|
||||
"embeddableApi": "src/legacy/core_plugins/embeddable_api",
|
||||
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
|
||||
"markdownVis": "src/legacy/core_plugins/markdown_vis",
|
||||
"metricVis": "src/legacy/core_plugins/metric_vis",
|
||||
|
@ -25,6 +26,7 @@
|
|||
"xpack.apm": "x-pack/plugins/apm",
|
||||
"xpack.beatsManagement": "x-pack/plugins/beats_management",
|
||||
"xpack.canvas": "x-pack/plugins/canvas",
|
||||
"xpack.code": "x-pack/plugins/code",
|
||||
"xpack.crossClusterReplication": "x-pack/plugins/cross_cluster_replication",
|
||||
"xpack.dashboardMode": "x-pack/plugins/dashboard_mode",
|
||||
"xpack.graph": "x-pack/plugins/graph",
|
||||
|
|
|
@ -62,11 +62,20 @@ See .i18nrc.json for the list of supported namespaces.`)
|
|||
}
|
||||
}
|
||||
|
||||
export async function extractMessagesFromPathToMap(inputPath, targetMap, config, reporter) {
|
||||
export async function matchEntriesWithExctractors(inputPath, options = {}) {
|
||||
const {
|
||||
additionalIgnore = [],
|
||||
mark = false,
|
||||
absolute = false,
|
||||
} = options;
|
||||
const ignore = ['**/node_modules/**', '**/__tests__/**', '**/*.test.{js,jsx,ts,tsx}', '**/*.d.ts'].concat(additionalIgnore);
|
||||
|
||||
const entries = await globAsync('*.{js,jsx,pug,ts,tsx,html}', {
|
||||
cwd: inputPath,
|
||||
matchBase: true,
|
||||
ignore: ['**/node_modules/**', '**/__tests__/**', '**/*.test.{js,jsx,ts,tsx}', '**/*.d.ts'],
|
||||
ignore,
|
||||
mark,
|
||||
absolute,
|
||||
});
|
||||
|
||||
const { htmlEntries, codeEntries, pugEntries } = entries.reduce(
|
||||
|
@ -86,37 +95,43 @@ export async function extractMessagesFromPathToMap(inputPath, targetMap, config,
|
|||
{ htmlEntries: [], codeEntries: [], pugEntries: [] }
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
[
|
||||
[htmlEntries, extractHtmlMessages],
|
||||
[codeEntries, extractCodeMessages],
|
||||
[pugEntries, extractPugMessages],
|
||||
].map(async ([entries, extractFunction]) => {
|
||||
const files = await Promise.all(
|
||||
filterEntries(entries, config.exclude).map(async entry => {
|
||||
return {
|
||||
name: entry,
|
||||
content: await readFileAsync(entry),
|
||||
};
|
||||
})
|
||||
);
|
||||
return [
|
||||
[htmlEntries, extractHtmlMessages],
|
||||
[codeEntries, extractCodeMessages],
|
||||
[pugEntries, extractPugMessages],
|
||||
];
|
||||
}
|
||||
|
||||
for (const { name, content } of files) {
|
||||
const reporterWithContext = reporter.withContext({ name });
|
||||
export async function extractMessagesFromPathToMap(inputPath, targetMap, config, reporter) {
|
||||
const categorizedEntries = await matchEntriesWithExctractors(inputPath);
|
||||
return Promise.all(
|
||||
categorizedEntries
|
||||
.map(async ([entries, extractFunction]) => {
|
||||
const files = await Promise.all(
|
||||
filterEntries(entries, config.exclude).map(async entry => {
|
||||
return {
|
||||
name: entry,
|
||||
content: await readFileAsync(entry),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
try {
|
||||
for (const [id, value] of extractFunction(content, reporterWithContext)) {
|
||||
validateMessageNamespace(id, name, config.paths, reporterWithContext);
|
||||
addMessageToMap(targetMap, id, value, reporterWithContext);
|
||||
for (const { name, content } of files) {
|
||||
const reporterWithContext = reporter.withContext({ name });
|
||||
|
||||
try {
|
||||
for (const [id, value] of extractFunction(content, reporterWithContext)) {
|
||||
validateMessageNamespace(id, name, config.paths, reporterWithContext);
|
||||
addMessageToMap(targetMap, id, value, reporterWithContext);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!isFailError(error)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
reporterWithContext.report(error);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!isFailError(error)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
reporterWithContext.report(error);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
// @ts-ignore
|
||||
export { extractMessagesFromPathToMap } from './extract_default_translations';
|
||||
// @ts-ignore
|
||||
export { matchEntriesWithExctractors } from './extract_default_translations';
|
||||
// @ts-ignore
|
||||
export { writeFileAsync, readFileAsync, normalizePath, ErrorReporter } from './utils';
|
||||
export { serializeToJson, serializeToJson5 } from './serializers';
|
||||
export { I18nConfig, filterConfigPaths, mergeConfigs } from './config';
|
||||
|
|
|
@ -37,7 +37,7 @@ import { createFailError } from '../run';
|
|||
import { I18nConfig } from './config';
|
||||
import { serializeToJson } from './serializers';
|
||||
|
||||
interface IntegrateOptions {
|
||||
export interface IntegrateOptions {
|
||||
sourceFileName: string;
|
||||
targetFileName?: string;
|
||||
dryRun: boolean;
|
||||
|
|
48
src/dev/i18n/tasks/check_compatibility.ts
Normal file
48
src/dev/i18n/tasks/check_compatibility.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { integrateLocaleFiles, I18nConfig } from '..';
|
||||
|
||||
export interface I18nFlags {
|
||||
fix: boolean;
|
||||
ignoreIncompatible: boolean;
|
||||
ignoreUnused: boolean;
|
||||
ignoreMissing: boolean;
|
||||
}
|
||||
|
||||
export function checkCompatibility(config: I18nConfig, flags: I18nFlags, log: ToolingLog) {
|
||||
const { fix, ignoreIncompatible, ignoreUnused, ignoreMissing } = flags;
|
||||
return config.translations.map(translationsPath => ({
|
||||
task: async ({ messages }: { messages: Map<string, { message: string }> }) => {
|
||||
// If `fix` is set we should try apply all possible fixes and override translations file.
|
||||
await integrateLocaleFiles(messages, {
|
||||
dryRun: !fix,
|
||||
ignoreIncompatible: fix || ignoreIncompatible,
|
||||
ignoreUnused: fix || ignoreUnused,
|
||||
ignoreMissing: fix || ignoreMissing,
|
||||
sourceFileName: translationsPath,
|
||||
targetFileName: fix ? translationsPath : undefined,
|
||||
config,
|
||||
log,
|
||||
});
|
||||
},
|
||||
title: `Compatibility check with ${translationsPath}`,
|
||||
}));
|
||||
}
|
|
@ -18,19 +18,18 @@
|
|||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import Listr from 'listr';
|
||||
|
||||
import { ErrorReporter, extractMessagesFromPathToMap, filterConfigPaths, I18nConfig } from '..';
|
||||
import { createFailError } from '../../run';
|
||||
|
||||
export async function extractDefaultMessages({
|
||||
export function extractDefaultMessages({
|
||||
path,
|
||||
config,
|
||||
}: {
|
||||
path?: string | string[];
|
||||
config: I18nConfig;
|
||||
}) {
|
||||
const filteredPaths = filterConfigPaths(Array.isArray(path) ? path : [path || './'], config);
|
||||
const inputPaths = Array.isArray(path) ? path : [path || './'];
|
||||
const filteredPaths = filterConfigPaths(inputPaths, config) as string[];
|
||||
if (filteredPaths.length === 0) {
|
||||
throw createFailError(
|
||||
`${chalk.white.bgRed(
|
||||
|
@ -39,36 +38,22 @@ export async function extractDefaultMessages({
|
|||
);
|
||||
}
|
||||
|
||||
const reporter = new ErrorReporter();
|
||||
return filteredPaths.map(filteredPath => ({
|
||||
task: async (context: {
|
||||
messages: Map<string, { message: string }>;
|
||||
reporter: ErrorReporter;
|
||||
}) => {
|
||||
const { messages, reporter } = context;
|
||||
const initialErrorsNumber = reporter.errors.length;
|
||||
|
||||
const list = new Listr(
|
||||
filteredPaths.map(filteredPath => ({
|
||||
task: async (messages: Map<string, unknown>) => {
|
||||
const initialErrorsNumber = reporter.errors.length;
|
||||
// Return result if no new errors were reported for this path.
|
||||
const result = await extractMessagesFromPathToMap(filteredPath, messages, config, reporter);
|
||||
if (reporter.errors.length === initialErrorsNumber) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return result if no new errors were reported for this path.
|
||||
const result = await extractMessagesFromPathToMap(filteredPath, messages, config, reporter);
|
||||
if (reporter.errors.length === initialErrorsNumber) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Throw an empty error to make Listr mark the task as failed without any message.
|
||||
throw new Error('');
|
||||
},
|
||||
title: filteredPath,
|
||||
})),
|
||||
{
|
||||
exitOnError: false,
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
return await list.run(new Map());
|
||||
} catch (error) {
|
||||
if (error.name === 'ListrError' && reporter.errors.length) {
|
||||
throw createFailError(reporter.errors.join('\n\n'));
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
throw reporter;
|
||||
},
|
||||
title: filteredPath,
|
||||
}));
|
||||
}
|
||||
|
|
109
src/dev/i18n/tasks/extract_untracked_translations.ts
Normal file
109
src/dev/i18n/tasks/extract_untracked_translations.ts
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
I18nConfig,
|
||||
matchEntriesWithExctractors,
|
||||
normalizePath,
|
||||
readFileAsync,
|
||||
ErrorReporter,
|
||||
} from '..';
|
||||
import { createFailError } from '../../run';
|
||||
|
||||
function filterEntries(entries: string[], exclude: string[]) {
|
||||
return entries.filter((entry: string) =>
|
||||
exclude.every((excludedPath: string) => !normalizePath(entry).startsWith(excludedPath))
|
||||
);
|
||||
}
|
||||
|
||||
export async function extractUntrackedMessagesTask({
|
||||
path,
|
||||
config,
|
||||
reporter,
|
||||
}: {
|
||||
path?: string | string[];
|
||||
config: I18nConfig;
|
||||
reporter: any;
|
||||
}) {
|
||||
const inputPaths = Array.isArray(path) ? path : [path || './'];
|
||||
const availablePaths = Object.values(config.paths);
|
||||
const ignore = availablePaths.concat([
|
||||
'**/build/**',
|
||||
'**/webpackShims/**',
|
||||
'**/__fixtures__/**',
|
||||
'**/packages/kbn-i18n/**',
|
||||
'**/packages/kbn-plugin-generator/sao_template/**',
|
||||
'**/packages/kbn-ui-framework/generator-kui/**',
|
||||
'**/target/**',
|
||||
'**/test/**',
|
||||
'**/scripts/**',
|
||||
'**/src/dev/**',
|
||||
'**/target/**',
|
||||
'**/dist/**',
|
||||
]);
|
||||
for (const inputPath of inputPaths) {
|
||||
const categorizedEntries = await matchEntriesWithExctractors(inputPath, {
|
||||
additionalIgnore: ignore,
|
||||
mark: true,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
for (const [entries, extractFunction] of categorizedEntries) {
|
||||
const files = await Promise.all(
|
||||
filterEntries(entries, config.exclude)
|
||||
.filter(entry => {
|
||||
const normalizedEntry = normalizePath(entry);
|
||||
return !availablePaths.some(
|
||||
availablePath =>
|
||||
normalizedEntry.startsWith(`${normalizePath(availablePath)}/`) ||
|
||||
normalizePath(availablePath) === normalizedEntry
|
||||
);
|
||||
})
|
||||
.map(async (entry: any) => ({
|
||||
name: entry,
|
||||
content: await readFileAsync(entry),
|
||||
}))
|
||||
);
|
||||
|
||||
for (const { name, content } of files) {
|
||||
const reporterWithContext = reporter.withContext({ name });
|
||||
for (const [id] of extractFunction(content, reporterWithContext)) {
|
||||
const errorMessage = `Untracked file contains i18n label (${id}).`;
|
||||
reporterWithContext.report(createFailError(errorMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function extractUntrackedMessages(srcPaths: string[], config: I18nConfig) {
|
||||
return srcPaths.map(srcPath => ({
|
||||
title: `Checking untracked messages in ${srcPath}`,
|
||||
task: async (context: { reporter: ErrorReporter }) => {
|
||||
const { reporter } = context;
|
||||
const initialErrorsNumber = reporter.errors.length;
|
||||
const result = await extractUntrackedMessagesTask({ path: srcPath, config, reporter });
|
||||
if (reporter.errors.length === initialErrorsNumber) {
|
||||
return result;
|
||||
}
|
||||
|
||||
throw reporter;
|
||||
},
|
||||
}));
|
||||
}
|
|
@ -18,3 +18,5 @@
|
|||
*/
|
||||
|
||||
export { extractDefaultMessages } from './extract_default_translations';
|
||||
export { extractUntrackedMessages } from './extract_untracked_translations';
|
||||
export { checkCompatibility } from './check_compatibility';
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import chalk from 'chalk';
|
||||
import Listr from 'listr';
|
||||
|
||||
import { integrateLocaleFiles, mergeConfigs } from './i18n';
|
||||
import { extractDefaultMessages } from './i18n/tasks';
|
||||
import { ErrorReporter, mergeConfigs } from './i18n';
|
||||
import { extractDefaultMessages, extractUntrackedMessages, checkCompatibility } from './i18n/tasks';
|
||||
import { createFailError, run } from './run';
|
||||
|
||||
run(
|
||||
|
@ -60,48 +60,58 @@ run(
|
|||
}
|
||||
|
||||
const config = await mergeConfigs(includeConfig);
|
||||
const defaultMessages = await extractDefaultMessages({ path, config });
|
||||
const srcPaths = Array().concat(path || ['./src', './packages', './x-pack']);
|
||||
|
||||
if (config.translations.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const list = new Listr(
|
||||
config.translations.map(translationsPath => ({
|
||||
task: async () => {
|
||||
// If `--fix` is set we should try apply all possible fixes and override translations file.
|
||||
await integrateLocaleFiles(defaultMessages, {
|
||||
sourceFileName: translationsPath,
|
||||
targetFileName: fix ? translationsPath : undefined,
|
||||
dryRun: !fix,
|
||||
ignoreIncompatible: fix || !!ignoreIncompatible,
|
||||
ignoreUnused: fix || !!ignoreUnused,
|
||||
ignoreMissing: fix || !!ignoreMissing,
|
||||
config,
|
||||
log,
|
||||
});
|
||||
[
|
||||
{
|
||||
title: 'Checking For Untracked Messages',
|
||||
task: () => new Listr(extractUntrackedMessages(srcPaths, config), { exitOnError: true }),
|
||||
},
|
||||
title: `Compatibility check with ${translationsPath}`,
|
||||
})),
|
||||
{
|
||||
title: 'Validating Default Messages',
|
||||
task: () =>
|
||||
new Listr(extractDefaultMessages({ path: srcPaths, config }), { exitOnError: true }),
|
||||
},
|
||||
{
|
||||
title: 'Compatibility Checks',
|
||||
task: () =>
|
||||
new Listr(
|
||||
checkCompatibility(
|
||||
config,
|
||||
{
|
||||
ignoreIncompatible: !!ignoreIncompatible,
|
||||
ignoreUnused: !!ignoreUnused,
|
||||
ignoreMissing: !!ignoreMissing,
|
||||
fix,
|
||||
},
|
||||
log
|
||||
),
|
||||
{ exitOnError: true }
|
||||
),
|
||||
},
|
||||
],
|
||||
{
|
||||
concurrent: true,
|
||||
exitOnError: false,
|
||||
concurrent: false,
|
||||
exitOnError: true,
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
await list.run();
|
||||
const reporter = new ErrorReporter();
|
||||
const messages: Map<string, { message: string }> = new Map();
|
||||
await list.run({ messages, reporter });
|
||||
} catch (error) {
|
||||
process.exitCode = 1;
|
||||
|
||||
if (!error.errors) {
|
||||
if (error instanceof ErrorReporter) {
|
||||
error.errors.forEach((e: string | Error) => log.error(e));
|
||||
} else {
|
||||
log.error('Unhandled exception!');
|
||||
log.error(error);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
for (const e of error.errors) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -18,9 +18,16 @@
|
|||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import Listr from 'listr';
|
||||
import { resolve } from 'path';
|
||||
|
||||
import { mergeConfigs, serializeToJson, serializeToJson5, writeFileAsync } from './i18n';
|
||||
import {
|
||||
ErrorReporter,
|
||||
mergeConfigs,
|
||||
serializeToJson,
|
||||
serializeToJson5,
|
||||
writeFileAsync,
|
||||
} from './i18n';
|
||||
import { extractDefaultMessages } from './i18n/tasks';
|
||||
import { createFailError, run } from './run';
|
||||
|
||||
|
@ -32,6 +39,7 @@ run(
|
|||
'output-format': outputFormat,
|
||||
'include-config': includeConfig,
|
||||
},
|
||||
log,
|
||||
}) => {
|
||||
if (!outputDir || typeof outputDir !== 'string') {
|
||||
throw createFailError(
|
||||
|
@ -46,18 +54,42 @@ run(
|
|||
}
|
||||
|
||||
const config = await mergeConfigs(includeConfig);
|
||||
const defaultMessages = await extractDefaultMessages({ path, config });
|
||||
|
||||
// Messages shouldn't be written to a file if output is not supplied.
|
||||
if (!outputDir || !defaultMessages.size) {
|
||||
return;
|
||||
const list = new Listr([
|
||||
{
|
||||
title: 'Extracting Default Messages',
|
||||
task: () => new Listr(extractDefaultMessages({ path, config }), { exitOnError: true }),
|
||||
},
|
||||
{
|
||||
title: 'Writing to file',
|
||||
enabled: ctx => outputDir && ctx.messages.size,
|
||||
task: async ctx => {
|
||||
const sortedMessages = [...ctx.messages].sort(([key1], [key2]) =>
|
||||
key1.localeCompare(key2)
|
||||
);
|
||||
await writeFileAsync(
|
||||
resolve(outputDir, 'en.json'),
|
||||
outputFormat === 'json5'
|
||||
? serializeToJson5(sortedMessages)
|
||||
: serializeToJson(sortedMessages)
|
||||
);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
try {
|
||||
const reporter = new ErrorReporter();
|
||||
const messages: Map<string, { message: string }> = new Map();
|
||||
await list.run({ messages, reporter });
|
||||
} catch (error) {
|
||||
process.exitCode = 1;
|
||||
if (error instanceof ErrorReporter) {
|
||||
error.errors.forEach((e: string | Error) => log.error(e));
|
||||
} else {
|
||||
log.error('Unhandled exception!');
|
||||
log.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
const sortedMessages = [...defaultMessages].sort(([key1], [key2]) => key1.localeCompare(key2));
|
||||
await writeFileAsync(
|
||||
resolve(outputDir, 'en.json'),
|
||||
outputFormat === 'json5' ? serializeToJson5(sortedMessages) : serializeToJson(sortedMessages)
|
||||
);
|
||||
},
|
||||
{
|
||||
flags: {
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import Listr from 'listr';
|
||||
|
||||
import { integrateLocaleFiles, mergeConfigs } from './i18n';
|
||||
import { ErrorReporter, integrateLocaleFiles, mergeConfigs } from './i18n';
|
||||
import { extractDefaultMessages } from './i18n/tasks';
|
||||
import { createFailError, run } from './run';
|
||||
|
||||
|
@ -75,18 +76,41 @@ run(
|
|||
}
|
||||
|
||||
const config = await mergeConfigs(includeConfig);
|
||||
const defaultMessages = await extractDefaultMessages({ path, config });
|
||||
const list = new Listr([
|
||||
{
|
||||
title: 'Extracting Default Messages',
|
||||
task: () => new Listr(extractDefaultMessages({ path, config }), { exitOnError: true }),
|
||||
},
|
||||
{
|
||||
title: 'Intregrating Locale File',
|
||||
task: async ({ messages }) => {
|
||||
await integrateLocaleFiles(messages, {
|
||||
sourceFileName: source,
|
||||
targetFileName: target,
|
||||
dryRun,
|
||||
ignoreIncompatible,
|
||||
ignoreUnused,
|
||||
ignoreMissing,
|
||||
config,
|
||||
log,
|
||||
});
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
await integrateLocaleFiles(defaultMessages, {
|
||||
sourceFileName: source,
|
||||
targetFileName: target,
|
||||
dryRun,
|
||||
ignoreIncompatible,
|
||||
ignoreUnused,
|
||||
ignoreMissing,
|
||||
config,
|
||||
log,
|
||||
});
|
||||
try {
|
||||
const reporter = new ErrorReporter();
|
||||
const messages: Map<string, { message: string }> = new Map();
|
||||
await list.run({ messages, reporter });
|
||||
} catch (error) {
|
||||
process.exitCode = 1;
|
||||
if (error instanceof ErrorReporter) {
|
||||
error.errors.forEach((e: string | Error) => log.error(e));
|
||||
} else {
|
||||
log.error('Unhandled exception!');
|
||||
log.error(error);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
flags: {
|
||||
|
|
|
@ -42,7 +42,7 @@ export async function buildContextMenuForActions({
|
|||
|
||||
return {
|
||||
id: 'mainMenu',
|
||||
title: i18n.translate('embeddableAPI.actionPanel.title', {
|
||||
title: i18n.translate('embeddableApi.actionPanel.title', {
|
||||
defaultMessage: 'Options',
|
||||
}),
|
||||
items: menuItems,
|
||||
|
|
|
@ -35,7 +35,7 @@ export class AddPanelAction extends Action {
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.panel.addPanel.displayName', {
|
||||
return i18n.translate('embeddableApi.addPanel.displayName', {
|
||||
defaultMessage: 'Add panel',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ export class AddPanelFlyout extends React.Component<Props> {
|
|||
|
||||
this.lastToast = toastNotifications.addSuccess({
|
||||
title: i18n.translate(
|
||||
'kbn.embeddables.addPanel.savedObjectAddedToContainerSuccessMessageTitle',
|
||||
'embeddableApi.addPanel.savedObjectAddedToContainerSuccessMessageTitle',
|
||||
{
|
||||
defaultMessage: '{savedObjectName} was added',
|
||||
values: {
|
||||
|
@ -103,7 +103,7 @@ export class AddPanelFlyout extends React.Component<Props> {
|
|||
inputDisplay: (
|
||||
<EuiText>
|
||||
<FormattedMessage
|
||||
id="kbn.embeddables.addPanel.createNewDefaultOption"
|
||||
id="embeddableApi.addPanel.createNewDefaultOption"
|
||||
defaultMessage="Create new ..."
|
||||
/>
|
||||
</EuiText>
|
||||
|
@ -119,7 +119,7 @@ export class AddPanelFlyout extends React.Component<Props> {
|
|||
inputDisplay: (
|
||||
<EuiText>
|
||||
<FormattedMessage
|
||||
id="kbn.embeddables.addPanel.createNew"
|
||||
id="embeddableApi.addPanel.createNew"
|
||||
defaultMessage="Create new {factoryName}"
|
||||
values={{
|
||||
factoryName: factory.getDisplayName(),
|
||||
|
@ -139,7 +139,7 @@ export class AddPanelFlyout extends React.Component<Props> {
|
|||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2>
|
||||
<FormattedMessage id="kbn.embeddables.addPanelsTitle" defaultMessage="Add panels" />
|
||||
<FormattedMessage id="embeddableApi.addPanel.Title" defaultMessage="Add panels" />
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
|
@ -159,7 +159,7 @@ export class AddPanelFlyout extends React.Component<Props> {
|
|||
>
|
||||
}
|
||||
showFilter={true}
|
||||
noItemsMessage={i18n.translate('kbn.embeddables.addPanel.noMatchingObjectsMessage', {
|
||||
noItemsMessage={i18n.translate('embeddableApi.addPanel.noMatchingObjectsMessage', {
|
||||
defaultMessage: 'No matching objects found.',
|
||||
})}
|
||||
/>
|
||||
|
|
|
@ -40,7 +40,7 @@ export class CustomizePanelTitleAction extends Action {
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddables.panel.customizePanel.displayName', {
|
||||
return i18n.translate('embeddableApi.customizePanel.action.displayName', {
|
||||
defaultMessage: 'Customize panel',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ export class CustomizePanelModalUi extends Component<CustomizePanelProps, State>
|
|||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Show panel title"
|
||||
id="embeddable.customizePanel.showTitle"
|
||||
id="embeddableApi.customizePanel.modal.showTitle"
|
||||
/>
|
||||
}
|
||||
onChange={this.onHideTitleToggle}
|
||||
|
@ -105,7 +105,7 @@ export class CustomizePanelModalUi extends Component<CustomizePanelProps, State>
|
|||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label={this.props.intl.formatMessage({
|
||||
id: 'kbn.dashboard.panel.optionsMenuForm.panelTitleFormRowLabel',
|
||||
id: 'embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleFormRowLabel',
|
||||
defaultMessage: 'Panel title',
|
||||
})}
|
||||
>
|
||||
|
@ -119,7 +119,7 @@ export class CustomizePanelModalUi extends Component<CustomizePanelProps, State>
|
|||
value={this.state.title || ''}
|
||||
onChange={e => this.updateTitle(e.target.value)}
|
||||
aria-label={this.props.intl.formatMessage({
|
||||
id: 'kbn.embeddable.panel.optionsMenuForm.panelTitleInputAriaLabel',
|
||||
id: 'embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleInputAriaLabel',
|
||||
defaultMessage: 'Enter a custom title for your panel',
|
||||
})}
|
||||
append={
|
||||
|
@ -129,7 +129,7 @@ export class CustomizePanelModalUi extends Component<CustomizePanelProps, State>
|
|||
disabled={this.state.hideTitle}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="kbn.dashboard.panel.optionsMenuForm.resetCustomDashboardButtonLabel"
|
||||
id="embeddableApi.customizePanel.modal.optionsMenuForm.resetCustomDashboardButtonLabel"
|
||||
defaultMessage="Reset"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
|
@ -142,11 +142,17 @@ export class CustomizePanelModalUi extends Component<CustomizePanelProps, State>
|
|||
onClick={() => this.props.updateTitle(this.props.embeddable.getOutput().title)}
|
||||
>
|
||||
{' '}
|
||||
<FormattedMessage id="kbn.embeddables.customizePanel.cancel" defaultMessage="Cancel" />
|
||||
<FormattedMessage
|
||||
id="embeddableApi.customizePanel.modal.cancel"
|
||||
defaultMessage="Cancel"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
|
||||
<EuiButton data-test-subj="saveNewTitleButton" onClick={this.save} fill>
|
||||
<FormattedMessage id="kbn.embeddables.customizePanel.save" defaultMessage="Save" />
|
||||
<FormattedMessage
|
||||
id="embeddableApi.customizePanel.modal.saveButtonTitle"
|
||||
defaultMessage="Save"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiModalFooter>
|
||||
</React.Fragment>
|
||||
|
|
|
@ -46,7 +46,7 @@ function CustomizeTitleFormUi({
|
|||
<div className="embPanel__optionsMenuForm" data-test-subj="dashboardPanelTitleInputMenuItem">
|
||||
<EuiFormRow
|
||||
label={intl.formatMessage({
|
||||
id: 'kbn.dashboard.panel.optionsMenuForm.panelTitleFormRowLabel',
|
||||
id: 'embeddableApi.customizeTitle.optionsMenuForm.panelTitleFormRowLabel',
|
||||
defaultMessage: 'Panel title',
|
||||
})}
|
||||
>
|
||||
|
@ -58,7 +58,7 @@ function CustomizeTitleFormUi({
|
|||
value={title}
|
||||
onChange={onInputChange}
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'kbn.dashboard.panel.optionsMenuForm.panelTitleInputAriaLabel',
|
||||
id: 'embeddableApi.customizeTitle.optionsMenuForm.panelTitleInputAriaLabel',
|
||||
defaultMessage: 'Changes to this input are applied immediately. Press enter to exit.',
|
||||
})}
|
||||
/>
|
||||
|
@ -66,7 +66,7 @@ function CustomizeTitleFormUi({
|
|||
|
||||
<EuiButtonEmpty data-test-subj="resetCustomEmbeddablePanelTitle" onClick={onReset}>
|
||||
<FormattedMessage
|
||||
id="kbn.dashboard.panel.optionsMenuForm.resetCustomDashboardButtonLabel"
|
||||
id="embeddableApi.customizeTitle.optionsMenuForm.resetCustomDashboardButtonLabel"
|
||||
defaultMessage="Reset title"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
|
|
|
@ -40,7 +40,7 @@ export class EditPanelAction extends Action {
|
|||
if (!factory) {
|
||||
throw new EmbeddableFactoryNotFoundError(embeddable.type);
|
||||
}
|
||||
return i18n.translate('kbn.dashboard.panel.editPanel.displayName', {
|
||||
return i18n.translate('embeddableApi.panel.editPanel.displayName', {
|
||||
defaultMessage: 'Edit {value}',
|
||||
values: {
|
||||
value: factory.getDisplayName(),
|
||||
|
|
|
@ -34,7 +34,7 @@ export class InspectPanelAction extends Action {
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.panel.inspectPanel.displayName', {
|
||||
return i18n.translate('embeddableApi.panel.inspectPanel.displayName', {
|
||||
defaultMessage: 'Inspect',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export class RemovePanelAction extends Action {
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.panel.removePanel.displayName', {
|
||||
return i18n.translate('embeddableApi.panel.removePanel.displayName', {
|
||||
defaultMessage: 'Delete from dashboard',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ function PanelHeaderUi({
|
|||
title={title}
|
||||
aria-label={intl.formatMessage(
|
||||
{
|
||||
id: 'kbn.dashboard.panel.dashboardPanelAriaLabel',
|
||||
id: 'embeddableApi.panel.dashboardPanelAriaLabel',
|
||||
defaultMessage: 'Dashboard panel: {title}',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -84,7 +84,7 @@ class PanelOptionsMenuUi extends React.Component<PanelOptionsMenuUiProps, State>
|
|||
color="text"
|
||||
className="embPanel__optionsMenuButton"
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'kbn.dashboard.panel.optionsMenu.panelOptionsButtonAriaLabel',
|
||||
id: 'embeddableApi.panel.optionsMenu.panelOptionsButtonAriaLabel',
|
||||
defaultMessage: 'Panel options',
|
||||
})}
|
||||
data-test-subj="embeddablePanelToggleMenuIcon"
|
||||
|
|
|
@ -35,7 +35,7 @@ export class ContactCardEmbeddableFactory extends EmbeddableFactory<ContactCardE
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.samples.contactCard.displayName', {
|
||||
return i18n.translate('embeddableApi.samples.contactCard.displayName', {
|
||||
defaultMessage: 'contact card',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ export class FilterableContainerFactory extends EmbeddableFactory<FilterableCont
|
|||
public readonly type = FILTERABLE_CONTAINER;
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.samples.filterable.displayName', {
|
||||
return i18n.translate('embeddableApi.samples.filterableContainer.displayName', {
|
||||
defaultMessage: 'filterable dashboard',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export class FilterableEmbeddableFactory extends EmbeddableFactory<FilterableEmb
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.samples.filterable.displayName', {
|
||||
return i18n.translate('embeddableApi.samples.filterableEmbeddable.displayName', {
|
||||
defaultMessage: 'filterable',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ export class HelloWorldEmbeddableFactory extends EmbeddableFactory {
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('kbn.embeddable.samples.helloworld.displayName', {
|
||||
return i18n.translate('embeddableApi.samples.helloworld.displayName', {
|
||||
defaultMessage: 'hello world',
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue