[App Search] Misc naming tech debt (#82770)

* Rename `engine_overview` folder to `engines`

- To better match ent-search folder structure
- Also rename/clarify pluralization of "Engines" where possible, to distinguish between individual Engine Overview pages

* DRY out Engines and Meta Engines titles

* DRY out Credentials title

* DRY out Settings title

* DRY out Role Mappings title

* Update localization keys to match changes

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Constance 2020-11-09 14:10:22 -08:00 committed by GitHub
parent ae6f5afe8d
commit 04c583e2b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 135 additions and 123 deletions

View file

@ -3,8 +3,14 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const CREDENTIALS_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.credentials.title',
{ defaultMessage: 'Credentials' }
);
export enum ApiTokenTypes {
Admin = 'admin',
Private = 'private',

View file

@ -28,6 +28,7 @@ import { FlashMessages } from '../../../shared/flash_messages';
import { CredentialsLogic } from './credentials_logic';
import { externalUrl } from '../../../shared/enterprise_search_url/external_url';
import { CREDENTIALS_TITLE } from './constants';
import { CredentialsList } from './credentials_list';
import { CredentialsFlyout } from './credentials_flyout';
@ -47,21 +48,11 @@ export const Credentials: React.FC = () => {
return (
<>
<SetPageChrome
trail={[
i18n.translate('xpack.enterpriseSearch.appSearch.credentials.title', {
defaultMessage: 'Credentials',
}),
]}
/>
<SetPageChrome trail={[CREDENTIALS_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>
{i18n.translate('xpack.enterpriseSearch.appSearch.credentials.title', {
defaultMessage: 'Credentials',
})}
</h1>
<h1>{CREDENTIALS_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>

View file

@ -5,3 +5,4 @@
*/
export { Credentials } from './credentials';
export { CREDENTIALS_TITLE } from './constants';

View file

@ -9,10 +9,6 @@ import { i18n } from '@kbn/i18n';
// TODO: It's very likely that we'll move these i18n constants to their respective component
// folders once those are migrated over. This is a temporary way of DRYing them out for now.
export const ENGINES_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.engines.title', {
defaultMessage: 'Engines',
});
export const OVERVIEW_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.overview.title',
{ defaultMessage: 'Overview' }

View file

@ -30,8 +30,8 @@ import {
ENGINE_API_LOGS_PATH,
} from '../../routes';
import { getAppSearchUrl } from '../../../shared/enterprise_search_url';
import { ENGINES_TITLE } from '../engines';
import {
ENGINES_TITLE,
OVERVIEW_TITLE,
ANALYTICS_TITLE,
DOCUMENTS_TITLE,

View file

@ -14,7 +14,7 @@ import { getAppSearchUrl } from '../../../../shared/enterprise_search_url';
import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome';
import { CREATE_ENGINES_PATH } from '../../../routes';
import { EngineOverviewHeader } from './header';
import { EnginesOverviewHeader } from './header';
import './empty_state.scss';
@ -34,7 +34,7 @@ export const EmptyState: React.FC = () => {
return (
<>
<SetPageChrome />
<EngineOverviewHeader />
<EnginesOverviewHeader />
<EuiPageContent className="emptyState">
<EuiEmptyPrompt
className="emptyState__prompt"

View file

@ -11,16 +11,16 @@ import { mockTelemetryActions } from '../../../../__mocks__';
import React from 'react';
import { shallow } from 'enzyme';
import { EngineOverviewHeader } from './';
import { EnginesOverviewHeader } from './';
describe('EngineOverviewHeader', () => {
describe('EnginesOverviewHeader', () => {
it('renders', () => {
const wrapper = shallow(<EngineOverviewHeader />);
const wrapper = shallow(<EnginesOverviewHeader />);
expect(wrapper.find('h1')).toHaveLength(1);
});
it('renders a launch app search button that sends telemetry on click', () => {
const wrapper = shallow(<EngineOverviewHeader />);
const wrapper = shallow(<EnginesOverviewHeader />);
const button = wrapper.find('[data-test-subj="launchButton"]');
expect(button.prop('href')).toBe('http://localhost:3002/as');

View file

@ -19,7 +19,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { TelemetryLogic } from '../../../../shared/telemetry';
import { getAppSearchUrl } from '../../../../shared/enterprise_search_url';
export const EngineOverviewHeader: React.FC = () => {
export const EnginesOverviewHeader: React.FC = () => {
const { sendAppSearchTelemetry } = useActions(TelemetryLogic);
const buttonProps = {
@ -42,7 +42,7 @@ export const EngineOverviewHeader: React.FC = () => {
<h1>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.enginesOverview.title"
defaultMessage="Engine Overview"
defaultMessage="Engines Overview"
/>
</h1>
</EuiTitle>

View file

@ -4,6 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { EngineOverviewHeader } from './header';
export { EnginesOverviewHeader } from './header';
export { LoadingState } from './loading_state';
export { EmptyState } from './empty_state';

View file

@ -8,13 +8,13 @@ import React from 'react';
import { EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui';
import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome';
import { EngineOverviewHeader } from './header';
import { EnginesOverviewHeader } from './header';
export const LoadingState: React.FC = () => {
return (
<>
<SetPageChrome />
<EngineOverviewHeader />
<EnginesOverviewHeader />
<EuiPageContent paddingSize="l">
<EuiLoadingContent lines={5} />
<EuiSpacer size="xxl" />

View file

@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const ENGINES_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.engines.title', {
defaultMessage: 'Engines',
});
export const META_ENGINES_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.metaEngines.title',
{ defaultMessage: 'Meta Engines' }
);

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
.engineOverview {
.enginesOverview {
padding: $euiSize;
@include euiBreakpoint('m', 'l', 'xl') {

View file

@ -14,14 +14,14 @@ import { shallow, ReactWrapper } from 'enzyme';
import { mountAsync, mockHttpValues, setMockValues } from '../../../__mocks__';
import { LoadingState, EmptyState } from './components';
import { EngineTable } from './engine_table';
import { EnginesTable } from './engines_table';
import { EngineOverview } from './';
import { EnginesOverview } from './';
describe('EngineOverview', () => {
describe('EnginesOverview', () => {
describe('non-happy-path states', () => {
it('isLoading', () => {
const wrapper = shallow(<EngineOverview />);
const wrapper = shallow(<EnginesOverview />);
expect(wrapper.find(LoadingState)).toHaveLength(1);
});
@ -36,7 +36,7 @@ describe('EngineOverview', () => {
}),
},
});
const wrapper = await mountAsync(<EngineOverview />, { i18n: true });
const wrapper = await mountAsync(<EnginesOverview />, { i18n: true });
expect(wrapper.find(EmptyState)).toHaveLength(1);
});
@ -69,9 +69,9 @@ describe('EngineOverview', () => {
});
it('renders and calls the engines API', async () => {
const wrapper = await mountAsync(<EngineOverview />, { i18n: true });
const wrapper = await mountAsync(<EnginesOverview />, { i18n: true });
expect(wrapper.find(EngineTable)).toHaveLength(1);
expect(wrapper.find(EnginesTable)).toHaveLength(1);
expect(mockApi).toHaveBeenNthCalledWith(1, '/api/app_search/engines', {
query: {
type: 'indexed',
@ -86,9 +86,9 @@ describe('EngineOverview', () => {
hasPlatinumLicense: true,
http: { ...mockHttpValues.http, get: mockApi },
});
const wrapper = await mountAsync(<EngineOverview />, { i18n: true });
const wrapper = await mountAsync(<EnginesOverview />, { i18n: true });
expect(wrapper.find(EngineTable)).toHaveLength(2);
expect(wrapper.find(EnginesTable)).toHaveLength(2);
expect(mockApi).toHaveBeenNthCalledWith(2, '/api/app_search/engines', {
query: {
type: 'meta',
@ -100,10 +100,10 @@ describe('EngineOverview', () => {
describe('pagination', () => {
const getTablePagination = (wrapper: ReactWrapper) =>
wrapper.find(EngineTable).prop('pagination');
wrapper.find(EnginesTable).prop('pagination');
it('passes down page data from the API', async () => {
const wrapper = await mountAsync(<EngineOverview />, { i18n: true });
const wrapper = await mountAsync(<EnginesOverview />, { i18n: true });
const pagination = getTablePagination(wrapper);
expect(pagination.totalEngines).toEqual(100);
@ -111,7 +111,7 @@ describe('EngineOverview', () => {
});
it('re-polls the API on page change', async () => {
const wrapper = await mountAsync(<EngineOverview />, { i18n: true });
const wrapper = await mountAsync(<EnginesOverview />, { i18n: true });
await act(async () => getTablePagination(wrapper).onPaginate(5));
wrapper.update();

View file

@ -13,7 +13,6 @@ import {
EuiTitle,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
@ -23,11 +22,11 @@ import { LicensingLogic } from '../../../shared/licensing';
import { EngineIcon } from './assets/engine_icon';
import { MetaEngineIcon } from './assets/meta_engine_icon';
import { ENGINES_TITLE, META_ENGINES_TITLE } from './constants';
import { EnginesOverviewHeader, LoadingState, EmptyState } from './components';
import { EnginesTable } from './engines_table';
import { EngineOverviewHeader, LoadingState, EmptyState } from './components';
import { EngineTable } from './engine_table';
import './engine_overview.scss';
import './engines_overview.scss';
interface IGetEnginesParams {
type: string;
@ -38,7 +37,7 @@ interface ISetEnginesCallbacks {
setResultsTotal: React.Dispatch<React.SetStateAction<number>>;
}
export const EngineOverview: React.FC = () => {
export const EnginesOverview: React.FC = () => {
const { http } = useValues(HttpLogic);
const { hasPlatinumLicense } = useValues(LicensingLogic);
@ -88,21 +87,18 @@ export const EngineOverview: React.FC = () => {
<SetPageChrome />
<SendTelemetry action="viewed" metric="engines_overview" />
<EngineOverviewHeader />
<EuiPageContent panelPaddingSize="s" className="engineOverview">
<EnginesOverviewHeader />
<EuiPageContent panelPaddingSize="s" className="enginesOverview">
<FlashMessages />
<EuiPageContentHeader>
<EuiTitle size="s">
<h2>
<EngineIcon />
{i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.engines', {
defaultMessage: 'Engines',
})}
<EngineIcon /> {ENGINES_TITLE}
</h2>
</EuiTitle>
</EuiPageContentHeader>
<EuiPageContentBody data-test-subj="appSearchEngines">
<EngineTable
<EnginesTable
data={engines}
pagination={{
totalEngines: enginesTotal,
@ -118,15 +114,12 @@ export const EngineOverview: React.FC = () => {
<EuiPageContentHeader>
<EuiTitle size="s">
<h2>
<MetaEngineIcon />
{i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.metaEngines', {
defaultMessage: 'Meta Engines',
})}
<MetaEngineIcon /> {META_ENGINES_TITLE}
</h2>
</EuiTitle>
</EuiPageContentHeader>
<EuiPageContentBody data-test-subj="appSearchMetaEngines">
<EngineTable
<EnginesTable
data={metaEngines}
pagination={{
totalEngines: metaEnginesTotal,

View file

@ -12,13 +12,13 @@ import React from 'react';
import { EuiBasicTable, EuiPagination, EuiButtonEmpty } from '@elastic/eui';
import { EuiLink } from '../../../shared/react_router_helpers';
import { EngineTable } from './engine_table';
import { EnginesTable } from './engines_table';
describe('EngineTable', () => {
describe('EnginesTable', () => {
const onPaginate = jest.fn(); // onPaginate updates the engines API call upstream
const wrapper = mountWithIntl(
<EngineTable
<EnginesTable
data={[
{
name: 'test-engine',
@ -71,7 +71,10 @@ describe('EngineTable', () => {
it('handles empty data', () => {
const emptyWrapper = mountWithIntl(
<EngineTable data={[]} pagination={{ totalEngines: 0, pageIndex: 0, onPaginate: () => {} }} />
<EnginesTable
data={[]}
pagination={{ totalEngines: 0, pageIndex: 0, onPaginate: () => {} }}
/>
);
const emptyTable = emptyWrapper.find(EuiBasicTable);

View file

@ -16,28 +16,28 @@ import { getEngineRoute } from '../../routes';
import { ENGINES_PAGE_SIZE } from '../../../../../common/constants';
export interface IEngineTableData {
interface IEnginesTableData {
name: string;
created_at: string;
document_count: number;
field_count: number;
}
export interface IEngineTablePagination {
interface IEnginesTablePagination {
totalEngines: number;
pageIndex: number;
onPaginate(pageIndex: number): void;
}
export interface IEngineTableProps {
data: IEngineTableData[];
pagination: IEngineTablePagination;
interface IEnginesTableProps {
data: IEnginesTableData[];
pagination: IEnginesTablePagination;
}
export interface IOnChange {
interface IOnChange {
page: {
index: number;
};
}
export const EngineTable: React.FC<IEngineTableProps> = ({
export const EnginesTable: React.FC<IEnginesTableProps> = ({
data,
pagination: { totalEngines, pageIndex, onPaginate },
}) => {
@ -52,7 +52,7 @@ export const EngineTable: React.FC<IEngineTableProps> = ({
}),
});
const columns: Array<EuiBasicTableColumn<IEngineTableData>> = [
const columns: Array<EuiBasicTableColumn<IEnginesTableData>> = [
{
field: 'name',
name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name', {

View file

@ -0,0 +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;
* you may not use this file except in compliance with the Elastic License.
*/
export { EnginesOverview } from './engines_overview';
export { ENGINES_TITLE, META_ENGINES_TITLE } from './constants';

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const ROLE_MAPPINGS_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.roleMappings.title',
{ defaultMessage: 'Role Mappings' }
);

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { EngineOverview } from './engine_overview';
export { ROLE_MAPPINGS_TITLE } from './constants';

View file

@ -0,0 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const SETTINGS_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.settings.title', {
defaultMessage: 'Settings',
});

View file

@ -5,3 +5,4 @@
*/
export { Settings } from './settings';
export { SETTINGS_TITLE } from './constants';

View file

@ -6,30 +6,21 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiPageHeader, EuiPageHeaderSection, EuiPageContentBody, EuiTitle } from '@elastic/eui';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { FlashMessages } from '../../../shared/flash_messages';
import { SETTINGS_TITLE } from './';
export const Settings: React.FC = () => {
return (
<>
<SetPageChrome
trail={[
i18n.translate('xpack.enterpriseSearch.appSearch.settings.title', {
defaultMessage: 'Settings',
}),
]}
/>
<SetPageChrome trail={[SETTINGS_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>
{i18n.translate('xpack.enterpriseSearch.appSearch.settings.title', {
defaultMessage: 'Settings',
})}
</h1>
<h1>{SETTINGS_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>

View file

@ -16,7 +16,7 @@ import { shallow } from 'enzyme';
import { Layout, SideNav, SideNavLink } from '../shared/layout';
import { SetupGuide } from './components/setup_guide';
import { ErrorConnecting } from './components/error_connecting';
import { EngineOverview } from './components/engine_overview';
import { EnginesOverview } from './components/engines';
import { EngineRouter } from './components/engine';
import { AppSearch, AppSearchUnconfigured, AppSearchConfigured, AppSearchNav } from './';
@ -57,7 +57,7 @@ describe('AppSearchConfigured', () => {
expect(wrapper.find(Layout)).toHaveLength(2);
expect(wrapper.find(Layout).last().prop('readOnlyMode')).toBeFalsy();
expect(wrapper.find(EngineOverview)).toHaveLength(1);
expect(wrapper.find(EnginesOverview)).toHaveLength(1);
expect(wrapper.find(EngineRouter)).toHaveLength(1);
});

View file

@ -8,8 +8,6 @@ import React, { useEffect } from 'react';
import { Route, Redirect, Switch } from 'react-router-dom';
import { useActions, useValues } from 'kea';
import { i18n } from '@kbn/i18n';
import { getAppSearchUrl } from '../shared/enterprise_search_url';
import { KibanaLogic } from '../shared/kibana';
import { HttpLogic } from '../shared/http';
@ -33,9 +31,10 @@ import {
import { SetupGuide } from './components/setup_guide';
import { ErrorConnecting } from './components/error_connecting';
import { NotFound } from '../shared/not_found';
import { EngineOverview } from './components/engine_overview';
import { Settings } from './components/settings';
import { Credentials } from './components/credentials';
import { EnginesOverview, ENGINES_TITLE } from './components/engines';
import { Settings, SETTINGS_TITLE } from './components/settings';
import { Credentials, CREDENTIALS_TITLE } from './components/credentials';
import { ROLE_MAPPINGS_TITLE } from './components/role_mappings';
export const AppSearch: React.FC<IInitialAppData> = (props) => {
const { config } = useValues(KibanaLogic);
@ -82,7 +81,7 @@ export const AppSearchConfigured: React.FC<IInitialAppData> = (props) => {
<Redirect to={ENGINES_PATH} />
</Route>
<Route exact path={ENGINES_PATH}>
<EngineOverview />
<EnginesOverview />
</Route>
<Route exact path={SETTINGS_PATH}>
<Settings />
@ -113,29 +112,15 @@ export const AppSearchNav: React.FC<IAppSearchNavProps> = ({ subNav }) => {
return (
<SideNav product={APP_SEARCH_PLUGIN}>
<SideNavLink to={ENGINES_PATH} subNav={subNav} isRoot>
{i18n.translate('xpack.enterpriseSearch.appSearch.nav.engines', {
defaultMessage: 'Engines',
})}
{ENGINES_TITLE}
</SideNavLink>
{canViewSettings && (
<SideNavLink to={SETTINGS_PATH}>
{i18n.translate('xpack.enterpriseSearch.appSearch.nav.settings', {
defaultMessage: 'Settings',
})}
</SideNavLink>
)}
{canViewSettings && <SideNavLink to={SETTINGS_PATH}>{SETTINGS_TITLE}</SideNavLink>}
{canViewAccountCredentials && (
<SideNavLink to={CREDENTIALS_PATH}>
{i18n.translate('xpack.enterpriseSearch.appSearch.nav.credentials', {
defaultMessage: 'Credentials',
})}
</SideNavLink>
<SideNavLink to={CREDENTIALS_PATH}>{CREDENTIALS_TITLE}</SideNavLink>
)}
{canViewRoleMappings && (
<SideNavLink isExternal to={getAppSearchUrl(ROLE_MAPPINGS_PATH)}>
{i18n.translate('xpack.enterpriseSearch.appSearch.nav.roleMappings', {
defaultMessage: 'Role Mappings',
})}
{ROLE_MAPPINGS_TITLE}
</SideNavLink>
)}
</SideNav>

View file

@ -6930,8 +6930,8 @@
"xpack.enterpriseSearch.appSearch.emptyState.createFirstEngineCta": "エンジンを作成",
"xpack.enterpriseSearch.appSearch.emptyState.description1": "App Searchエンジンは、検索エクスペリエンスのために、ドキュメントを格納します。",
"xpack.enterpriseSearch.appSearch.emptyState.title": "初めてのエンジンの作成",
"xpack.enterpriseSearch.appSearch.enginesOverview.engines": "エンジン",
"xpack.enterpriseSearch.appSearch.enginesOverview.metaEngines": "メタエンジン",
"xpack.enterpriseSearch.appSearch.engines.title": "エンジン",
"xpack.enterpriseSearch.appSearch.metaEngines.title": "メタエンジン",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.action.manage": "管理",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.actions": "アクション",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.createdAt": "作成日時",
@ -6939,10 +6939,9 @@
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.fieldCount": "フィールドカウント",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name": "名前",
"xpack.enterpriseSearch.appSearch.enginesOverview.title": "エンジン概要",
"xpack.enterpriseSearch.appSearch.nav.credentials": "資格情報",
"xpack.enterpriseSearch.appSearch.nav.engines": "エンジン",
"xpack.enterpriseSearch.appSearch.nav.roleMappings": "ロールマッピング",
"xpack.enterpriseSearch.appSearch.nav.settings": "アカウント設定",
"xpack.enterpriseSearch.appSearch.credentials.title": "資格情報",
"xpack.enterpriseSearch.appSearch.roleMappings.title": "ロールマッピング",
"xpack.enterpriseSearch.appSearch.settings.title": "アカウント設定",
"xpack.enterpriseSearch.appSearch.productCardDescription": "Elastic App Searchには、強力な検索を設計し、WebサイトやWeb/モバイルアプリケーションにデプロイするための使いやすいツールがあります。",
"xpack.enterpriseSearch.appSearch.productCta": "App Searchの起動",
"xpack.enterpriseSearch.appSearch.productDescription": "ダッシュボード、分析、APIを活用し、高度なアプリケーション検索をシンプルにします。",

View file

@ -6936,8 +6936,8 @@
"xpack.enterpriseSearch.appSearch.emptyState.createFirstEngineCta": "创建引擎",
"xpack.enterpriseSearch.appSearch.emptyState.description1": "App Search 引擎存储文档以提升您的搜索体验。",
"xpack.enterpriseSearch.appSearch.emptyState.title": "创建您的首个引擎",
"xpack.enterpriseSearch.appSearch.enginesOverview.engines": "引擎",
"xpack.enterpriseSearch.appSearch.enginesOverview.metaEngines": "元引擎",
"xpack.enterpriseSearch.appSearch.engines.title": "引擎",
"xpack.enterpriseSearch.appSearch.metaEngines.title": "元引擎",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.action.manage": "管理",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.actions": "操作",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.createdAt": "创建于",
@ -6945,10 +6945,9 @@
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.fieldCount": "字段计数",
"xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name": "名称",
"xpack.enterpriseSearch.appSearch.enginesOverview.title": "引擎概览",
"xpack.enterpriseSearch.appSearch.nav.credentials": "凭据",
"xpack.enterpriseSearch.appSearch.nav.engines": "引擎",
"xpack.enterpriseSearch.appSearch.nav.roleMappings": "角色映射",
"xpack.enterpriseSearch.appSearch.nav.settings": "帐户设置",
"xpack.enterpriseSearch.appSearch.credentials.title": "凭据",
"xpack.enterpriseSearch.appSearch.roleMappings.title": "角色映射",
"xpack.enterpriseSearch.appSearch.settings.title": "帐户设置",
"xpack.enterpriseSearch.appSearch.productCardDescription": "Elastic App Search 提供用户友好的工具,用于设计强大的搜索功能,并将其部署到您的网站或 Web/移动应用程序。",
"xpack.enterpriseSearch.appSearch.productCta": "启动 App Search",
"xpack.enterpriseSearch.appSearch.productDescription": "利用仪表板、分析和 API 执行高级应用程序搜索简单易行。",