Skip to content

Commit 68c3778

Browse files
committed
update tests
1 parent ade0188 commit 68c3778

5 files changed

Lines changed: 136 additions & 33 deletions

File tree

src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
jest.mock('@kbn/i18n');
10+
11+
import { i18n } from '@kbn/i18n';
12+
13+
import i18ntokens from '@elastic/eui/i18ntokens.json';
14+
import { getEuiContextMapping } from './i18n_eui_mapping';
15+
16+
/** Regexp to find {values} usage */
17+
const VALUES_REGEXP = /\{\w+\}/;
18+
19+
describe('@elastic/eui i18n tokens', () => {
20+
const i18nTranslateMock = jest
21+
.fn()
22+
.mockImplementation((id, { defaultMessage }) => defaultMessage);
23+
i18n.translate = i18nTranslateMock;
24+
25+
const euiContextMapping = getEuiContextMapping();
26+
27+
test('all tokens are mapped', () => {
28+
// Extract the tokens from the EUI library: We need to uniq them because they might be duplicated
29+
const euiTokensFromLib = [...new Set(i18ntokens.map(({ token }) => token))];
30+
const euiTokensFromMapping = Object.keys(euiContextMapping);
31+
32+
expect(euiTokensFromMapping.sort()).toStrictEqual(euiTokensFromLib.sort());
33+
});
34+
35+
test('tokens that include {word} should be mapped to functions', () => {
36+
const euiTokensFromLibWithValues = i18ntokens.filter(({ defString }) =>
37+
VALUES_REGEXP.test(defString)
38+
);
39+
const euiTokensFromLib = [...new Set(euiTokensFromLibWithValues.map(({ token }) => token))];
40+
const euiTokensFromMapping = Object.entries(euiContextMapping)
41+
.filter(([, value]) => typeof value === 'function')
42+
.map(([key]) => key);
43+
44+
expect(euiTokensFromMapping.sort()).toStrictEqual(euiTokensFromLib.sort());
45+
});
46+
47+
i18ntokens.forEach(({ token, defString }) => {
48+
describe(`Token "${token}"`, () => {
49+
let i18nTranslateCall: [
50+
string,
51+
{ defaultMessage: string; values?: object; description?: string }
52+
];
53+
54+
beforeAll(() => {
55+
// If it's a function, call it, so we have the mock to register the call.
56+
const entry = euiContextMapping[token as keyof typeof euiContextMapping];
57+
const translationOutput = typeof entry === 'function' ? entry({}) : entry;
58+
59+
// If it's a string, it comes from i18n.translate call
60+
if (typeof translationOutput === 'string') {
61+
// find the call in the mocks
62+
i18nTranslateCall = i18nTranslateMock.mock.calls.find(
63+
([kbnToken]) => kbnToken === `core.${token}`
64+
);
65+
} else {
66+
// Otherwise, it's a fn returning `FormattedMessage` component => read the props
67+
const { id, defaultMessage, values } = translationOutput.props;
68+
i18nTranslateCall = [id, { defaultMessage, values }];
69+
}
70+
});
71+
72+
test('a translation should be registered as `core.{TOKEN}`', () => {
73+
expect(i18nTranslateCall).not.toBeUndefined();
74+
});
75+
76+
test('defaultMessage is in sync with defString', () => {
77+
// Clean up typical errors from the `@elastic/eui` extraction token tool
78+
const normalizedDefString = defString
79+
// Quoted words should use double-quotes
80+
.replace(/\s'/g, ' "')
81+
.replace(/'\s/g, '" ')
82+
// Should not include break-lines
83+
.replace(/\n/g, '')
84+
// Should trim extra spaces
85+
.replace(/\s{2,}/g, ' ')
86+
.trim();
87+
88+
expect(i18nTranslateCall[1].defaultMessage).toBe(normalizedDefString);
89+
});
90+
91+
test('values should match', () => {
92+
const valuesFromEuiLib = defString.match(new RegExp(VALUES_REGEXP, 'g')) || [];
93+
const receivedValuesInMock = Object.keys(i18nTranslateCall[1].values ?? {}).map(
94+
(key) => `{${key}}`
95+
);
96+
expect(receivedValuesInMock.sort()).toStrictEqual(valuesFromEuiLib.sort());
97+
});
98+
});
99+
});
100+
});

src/core/public/i18n/i18n_eui_mapping.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface EuiValues {
1515
}
1616

1717
export const getEuiContextMapping = () => {
18-
const euiContextMapping = {
18+
return {
1919
'euiAccordion.isLoading': i18n.translate('core.euiAccordion.isLoading', {
2020
defaultMessage: 'Loading',
2121
}),
@@ -143,12 +143,6 @@ export const getEuiContextMapping = () => {
143143
'ARIA label and tooltip content describing a button that expands an actions menu',
144144
}
145145
),
146-
'euiCollapsibleNav.closeButtonLabel': i18n.translate(
147-
'core.euiCollapsibleNav.closeButtonLabel',
148-
{
149-
defaultMessage: 'close',
150-
}
151-
),
152146
'euiColorPicker.screenReaderAnnouncement': i18n.translate(
153147
'core.euiColorPicker.screenReaderAnnouncement',
154148
{
@@ -1134,7 +1128,24 @@ export const getEuiContextMapping = () => {
11341128
defaultMessage: 'You can quickly navigate this list using arrow keys.',
11351129
}
11361130
),
1131+
'euiNotificationEventReadIcon.read': i18n.translate('core.euiNotificationEventReadIcon.read', {
1132+
defaultMessage: 'Read',
1133+
}),
1134+
'euiNotificationEventReadIcon.readAria': ({ eventName }: EuiValues) =>
1135+
i18n.translate('core.euiNotificationEventReadIcon.readAria', {
1136+
defaultMessage: '{eventName} is read',
1137+
values: { eventName },
1138+
}),
1139+
'euiNotificationEventReadIcon.unread': i18n.translate(
1140+
'core.euiNotificationEventReadIcon.unread',
1141+
{
1142+
defaultMessage: 'Unread',
1143+
}
1144+
),
1145+
'euiNotificationEventReadIcon.unreadAria': ({ eventName }: EuiValues) =>
1146+
i18n.translate('core.euiNotificationEventReadIcon.unreadAria', {
1147+
defaultMessage: '{eventName} is unread',
1148+
values: { eventName },
1149+
}),
11371150
};
1138-
1139-
return euiContextMapping;
11401151
};

x-pack/plugins/translations/translations/ja-JP.json

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@
244244
"core.euiBasicTable.selectThisRow": "この行を選択",
245245
"core.euiBasicTable.tableAutoCaptionWithoutPagination": "この表には{itemCount}行あります。",
246246
"core.euiBasicTable.tableCaptionWithPagination": "{tableCaption}; {page}/{pageCount}ページ。",
247-
"core.euiBasicTable.tableDescriptionWithoutPagination": "この表には{totalItemCount}行中{itemCount}行あります; {page}/{pageCount}ページ。",
248247
"core.euiBasicTable.tablePagination": "前の表のページネーション: {tableCaption}",
249248
"core.euiBasicTable.tableSimpleAutoCaptionWithPagination": "この表には{itemCount}行あります; {page}/{pageCount}ページ。",
250249
"core.euiBottomBar.customScreenReaderAnnouncement": "ドキュメントの最後には、新しいリージョンランドマーク{landmarkHeading}とページレベルのコントロールがあります。",
@@ -332,7 +331,6 @@
332331
"core.euiFieldPassword.showPassword": "パスワードをプレーンテキストとして表示します。注記:こうすると、パスワードが誰にでも見える形で画面に表示されます。",
333332
"core.euiFilePicker.clearSelectedFiles": "選択したファイルを消去",
334333
"core.euiFilePicker.filesSelected": "選択されたファイル",
335-
"core.euiFilterButton.filterBadge": "${count} ${filterCountLabel} 個のフィルター",
336334
"core.euiFlyout.closeAriaLabel": "このダイアログを閉じる",
337335
"core.euiForm.addressFormErrors": "ハイライトされたエラーを修正してください。",
338336
"core.euiFormControlLayoutClearButton.label": "インプットを消去",
@@ -357,8 +355,6 @@
357355
"core.euiMarkdownEditorToolbar.editor": "エディター",
358356
"core.euiMarkdownEditorToolbar.previewMarkdown": "プレビュー",
359357
"core.euiModal.closeModal": "このモーダルウィンドウを閉じます",
360-
"core.euiNotificationEventMessages.accordionAriaLabelButtonText": "+ {messagesLength}以上",
361-
"core.euiNotificationEventMessages.accordionButtonText": "+ {eventName}の{messagesLength}メッセージ",
362358
"core.euiNotificationEventMessages.accordionHideText": "非表示",
363359
"core.euiNotificationEventMeta.contextMenuButton": "{eventName}のメニュー",
364360
"core.euiNotificationEventReadButton.markAsRead": "既読に設定",
@@ -6081,8 +6077,6 @@
60816077
"xpack.canvas.error.useImportWorkpad.missingPropertiesErrorMessage": "{CANVAS} ワークパッドに必要なプロパティの一部が欠けています。 {JSON} ファイルを編集して正しいプロパティ値を入力し、再試行してください。",
60826078
"xpack.canvas.error.workpadRoutes.createFailureErrorMessage": "ワークパッドを作成できませんでした",
60836079
"xpack.canvas.error.workpadRoutes.loadFailureErrorMessage": "ID でワークパッドを読み込めませんでした",
6084-
"expressionError.errorComponent.description": "表現が失敗し次のメッセージが返されました:",
6085-
"expressionError.errorComponent.title": "おっと!表現が失敗しました",
60866080
"xpack.canvas.expression.cancelButtonLabel": "キャンセル",
60876081
"xpack.canvas.expression.closeButtonLabel": "閉じる",
60886082
"xpack.canvas.expression.learnLinkText": "表現構文の詳細",
@@ -6494,15 +6488,11 @@
64946488
"xpack.canvas.renderer.advancedFilter.displayName": "高度なフィルター",
64956489
"xpack.canvas.renderer.advancedFilter.helpDescription": "Canvas フィルター表現をレンダリングします。",
64966490
"xpack.canvas.renderer.advancedFilter.inputPlaceholder": "フィルター表現を入力",
6497-
"expressionError.renderer.debug.displayName": "デバッグ",
6498-
"expressionError.renderer.debug.helpDescription": "デバッグアウトプットをフォーマットされた {JSON} としてレンダリングします",
64996491
"xpack.canvas.renderer.dropdownFilter.displayName": "ドロップダウンフィルター",
65006492
"xpack.canvas.renderer.dropdownFilter.helpDescription": "「{exactly}」フィルターの値を選択できるドロップダウンです",
65016493
"xpack.canvas.renderer.dropdownFilter.matchAllOptionLabel": "すべて",
65026494
"xpack.canvas.renderer.embeddable.displayName": "埋め込み可能",
65036495
"xpack.canvas.renderer.embeddable.helpDescription": "Kibana の他の部分から埋め込み可能な保存済みオブジェクトをレンダリングします",
6504-
"expressionError.renderer.error.displayName": "エラー情報",
6505-
"expressionError.renderer.error.helpDescription": "エラーデータをユーザーにわかるようにレンダリングします",
65066496
"xpack.canvas.renderer.image.displayName": "画像",
65076497
"xpack.canvas.renderer.image.helpDescription": "画像をレンダリングします",
65086498
"xpack.canvas.renderer.markdown.displayName": "マークダウン",
@@ -6986,6 +6976,12 @@
69866976
"xpack.canvas.workpadTemplates.table.descriptionColumnTitle": "説明",
69876977
"xpack.canvas.workpadTemplates.table.nameColumnTitle": "テンプレート名",
69886978
"xpack.canvas.workpadTemplates.table.tagsColumnTitle": "タグ",
6979+
"expressionError.errorComponent.description": "表現が失敗し次のメッセージが返されました:",
6980+
"expressionError.errorComponent.title": "おっと!表現が失敗しました",
6981+
"expressionError.renderer.debug.displayName": "デバッグ",
6982+
"expressionError.renderer.debug.helpDescription": "デバッグアウトプットをフォーマットされた {JSON} としてレンダリングします",
6983+
"expressionError.renderer.error.displayName": "エラー情報",
6984+
"expressionError.renderer.error.helpDescription": "エラーデータをユーザーにわかるようにレンダリングします",
69896985
"expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "表示される背景画像です。画像アセットは「{BASE64}」データ {URL} として提供するか、部分式で渡します。",
69906986
"expressionRevealImage.functions.revealImage.args.imageHelpText": "表示する画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。",
69916987
"expressionRevealImage.functions.revealImage.args.originHelpText": "画像で埋め始める位置です。たとえば、{list}、または {end}です。",

x-pack/plugins/translations/translations/zh-CN.json

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@
247247
"core.euiBasicTable.selectThisRow": "选择此行",
248248
"core.euiBasicTable.tableAutoCaptionWithoutPagination": "此表包含 {itemCount} 行。",
249249
"core.euiBasicTable.tableCaptionWithPagination": "{tableCaption};第 {page} 页,共 {pageCount} 页。",
250-
"core.euiBasicTable.tableDescriptionWithoutPagination": "此表包含 {itemCount} 行,共有 {totalItemCount} 行;第 {page} 页,共 {pageCount} 页。",
251250
"core.euiBasicTable.tablePagination": "前表分页:{tableCaption}",
252251
"core.euiBasicTable.tableSimpleAutoCaptionWithPagination": "此表包含 {itemCount} 行;第 {page} 页,共 {pageCount} 页。",
253252
"core.euiBottomBar.customScreenReaderAnnouncement": "有称作 {landmarkHeading} 且页面级别控件位于文档结尾的新地区地标。",
@@ -335,7 +334,6 @@
335334
"core.euiFieldPassword.showPassword": "将密码显示为纯文本。注意:这会将您的密码暴露在屏幕上。",
336335
"core.euiFilePicker.clearSelectedFiles": "清除选定的文件",
337336
"core.euiFilePicker.filesSelected": "个文件已选择",
338-
"core.euiFilterButton.filterBadge": "{count} 个 {filterCountLabel} 筛选",
339337
"core.euiFlyout.closeAriaLabel": "关闭此对话框",
340338
"core.euiForm.addressFormErrors": "请解决突出显示的错误。",
341339
"core.euiFormControlLayoutClearButton.label": "清除输入",
@@ -360,8 +358,6 @@
360358
"core.euiMarkdownEditorToolbar.editor": "编辑器",
361359
"core.euiMarkdownEditorToolbar.previewMarkdown": "预览",
362360
"core.euiModal.closeModal": "关闭此模式窗口",
363-
"core.euiNotificationEventMessages.accordionAriaLabelButtonText": "+ 另外 {messagesLength} 条",
364-
"core.euiNotificationEventMessages.accordionButtonText": "+ {eventName} 的 {messagesLength} 条消息",
365361
"core.euiNotificationEventMessages.accordionHideText": "隐藏",
366362
"core.euiNotificationEventMeta.contextMenuButton": "{eventName} 的菜单",
367363
"core.euiNotificationEventReadButton.markAsRead": "标记为已读",
@@ -6120,8 +6116,6 @@
61206116
"xpack.canvas.error.useImportWorkpad.missingPropertiesErrorMessage": "{CANVAS} Workpad 所需的某些属性缺失。 编辑 {JSON} 文件以提供正确的属性值,然后重试。",
61216117
"xpack.canvas.error.workpadRoutes.createFailureErrorMessage": "无法创建 Workpad",
61226118
"xpack.canvas.error.workpadRoutes.loadFailureErrorMessage": "无法加载具有以下 ID 的 Workpad",
6123-
"expressionError.errorComponent.description": "表达式失败,并显示消息:",
6124-
"expressionError.errorComponent.title": "哎哟!表达式失败",
61256119
"xpack.canvas.expression.cancelButtonLabel": "取消",
61266120
"xpack.canvas.expression.closeButtonLabel": "关闭",
61276121
"xpack.canvas.expression.learnLinkText": "学习表达式语法",
@@ -6534,15 +6528,11 @@
65346528
"xpack.canvas.renderer.advancedFilter.displayName": "高级筛选",
65356529
"xpack.canvas.renderer.advancedFilter.helpDescription": "呈现 Canvas 筛选表达式",
65366530
"xpack.canvas.renderer.advancedFilter.inputPlaceholder": "输入筛选表达式",
6537-
"expressionError.renderer.debug.displayName": "故障排查",
6538-
"expressionError.renderer.debug.helpDescription": "将故障排查输出呈现为带格式的 {JSON}",
65396531
"xpack.canvas.renderer.dropdownFilter.displayName": "下拉列表筛选",
65406532
"xpack.canvas.renderer.dropdownFilter.helpDescription": "可以从其中为“{exactly}”筛选选择值的下拉列表",
65416533
"xpack.canvas.renderer.dropdownFilter.matchAllOptionLabel": "任意",
65426534
"xpack.canvas.renderer.embeddable.displayName": "可嵌入",
65436535
"xpack.canvas.renderer.embeddable.helpDescription": "从 Kibana 的其他部分呈现可嵌入的已保存对象",
6544-
"expressionError.renderer.error.displayName": "错误信息",
6545-
"expressionError.renderer.error.helpDescription": "以用户友好的方式呈现错误数据",
65466536
"xpack.canvas.renderer.image.displayName": "图像",
65476537
"xpack.canvas.renderer.image.helpDescription": "呈现图像",
65486538
"xpack.canvas.renderer.markdown.displayName": "Markdown",
@@ -7034,6 +7024,12 @@
70347024
"xpack.canvas.workpadTemplates.table.descriptionColumnTitle": "描述",
70357025
"xpack.canvas.workpadTemplates.table.nameColumnTitle": "模板名称",
70367026
"xpack.canvas.workpadTemplates.table.tagsColumnTitle": "标签",
7027+
"expressionError.errorComponent.description": "表达式失败,并显示消息:",
7028+
"expressionError.errorComponent.title": "哎哟!表达式失败",
7029+
"expressionError.renderer.debug.displayName": "故障排查",
7030+
"expressionError.renderer.debug.helpDescription": "将故障排查输出呈现为带格式的 {JSON}",
7031+
"expressionError.renderer.error.displayName": "错误信息",
7032+
"expressionError.renderer.error.helpDescription": "以用户友好的方式呈现错误数据",
70377033
"expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "要显示的可选背景图像。以 `{BASE64}` 数据 {URL} 的形式提供图像资产或传入子表达式。",
70387034
"expressionRevealImage.functions.revealImage.args.imageHelpText": "要显示的图像。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。",
70397035
"expressionRevealImage.functions.revealImage.args.originHelpText": "要开始图像填充的位置。例如 {list} 或 {end}。",

0 commit comments

Comments
 (0)