diff --git a/.buildkite/pipelines/hourly.yml b/.buildkite/pipelines/hourly.yml index 78c57ff3bd1285..e5bc841774fde5 100644 --- a/.buildkite/pipelines/hourly.yml +++ b/.buildkite/pipelines/hourly.yml @@ -56,24 +56,44 @@ steps: - command: .buildkite/scripts/steps/functional/oss_accessibility.sh label: 'OSS Accessibility Tests' agents: - queue: ci-group-4d + queue: n2-4-spot depends_on: build timeout_in_minutes: 120 retry: automatic: - - exit_status: '*' + - exit_status: '1' limit: 1 + - exit_status: '-1' + limit: 3 + - exit_status: '130' + limit: 3 + - exit_status: '137' + limit: 3 + - exit_status: '143' + limit: 3 + - exit_status: '255' + limit: 3 - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh label: 'Default Accessibility Tests' agents: - queue: n2-4 + queue: n2-4-spot depends_on: build timeout_in_minutes: 120 retry: automatic: - - exit_status: '*' + - exit_status: '1' limit: 1 + - exit_status: '-1' + limit: 3 + - exit_status: '130' + limit: 3 + - exit_status: '137' + limit: 3 + - exit_status: '143' + limit: 3 + - exit_status: '255' + limit: 3 - command: .buildkite/scripts/steps/functional/oss_firefox.sh label: 'OSS Firefox Tests' @@ -89,13 +109,23 @@ steps: - command: .buildkite/scripts/steps/functional/xpack_firefox.sh label: 'Default Firefox Tests' agents: - queue: n2-4 + queue: n2-4-spot depends_on: build timeout_in_minutes: 120 retry: automatic: - - exit_status: '*' + - exit_status: '1' limit: 1 + - exit_status: '-1' + limit: 3 + - exit_status: '130' + limit: 3 + - exit_status: '137' + limit: 3 + - exit_status: '143' + limit: 3 + - exit_status: '255' + limit: 3 - command: .buildkite/scripts/steps/functional/oss_misc.sh label: 'OSS Misc Functional Tests' @@ -111,13 +141,23 @@ steps: - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh label: 'Saved Object Field Metrics' agents: - queue: n2-4 + queue: n2-4-spot depends_on: build timeout_in_minutes: 120 retry: automatic: - - exit_status: '*' + - exit_status: '1' limit: 1 + - exit_status: '-1' + limit: 3 + - exit_status: '130' + limit: 3 + - exit_status: '137' + limit: 3 + - exit_status: '143' + limit: 3 + - exit_status: '255' + limit: 3 - command: .buildkite/scripts/steps/test/jest.sh label: 'Jest Tests' @@ -138,9 +178,23 @@ steps: - command: .buildkite/scripts/steps/test/api_integration.sh label: 'API Integration Tests' agents: - queue: n2-2 + queue: n2-4-spot timeout_in_minutes: 120 key: api-integration + retry: + automatic: + - exit_status: '1' + limit: 1 + - exit_status: '-1' + limit: 3 + - exit_status: '130' + limit: 3 + - exit_status: '137' + limit: 3 + - exit_status: '143' + limit: 3 + - exit_status: '255' + limit: 3 - command: .buildkite/scripts/steps/lint.sh label: 'Linting' diff --git a/.github/workflows/backport-next.yml b/.github/workflows/backport-next.yml deleted file mode 100644 index 6779bb42472418..00000000000000 --- a/.github/workflows/backport-next.yml +++ /dev/null @@ -1,27 +0,0 @@ -on: - pull_request_target: - branches: - - main - types: - - labeled - - closed - -jobs: - backport: - name: Backport PR - runs-on: ubuntu-latest - if: | - github.event.pull_request.merged == true - && contains(github.event.pull_request.labels.*.name, 'auto-backport-next') - && ( - (github.event.action == 'labeled' && github.event.label.name == 'auto-backport-next') - || (github.event.action == 'closed') - ) - steps: - - name: Backport Action - uses: sqren/backport-github-action@v7.3.1 - with: - github_token: ${{secrets.KIBANAMACHINE_TOKEN}} - - - name: Backport log - run: cat /home/runner/.backport/backport.log diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index d126ea6ec9b388..375854b9c54b71 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -9,6 +9,7 @@ on: jobs: backport: name: Backport PR + runs-on: ubuntu-latest if: | github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'auto-backport') @@ -16,26 +17,11 @@ jobs: (github.event.action == 'labeled' && github.event.label.name == 'auto-backport') || (github.event.action == 'closed') ) - runs-on: ubuntu-latest steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: 'elastic/kibana-github-actions' - ref: main - path: ./actions - - - name: Install Actions - run: npm install --production --prefix ./actions - - - name: Fix Version Label Gaps - uses: ./actions/fix-version-gaps + - name: Backport Action + uses: sqren/backport-github-action@v7.4.0 with: github_token: ${{secrets.KIBANAMACHINE_TOKEN}} - - name: Run Backport - uses: ./actions/backport - with: - github_token: ${{secrets.KIBANAMACHINE_TOKEN}} - commit_user: kibanamachine - commit_email: 42973632+kibanamachine@users.noreply.github.com + - name: Backport log + run: cat ~/.backport/backport.log diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.executioncontext.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.executioncontext.md new file mode 100644 index 00000000000000..be5689ad7b080f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.executioncontext.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreSetup](./kibana-plugin-core-public.coresetup.md) > [executionContext](./kibana-plugin-core-public.coresetup.executioncontext.md) + +## CoreSetup.executionContext property + +[ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) + +Signature: + +```typescript +executionContext: ExecutionContextSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index 9488b8a26b8679..31793ec6f7a581 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -17,6 +17,7 @@ export interface CoreSetup + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreStart](./kibana-plugin-core-public.corestart.md) > [executionContext](./kibana-plugin-core-public.corestart.executioncontext.md) + +## CoreStart.executionContext property + +[ExecutionContextStart](./kibana-plugin-core-public.executioncontextstart.md) + +Signature: + +```typescript +executionContext: ExecutionContextStart; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.corestart.md b/docs/development/core/public/kibana-plugin-core-public.corestart.md index ae67696e12501b..edd80e1adb9f98 100644 --- a/docs/development/core/public/kibana-plugin-core-public.corestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.corestart.md @@ -20,6 +20,7 @@ export interface CoreStart | [chrome](./kibana-plugin-core-public.corestart.chrome.md) | ChromeStart | [ChromeStart](./kibana-plugin-core-public.chromestart.md) | | [deprecations](./kibana-plugin-core-public.corestart.deprecations.md) | DeprecationsServiceStart | [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | | [docLinks](./kibana-plugin-core-public.corestart.doclinks.md) | DocLinksStart | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | +| [executionContext](./kibana-plugin-core-public.corestart.executioncontext.md) | ExecutionContextStart | [ExecutionContextStart](./kibana-plugin-core-public.executioncontextstart.md) | | [fatalErrors](./kibana-plugin-core-public.corestart.fatalerrors.md) | FatalErrorsStart | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | | [http](./kibana-plugin-core-public.corestart.http.md) | HttpStart | [HttpStart](./kibana-plugin-core-public.httpstart.md) | | [i18n](./kibana-plugin-core-public.corestart.i18n.md) | I18nStart | [I18nStart](./kibana-plugin-core-public.i18nstart.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.clear.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.clear.md new file mode 100644 index 00000000000000..94936b94d0710b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.clear.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [clear](./kibana-plugin-core-public.executioncontextsetup.clear.md) + +## ExecutionContextSetup.clear() method + +clears the context + +Signature: + +```typescript +clear(): void; +``` +Returns: + +void + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.context_.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.context_.md new file mode 100644 index 00000000000000..d6c74db6d603e9 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.context_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [context$](./kibana-plugin-core-public.executioncontextsetup.context_.md) + +## ExecutionContextSetup.context$ property + +The current context observable + +Signature: + +```typescript +context$: Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.get.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.get.md new file mode 100644 index 00000000000000..65e9b1218649d2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.get.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [get](./kibana-plugin-core-public.executioncontextsetup.get.md) + +## ExecutionContextSetup.get() method + +Get the current top level context + +Signature: + +```typescript +get(): KibanaExecutionContext; +``` +Returns: + +KibanaExecutionContext + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.getaslabels.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.getaslabels.md new file mode 100644 index 00000000000000..0f0bda4e2913e9 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.getaslabels.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [getAsLabels](./kibana-plugin-core-public.executioncontextsetup.getaslabels.md) + +## ExecutionContextSetup.getAsLabels() method + +returns apm labels + +Signature: + +```typescript +getAsLabels(): Labels; +``` +Returns: + +Labels + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.md new file mode 100644 index 00000000000000..01581d2e80a5c9 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) + +## ExecutionContextSetup interface + +Kibana execution context. Used to provide execution context to Elasticsearch, reporting, performance monitoring, etc. + +Signature: + +```typescript +export interface ExecutionContextSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [context$](./kibana-plugin-core-public.executioncontextsetup.context_.md) | Observable<KibanaExecutionContext> | The current context observable | + +## Methods + +| Method | Description | +| --- | --- | +| [clear()](./kibana-plugin-core-public.executioncontextsetup.clear.md) | clears the context | +| [get()](./kibana-plugin-core-public.executioncontextsetup.get.md) | Get the current top level context | +| [getAsLabels()](./kibana-plugin-core-public.executioncontextsetup.getaslabels.md) | returns apm labels | +| [set(c$)](./kibana-plugin-core-public.executioncontextsetup.set.md) | Set the current top level context | +| [withGlobalContext(context)](./kibana-plugin-core-public.executioncontextsetup.withglobalcontext.md) | merges the current top level context with the specific event context | + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.set.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.set.md new file mode 100644 index 00000000000000..e3dcea78c827ab --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.set.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [set](./kibana-plugin-core-public.executioncontextsetup.set.md) + +## ExecutionContextSetup.set() method + +Set the current top level context + +Signature: + +```typescript +set(c$: KibanaExecutionContext): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| c$ | KibanaExecutionContext | | + +Returns: + +void + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.withglobalcontext.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.withglobalcontext.md new file mode 100644 index 00000000000000..574d0fd989750f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextsetup.withglobalcontext.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) > [withGlobalContext](./kibana-plugin-core-public.executioncontextsetup.withglobalcontext.md) + +## ExecutionContextSetup.withGlobalContext() method + +merges the current top level context with the specific event context + +Signature: + +```typescript +withGlobalContext(context?: KibanaExecutionContext): KibanaExecutionContext; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | KibanaExecutionContext | | + +Returns: + +KibanaExecutionContext + diff --git a/docs/development/core/public/kibana-plugin-core-public.executioncontextstart.md b/docs/development/core/public/kibana-plugin-core-public.executioncontextstart.md new file mode 100644 index 00000000000000..0d210ba5bb1c4d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.executioncontextstart.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ExecutionContextStart](./kibana-plugin-core-public.executioncontextstart.md) + +## ExecutionContextStart type + +See [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md). + +Signature: + +```typescript +export declare type ExecutionContextStart = ExecutionContextSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.kibanaexecutioncontext.md b/docs/development/core/public/kibana-plugin-core-public.kibanaexecutioncontext.md index 6266639b63976d..d8f8a77d84b2f4 100644 --- a/docs/development/core/public/kibana-plugin-core-public.kibanaexecutioncontext.md +++ b/docs/development/core/public/kibana-plugin-core-public.kibanaexecutioncontext.md @@ -10,9 +10,10 @@ Represents a meta-information about a Kibana entity initiating a search request. ```typescript export declare type KibanaExecutionContext = { - readonly type: string; - readonly name: string; - readonly id: string; + readonly type?: string; + readonly name?: string; + readonly page?: string; + readonly id?: string; readonly description?: string; readonly url?: string; child?: KibanaExecutionContext; diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index b51f5ed833fd37..fca697144a8723 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -62,6 +62,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. | | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | +| [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md) | Kibana execution context. Used to provide execution context to Elasticsearch, reporting, performance monitoring, etc. | | [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | | [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-core-public.httphandler.md). | @@ -160,6 +161,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeBreadcrumb](./kibana-plugin-core-public.chromebreadcrumb.md) | | | [ChromeHelpExtensionLinkBase](./kibana-plugin-core-public.chromehelpextensionlinkbase.md) | | | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | +| [ExecutionContextStart](./kibana-plugin-core-public.executioncontextstart.md) | See [ExecutionContextSetup](./kibana-plugin-core-public.executioncontextsetup.md). | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | | [HttpStart](./kibana-plugin-core-public.httpstart.md) | See [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | diff --git a/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.getaslabels.md b/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.getaslabels.md new file mode 100644 index 00000000000000..c8816a3deee4da --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.getaslabels.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ExecutionContextSetup](./kibana-plugin-core-server.executioncontextsetup.md) > [getAsLabels](./kibana-plugin-core-server.executioncontextsetup.getaslabels.md) + +## ExecutionContextSetup.getAsLabels() method + +Signature: + +```typescript +getAsLabels(): apm.Labels; +``` +Returns: + +apm.Labels + diff --git a/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.md b/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.md index 24591648ad953b..7fdc4d1ec1d57c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.executioncontextsetup.md @@ -15,5 +15,6 @@ export interface ExecutionContextSetup | Method | Description | | --- | --- | +| [getAsLabels()](./kibana-plugin-core-server.executioncontextsetup.getaslabels.md) | | | [withContext(context, fn)](./kibana-plugin-core-server.executioncontextsetup.withcontext.md) | Keeps track of execution context while the passed function is executed. Data are carried over all async operations spawned by the passed function. The nested calls stack the registered context on top of each other. | diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanaexecutioncontext.md b/docs/development/core/server/kibana-plugin-core-server.kibanaexecutioncontext.md index 0d65a3662da6f3..792af8f693869f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanaexecutioncontext.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanaexecutioncontext.md @@ -10,9 +10,10 @@ Represents a meta-information about a Kibana entity initiating a search request. ```typescript export declare type KibanaExecutionContext = { - readonly type: string; - readonly name: string; - readonly id: string; + readonly type?: string; + readonly name?: string; + readonly page?: string; + readonly id?: string; readonly description?: string; readonly url?: string; child?: KibanaExecutionContext; diff --git a/docs/user/dashboard/tsvb.asciidoc b/docs/user/dashboard/tsvb.asciidoc index a097e34b20911f..56e3606c18b72f 100644 --- a/docs/user/dashboard/tsvb.asciidoc +++ b/docs/user/dashboard/tsvb.asciidoc @@ -276,20 +276,4 @@ For other types of month over month calculations, use <> o Calculating the duration between the start and end of an event is unsupported in *TSVB* because *TSVB* requires correlation between different time periods. *TSVB* requires that the duration is pre-calculated. -==== - -[discrete] -[group-on-multiple-fields] -.*How do I group on multiple fields?* -[%collapsible] -==== - -To group with multiple fields, create runtime fields in the {data-source} you are visualizing. - -. Create a runtime field. Refer to <> for more information. -+ -[role="screenshot"] -image::images/tsvb_group_by_multiple_fields.png[Group by multiple fields] - -. Create a *TSVB* visualization and group by this field. ==== \ No newline at end of file diff --git a/docs/user/security/authentication/index.asciidoc b/docs/user/security/authentication/index.asciidoc index 2f2b2793897996..446de62326f8ed 100644 --- a/docs/user/security/authentication/index.asciidoc +++ b/docs/user/security/authentication/index.asciidoc @@ -5,7 +5,7 @@ Authentication ++++ :keywords: administrator, concept, security, authentication -:description: A list of the supported authentication mechanisms in {kib}. +:description: A list of the supported authentication mechanisms in {kib}. {kib} supports the following authentication mechanisms: @@ -483,4 +483,4 @@ To make this iframe leverage anonymous access automatically, you will need to mo NOTE: `auth_provider_hint` query string parameter goes *before* the hash URL fragment. -For more information on how to embed, refer to <>. +For more information, refer to <>. diff --git a/package.json b/package.json index fdb358c25fb83c..a2022e05c86cb8 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace", "@elastic/charts": "43.1.1", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", - "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.1.0-canary.3", + "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.2.0-canary.1", "@elastic/ems-client": "8.0.0", "@elastic/eui": "48.1.1", "@elastic/filesaver": "1.1.2", @@ -737,7 +737,7 @@ "callsites": "^3.1.0", "chai": "3.5.0", "chance": "1.0.18", - "chromedriver": "^98.0.0", + "chromedriver": "^98.0.1", "clean-webpack-plugin": "^3.0.0", "cmd-shim": "^2.1.0", "compression-webpack-plugin": "^4.0.0", diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts index 84e9159dfcd415..e9b5ab04a73905 100644 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts @@ -62,7 +62,10 @@ export class ToolingLog { * @param delta the number of spaces to increase/decrease the indentation * @param block a function to run and reset any indentation changes after */ - public indent(delta = 0, block?: () => Promise) { + public indent(delta: number): undefined; + public indent(delta: number, block: () => Promise): Promise; + public indent(delta: number, block: () => T): T; + public indent(delta = 0, block?: () => T | Promise) { const originalWidth = this.indentWidth$.getValue(); this.indentWidth$.next(Math.max(originalWidth + delta, 0)); if (!block) { diff --git a/packages/kbn-es/src/cli_commands/build_snapshots.js b/packages/kbn-es/src/cli_commands/build_snapshots.js index d6ea76faf2cf96..070f11b8b5f84d 100644 --- a/packages/kbn-es/src/cli_commands/build_snapshots.js +++ b/packages/kbn-es/src/cli_commands/build_snapshots.js @@ -42,32 +42,31 @@ exports.run = async (defaults = {}) => { for (const license of ['oss', 'trial']) { for (const platform of ['darwin', 'win32', 'linux']) { log.info('Building', platform, license === 'trial' ? 'default' : 'oss', 'snapshot'); - log.indent(4); + await log.indent(4, async () => { + const snapshotPath = await buildSnapshot({ + license, + sourcePath: options.sourcePath, + log, + platform, + }); - const snapshotPath = await buildSnapshot({ - license, - sourcePath: options.sourcePath, - log, - platform, - }); - - const filename = basename(snapshotPath); - const outputPath = resolve(outputDir, filename); - const hash = createHash('sha512'); - await pipelineAsync( - Fs.createReadStream(snapshotPath), - new Transform({ - transform(chunk, _, cb) { - hash.update(chunk); - cb(undefined, chunk); - }, - }), - Fs.createWriteStream(outputPath) - ); + const filename = basename(snapshotPath); + const outputPath = resolve(outputDir, filename); + const hash = createHash('sha512'); + await pipelineAsync( + Fs.createReadStream(snapshotPath), + new Transform({ + transform(chunk, _, cb) { + hash.update(chunk); + cb(undefined, chunk); + }, + }), + Fs.createWriteStream(outputPath) + ); - Fs.writeFileSync(`${outputPath}.sha512`, `${hash.digest('hex')} ${filename}`); - log.success('snapshot and shasum written to', outputPath); - log.indent(-4); + Fs.writeFileSync(`${outputPath}.sha512`, `${hash.digest('hex')} ${filename}`); + log.success('snapshot and shasum written to', outputPath); + }); } } }; diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 22ff9ae3c0cde3..3dd6d79fcb14ec 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -59,13 +59,10 @@ exports.Cluster = class Cluster { */ async installSource(options = {}) { this._log.info(chalk.bold('Installing from source')); - this._log.indent(4); - - const { installPath } = await installSource({ log: this._log, ...options }); - - this._log.indent(-4); - - return { installPath }; + return await this._log.indent(4, async () => { + const { installPath } = await installSource({ log: this._log, ...options }); + return { installPath }; + }); } /** @@ -78,16 +75,14 @@ exports.Cluster = class Cluster { */ async downloadSnapshot(options = {}) { this._log.info(chalk.bold('Downloading snapshot')); - this._log.indent(4); + return await this._log.indent(4, async () => { + const { installPath } = await downloadSnapshot({ + log: this._log, + ...options, + }); - const { installPath } = await downloadSnapshot({ - log: this._log, - ...options, + return { installPath }; }); - - this._log.indent(-4); - - return { installPath }; } /** @@ -100,16 +95,14 @@ exports.Cluster = class Cluster { */ async installSnapshot(options = {}) { this._log.info(chalk.bold('Installing from snapshot')); - this._log.indent(4); + return await this._log.indent(4, async () => { + const { installPath } = await installSnapshot({ + log: this._log, + ...options, + }); - const { installPath } = await installSnapshot({ - log: this._log, - ...options, + return { installPath }; }); - - this._log.indent(-4); - - return { installPath }; } /** @@ -122,16 +115,14 @@ exports.Cluster = class Cluster { */ async installArchive(path, options = {}) { this._log.info(chalk.bold('Installing from an archive')); - this._log.indent(4); + return await this._log.indent(4, async () => { + const { installPath } = await installArchive(path, { + log: this._log, + ...options, + }); - const { installPath } = await installArchive(path, { - log: this._log, - ...options, + return { installPath }; }); - - this._log.indent(-4); - - return { installPath }; } /** @@ -144,21 +135,19 @@ exports.Cluster = class Cluster { */ async extractDataDirectory(installPath, archivePath, extractDirName = 'data') { this._log.info(chalk.bold(`Extracting data directory`)); - this._log.indent(4); - - // stripComponents=1 excludes the root directory as that is how our archives are - // structured. This works in our favor as we can explicitly extract into the data dir - const extractPath = path.resolve(installPath, extractDirName); - this._log.info(`Data archive: ${archivePath}`); - this._log.info(`Extract path: ${extractPath}`); - - await extract({ - archivePath, - targetDir: extractPath, - stripComponents: 1, + await this._log.indent(4, async () => { + // stripComponents=1 excludes the root directory as that is how our archives are + // structured. This works in our favor as we can explicitly extract into the data dir + const extractPath = path.resolve(installPath, extractDirName); + this._log.info(`Data archive: ${archivePath}`); + this._log.info(`Extract path: ${extractPath}`); + + await extract({ + archivePath, + targetDir: extractPath, + stripComponents: 1, + }); }); - - this._log.indent(-4); } /** @@ -169,24 +158,27 @@ exports.Cluster = class Cluster { * @returns {Promise} */ async start(installPath, options = {}) { - this._exec(installPath, options); - - await Promise.race([ - // wait for native realm to be setup and es to be started - Promise.all([ - first(this._process.stdout, (data) => { - if (/started/.test(data)) { - return true; - } - }), - this._setupPromise, - ]), + // _exec indents and we wait for our own end condition, so reset the indent level to it's current state after we're done waiting + await this._log.indent(0, async () => { + this._exec(installPath, options); + + await Promise.race([ + // wait for native realm to be setup and es to be started + Promise.all([ + first(this._process.stdout, (data) => { + if (/started/.test(data)) { + return true; + } + }), + this._setupPromise, + ]), - // await the outcome of the process in case it exits before starting - this._outcome.then(() => { - throw createCliError('ES exited without starting'); - }), - ]); + // await the outcome of the process in case it exits before starting + this._outcome.then(() => { + throw createCliError('ES exited without starting'); + }), + ]); + }); } /** @@ -197,16 +189,19 @@ exports.Cluster = class Cluster { * @returns {Promise} */ async run(installPath, options = {}) { - this._exec(installPath, options); + // _exec indents and we wait for our own end condition, so reset the indent level to it's current state after we're done waiting + await this._log.indent(0, async () => { + this._exec(installPath, options); + + // log native realm setup errors so they aren't uncaught + this._setupPromise.catch((error) => { + this._log.error(error); + this.stop(); + }); - // log native realm setup errors so they aren't uncaught - this._setupPromise.catch((error) => { - this._log.error(error); - this.stop(); + // await the final outcome of the process + await this._outcome; }); - - // await the final outcome of the process - await this._outcome; } /** diff --git a/packages/kbn-optimizer/src/log_optimizer_state.ts b/packages/kbn-optimizer/src/log_optimizer_state.ts index 517e3bbfa51331..060f05a445eb59 100644 --- a/packages/kbn-optimizer/src/log_optimizer_state.ts +++ b/packages/kbn-optimizer/src/log_optimizer_state.ts @@ -95,16 +95,16 @@ export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) { if (state.phase === 'issue') { log.error(`webpack compile errors`); - log.indent(4); - for (const b of state.compilerStates) { - if (b.type === 'compiler issue') { - log.error(`[${b.bundleId}] build`); - log.indent(4); - log.error(b.failure); - log.indent(-4); + log.indent(4, () => { + for (const b of state.compilerStates) { + if (b.type === 'compiler issue') { + log.error(`[${b.bundleId}] build`); + log.indent(4, () => { + log.error(b.failure); + }); + } } - } - log.indent(-4); + }); return; } diff --git a/packages/kbn-plugin-helpers/src/tasks/optimize.ts b/packages/kbn-plugin-helpers/src/tasks/optimize.ts index c0f984eb03fcfb..ee05fa3d3354c2 100644 --- a/packages/kbn-plugin-helpers/src/tasks/optimize.ts +++ b/packages/kbn-plugin-helpers/src/tasks/optimize.ts @@ -23,26 +23,25 @@ export async function optimize({ log, plugin, sourceDir, buildDir }: BuildContex } log.info('running @kbn/optimizer'); - log.indent(2); - - // build bundles into target - const config = OptimizerConfig.create({ - repoRoot: REPO_ROOT, - pluginPaths: [sourceDir], - cache: false, - dist: true, - filter: [plugin.manifest.id], + await log.indent(2, async () => { + // build bundles into target + const config = OptimizerConfig.create({ + repoRoot: REPO_ROOT, + pluginPaths: [sourceDir], + cache: false, + dist: true, + filter: [plugin.manifest.id], + }); + + const target = Path.resolve(sourceDir, 'target'); + + await runOptimizer(config).pipe(logOptimizerState(log, config)).toPromise(); + + // clean up unnecessary files + Fs.unlinkSync(Path.resolve(target, 'public/metrics.json')); + Fs.unlinkSync(Path.resolve(target, 'public/.kbn-optimizer-cache')); + + // move target into buildDir + await asyncRename(target, Path.resolve(buildDir, 'target')); }); - - const target = Path.resolve(sourceDir, 'target'); - - await runOptimizer(config).pipe(logOptimizerState(log, config)).toPromise(); - - // clean up unnecessary files - Fs.unlinkSync(Path.resolve(target, 'public/metrics.json')); - Fs.unlinkSync(Path.resolve(target, 'public/.kbn-optimizer-cache')); - - // move target into buildDir - await asyncRename(target, Path.resolve(buildDir, 'target')); - log.indent(-2); } diff --git a/packages/kbn-test/src/functional_test_runner/fake_mocha_types.ts b/packages/kbn-test/src/functional_test_runner/fake_mocha_types.ts index dec381fb04b565..96ebcd79c4e436 100644 --- a/packages/kbn-test/src/functional_test_runner/fake_mocha_types.ts +++ b/packages/kbn-test/src/functional_test_runner/fake_mocha_types.ts @@ -31,6 +31,7 @@ export interface Test { file?: string; parent?: Suite; isPassed: () => boolean; + pending?: boolean; } export interface Runner extends EventEmitter { diff --git a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts index 53ec36dfbe55c8..9f21d8bd595b5d 100644 --- a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts +++ b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import Path from 'path'; +import { writeFileSync, mkdirSync } from 'fs'; +import Path, { dirname } from 'path'; import { ToolingLog } from '@kbn/dev-utils'; import { REPO_ROOT } from '@kbn/utils'; @@ -98,6 +99,15 @@ export class FunctionalTestRunner { reporterOptions ); + // there's a bug in mocha's dry run, see https://github.com/mochajs/mocha/issues/4838 + // until we can update to a mocha version where this is fixed, we won't actually + // execute the mocha dry run but simulate it by reading the suites and tests of + // the mocha object and writing a report file with similar structure to the json report + // (just leave out some execution details like timing, retry and erros) + if (config.get('mochaOpts.dryRun')) { + return this.simulateMochaDryRun(mocha); + } + await this.lifecycle.beforeTests.trigger(mocha.suite); this.log.info('Starting tests'); @@ -244,4 +254,62 @@ export class FunctionalTestRunner { this.closed = true; await this.lifecycle.cleanup.trigger(); } + + simulateMochaDryRun(mocha: any) { + interface TestEntry { + file: string; + title: string; + fullTitle: string; + } + + const getFullTitle = (node: Test | Suite): string => { + const parentTitle = node.parent && getFullTitle(node.parent); + return parentTitle ? `${parentTitle} ${node.title}` : node.title; + }; + + let suiteCount = 0; + const passes: TestEntry[] = []; + const pending: TestEntry[] = []; + + const collectTests = (suite: Suite) => { + for (const subSuite of suite.suites) { + suiteCount++; + for (const test of subSuite.tests) { + const testEntry = { + title: test.title, + fullTitle: getFullTitle(test), + file: test.file || '', + }; + if (test.pending) { + pending.push(testEntry); + } else { + passes.push(testEntry); + } + } + collectTests(subSuite); + } + }; + + collectTests(mocha.suite); + + const reportData = { + stats: { + suites: suiteCount, + tests: passes.length + pending.length, + passes: passes.length, + pending: pending.length, + failures: 0, + }, + tests: [...passes, ...pending], + passes, + pending, + failures: [], + }; + + const reportPath = mocha.options.reporterOptions.output; + mkdirSync(dirname(reportPath), { recursive: true }); + writeFileSync(reportPath, JSON.stringify(reportData, null, 2), 'utf8'); + + return 0; + } } diff --git a/src/core/public/apm_system.test.ts b/src/core/public/apm_system.test.ts index 842d5de7e5afcb..0a3a1dee63e57e 100644 --- a/src/core/public/apm_system.test.ts +++ b/src/core/public/apm_system.test.ts @@ -13,6 +13,7 @@ import type { Transaction } from '@elastic/apm-rum'; import { ApmSystem } from './apm_system'; import { Subject } from 'rxjs'; import { InternalApplicationStart } from './application/types'; +import { executionContextServiceMock } from './execution_context/execution_context_service.mock'; const initMock = init as jest.Mocked; const apmMock = apm as DeeplyMockedKeys; @@ -96,6 +97,7 @@ describe('ApmSystem', () => { application: { currentAppId$, } as any as InternalApplicationStart, + executionContext: executionContextServiceMock.createInternalStartContract(), }); expect(mark).toHaveBeenCalledWith('apm-start'); @@ -118,6 +120,7 @@ describe('ApmSystem', () => { application: { currentAppId$, } as any as InternalApplicationStart, + executionContext: executionContextServiceMock.createInternalStartContract(), }); currentAppId$.next('myapp'); @@ -145,6 +148,7 @@ describe('ApmSystem', () => { application: { currentAppId$, } as any as InternalApplicationStart, + executionContext: executionContextServiceMock.createInternalStartContract(), }); currentAppId$.next('myapp'); diff --git a/src/core/public/apm_system.ts b/src/core/public/apm_system.ts index 2231f394381f04..4e116c0a0182dd 100644 --- a/src/core/public/apm_system.ts +++ b/src/core/public/apm_system.ts @@ -10,6 +10,7 @@ import type { ApmBase, AgentConfigOptions, Transaction } from '@elastic/apm-rum' import { modifyUrl } from '@kbn/std'; import { CachedResourceObserver } from './apm_resource_counter'; import type { InternalApplicationStart } from './application'; +import { ExecutionContextStart } from './execution_context'; /** "GET protocol://hostname:port/pathname" */ const HTTP_REQUEST_TRANSACTION_NAME_REGEX = @@ -27,6 +28,7 @@ interface ApmConfig extends AgentConfigOptions { interface StartDeps { application: InternalApplicationStart; + executionContext: ExecutionContextStart; } export class ApmSystem { @@ -34,6 +36,7 @@ export class ApmSystem { private pageLoadTransaction?: Transaction; private resourceObserver: CachedResourceObserver; private apm?: ApmBase; + /** * `apmConfig` would be populated with relevant APM RUM agent * configuration if server is started with elastic.apm.* config. @@ -64,6 +67,15 @@ export class ApmSystem { this.markPageLoadStart(); + start.executionContext.context$.subscribe((c) => { + // We're using labels because we want the context to be indexed + // https://www.elastic.co/guide/en/apm/get-started/current/metadata.html + const apmContext = start.executionContext.getAsLabels(); + this.apm?.addLabels(apmContext); + }); + + // TODO: Start a new transaction every page change instead of every app change. + /** * Register listeners for navigation changes and capture them as * route-change transactions after Kibana app is bootstrapped diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 3d3331d54792bb..1aa01c13dd3751 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -31,6 +31,7 @@ import { DeprecationsService } from './deprecations'; import { ThemeService } from './theme'; import { CoreApp } from './core_app'; import type { InternalApplicationSetup, InternalApplicationStart } from './application/types'; +import { ExecutionContextService } from './execution_context'; interface Params { rootDomElement: HTMLElement; @@ -87,6 +88,7 @@ export class CoreSystem { private readonly theme: ThemeService; private readonly rootDomElement: HTMLElement; private readonly coreContext: CoreContext; + private readonly executionContext: ExecutionContextService; private fatalErrorsSetup: FatalErrorsSetup | null = null; constructor(params: Params) { @@ -121,6 +123,7 @@ export class CoreSystem { this.application = new ApplicationService(); this.integrations = new IntegrationsService(); this.deprecations = new DeprecationsService(); + this.executionContext = new ExecutionContextService(); this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); this.coreApp = new CoreApp(this.coreContext); @@ -137,7 +140,13 @@ export class CoreSystem { }); await this.integrations.setup(); this.docLinks.setup(); - const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); + + const executionContext = this.executionContext.setup(); + const http = this.http.setup({ + injectedMetadata, + fatalErrors: this.fatalErrorsSetup, + executionContext, + }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); const theme = this.theme.setup({ injectedMetadata }); @@ -153,6 +162,7 @@ export class CoreSystem { notifications, theme, uiSettings, + executionContext, }; // Services that do not expose contracts at setup @@ -201,6 +211,11 @@ export class CoreSystem { targetDomElement: notificationsTargetDomElement, }); const application = await this.application.start({ http, theme, overlays }); + + const executionContext = this.executionContext.start({ + curApp$: application.currentAppId$, + }); + const chrome = await this.chrome.start({ application, docLinks, @@ -216,6 +231,7 @@ export class CoreSystem { application, chrome, docLinks, + executionContext, http, theme, savedObjects, @@ -248,6 +264,7 @@ export class CoreSystem { return { application, + executionContext, }; } catch (error) { if (this.fatalErrorsSetup) { diff --git a/src/core/public/execution_context/execution_context_service.mock.ts b/src/core/public/execution_context/execution_context_service.mock.ts new file mode 100644 index 00000000000000..3941aa333cfa2a --- /dev/null +++ b/src/core/public/execution_context/execution_context_service.mock.ts @@ -0,0 +1,35 @@ +/* + * 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 { PublicMethodsOf } from '@kbn/utility-types'; +import { BehaviorSubject } from 'rxjs'; + +import { ExecutionContextService, ExecutionContextSetup } from './execution_context_service'; + +const createContractMock = (): jest.Mocked => ({ + context$: new BehaviorSubject({}), + clear: jest.fn(), + set: jest.fn(), + get: jest.fn(), + getAsLabels: jest.fn(), + withGlobalContext: jest.fn(), +}); + +const createMock = (): jest.Mocked> => ({ + setup: jest.fn().mockReturnValue(createContractMock()), + start: jest.fn().mockReturnValue(createContractMock()), + stop: jest.fn(), +}); + +export const executionContextServiceMock = { + create: createMock, + createSetupContract: createContractMock, + createStartContract: createContractMock, + createInternalSetupContract: createContractMock, + createInternalStartContract: createContractMock, +}; diff --git a/src/core/public/execution_context/execution_context_service.ts b/src/core/public/execution_context/execution_context_service.ts new file mode 100644 index 00000000000000..bf13a7351f9b5f --- /dev/null +++ b/src/core/public/execution_context/execution_context_service.ts @@ -0,0 +1,134 @@ +/* + * 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 { isEqual, isUndefined, omitBy } from 'lodash'; +import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { CoreService, KibanaExecutionContext } from '../../types'; + +// Should be exported from elastic/apm-rum +export type LabelValue = string | number | boolean; + +export interface Labels { + [key: string]: LabelValue; +} + +/** + * Kibana execution context. + * Used to provide execution context to Elasticsearch, reporting, performance monitoring, etc. + * @public + **/ +export interface ExecutionContextSetup { + /** + * The current context observable + **/ + context$: Observable; + /** + * Set the current top level context + **/ + set(c$: KibanaExecutionContext): void; + /** + * Get the current top level context + **/ + get(): KibanaExecutionContext; + /** + * clears the context + **/ + clear(): void; + /** + * returns apm labels + **/ + getAsLabels(): Labels; + /** + * merges the current top level context with the specific event context + **/ + withGlobalContext(context?: KibanaExecutionContext): KibanaExecutionContext; +} + +/** + * See {@link ExecutionContextSetup}. + * @public + */ +export type ExecutionContextStart = ExecutionContextSetup; + +export interface StartDeps { + curApp$: Observable; +} + +/** @internal */ +export class ExecutionContextService + implements CoreService +{ + private context$: BehaviorSubject = new BehaviorSubject({}); + private appId?: string; + private subscription: Subscription = new Subscription(); + private contract?: ExecutionContextSetup; + + public setup() { + this.contract = { + context$: this.context$.asObservable(), + clear: () => { + this.context$.next({}); + }, + set: (c: KibanaExecutionContext) => { + const newVal = { + ...this.context$.value, + ...c, + }; + if (!isEqual(newVal, this.context$.value)) { + this.context$.next(newVal); + } + }, + get: () => { + return this.mergeContext(); + }, + getAsLabels: () => { + return this.removeUndefined({ + name: this.appId, + id: this.context$.value?.id, + page: this.context$.value?.page, + }) as Labels; + }, + withGlobalContext: (context: KibanaExecutionContext) => { + return this.mergeContext(context); + }, + }; + + return this.contract; + } + + public start({ curApp$ }: StartDeps) { + const start = this.contract!; + + // Track app id changes and clear context on app change + this.subscription.add( + curApp$.subscribe((appId) => { + this.appId = appId; + start.clear(); + }) + ); + + return start; + } + + public stop() { + this.subscription.unsubscribe(); + } + + private removeUndefined(context: KibanaExecutionContext = {}) { + return omitBy(context, isUndefined); + } + + private mergeContext(context: KibanaExecutionContext = {}): KibanaExecutionContext { + return { + name: this.appId, + url: window.location.pathname, + ...this.context$.value, + ...context, + }; + } +} diff --git a/src/core/public/execution_context/index.ts b/src/core/public/execution_context/index.ts index b15a967ac714aa..f160b0ecea67b5 100644 --- a/src/core/public/execution_context/index.ts +++ b/src/core/public/execution_context/index.ts @@ -8,3 +8,5 @@ export type { KibanaExecutionContext } from '../../types'; export { ExecutionContextContainer } from './execution_context_container'; +export { ExecutionContextService } from './execution_context_service'; +export type { ExecutionContextSetup, ExecutionContextStart } from './execution_context_service'; diff --git a/src/core/public/http/fetch.test.ts b/src/core/public/http/fetch.test.ts index e897d69057e029..0691e2443c17f5 100644 --- a/src/core/public/http/fetch.test.ts +++ b/src/core/public/http/fetch.test.ts @@ -15,6 +15,7 @@ import { first } from 'rxjs/operators'; import { Fetch } from './fetch'; import { BasePath } from './base_path'; import { HttpResponse, HttpFetchOptionsWithPath } from './types'; +import { executionContextServiceMock } from '../execution_context/execution_context_service.mock'; function delay(duration: number) { return new Promise((r) => setTimeout(r, duration)); @@ -23,9 +24,11 @@ function delay(duration: number) { const BASE_PATH = 'http://localhost/myBase'; describe('Fetch', () => { + const executionContextMock = executionContextServiceMock.createSetupContract(); const fetchInstance = new Fetch({ basePath: new BasePath(BASE_PATH), kibanaVersion: 'VERSION', + executionContext: executionContextMock, }); afterEach(() => { fetchMock.restore(); @@ -230,13 +233,15 @@ describe('Fetch', () => { it('should inject context headers if provided', async () => { fetchMock.get('*', {}); + const context = { + type: 'test-type', + name: 'test-name', + description: 'test-description', + id: '42', + }; + executionContextMock.withGlobalContext.mockReturnValue(context); await fetchInstance.fetch('/my/path', { - context: { - type: 'test-type', - name: 'test-name', - description: 'test-description', - id: '42', - }, + context, }); expect(fetchMock.lastOptions()!.headers).toMatchObject({ @@ -245,6 +250,29 @@ describe('Fetch', () => { }); }); + it('should include top level context context headers if provided', async () => { + fetchMock.get('*', {}); + + const context = { + type: 'test-type', + name: 'test-name', + description: 'test-description', + id: '42', + }; + executionContextMock.withGlobalContext.mockReturnValue({ + ...context, + name: 'banana', + }); + await fetchInstance.fetch('/my/path', { + context, + }); + + expect(fetchMock.lastOptions()!.headers).toMatchObject({ + 'x-kbn-context': + '%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22banana%22%2C%22description%22%3A%22test-description%22%2C%22id%22%3A%2242%22%7D', + }); + }); + it('should return response', async () => { fetchMock.get('*', { foo: 'bar' }); const json = await fetchInstance.fetch('/my/path'); diff --git a/src/core/public/http/fetch.ts b/src/core/public/http/fetch.ts index 4ee81f4b47aa0c..9a333161e1b7a5 100644 --- a/src/core/public/http/fetch.ts +++ b/src/core/public/http/fetch.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { omitBy } from 'lodash'; +import { isEmpty, omitBy } from 'lodash'; import { format } from 'url'; import { BehaviorSubject } from 'rxjs'; @@ -22,11 +22,12 @@ import { HttpFetchError } from './http_fetch_error'; import { HttpInterceptController } from './http_intercept_controller'; import { interceptRequest, interceptResponse } from './intercept'; import { HttpInterceptHaltError } from './http_intercept_halt_error'; -import { ExecutionContextContainer } from '../execution_context'; +import { ExecutionContextContainer, ExecutionContextSetup } from '../execution_context'; interface Params { basePath: IBasePath; kibanaVersion: string; + executionContext: ExecutionContextSetup; } const JSON_CONTENT = /^(application\/(json|x-javascript)|text\/(x-)?javascript|x-json)(;.*)?$/; @@ -107,6 +108,7 @@ export class Fetch { }; private createRequest(options: HttpFetchOptionsWithPath): Request { + const context = this.params.executionContext.withGlobalContext(options.context); // Merge and destructure options out that are not applicable to the Fetch API. const { query, @@ -125,7 +127,7 @@ export class Fetch { 'Content-Type': 'application/json', ...options.headers, 'kbn-version': this.params.kibanaVersion, - ...(options.context ? new ExecutionContextContainer(options.context).toHeader() : {}), + ...(!isEmpty(context) ? new ExecutionContextContainer(context).toHeader() : {}), }), }; diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts index 2b41991904d974..698fa876433d41 100644 --- a/src/core/public/http/http_service.test.ts +++ b/src/core/public/http/http_service.test.ts @@ -14,6 +14,7 @@ import { fatalErrorsServiceMock } from '../fatal_errors/fatal_errors_service.moc import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { HttpService } from './http_service'; import { Observable } from 'rxjs'; +import { executionContextServiceMock } from '../execution_context/execution_context_service.mock'; describe('interceptors', () => { afterEach(() => fetchMock.restore()); @@ -22,9 +23,10 @@ describe('interceptors', () => { fetchMock.get('*', {}); const injectedMetadata = injectedMetadataServiceMock.createSetupContract(); const fatalErrors = fatalErrorsServiceMock.createSetupContract(); + const executionContext = executionContextServiceMock.createSetupContract(); const httpService = new HttpService(); - const setup = httpService.setup({ fatalErrors, injectedMetadata }); + const setup = httpService.setup({ fatalErrors, injectedMetadata, executionContext }); const setupInterceptor = jest.fn(); setup.intercept({ request: setupInterceptor }); @@ -47,7 +49,8 @@ describe('#setup()', () => { const injectedMetadata = injectedMetadataServiceMock.createSetupContract(); const fatalErrors = fatalErrorsServiceMock.createSetupContract(); const httpService = new HttpService(); - httpService.setup({ fatalErrors, injectedMetadata }); + const executionContext = executionContextServiceMock.createSetupContract(); + httpService.setup({ fatalErrors, injectedMetadata, executionContext }); const loadingServiceSetup = loadingServiceMock.setup.mock.results[0].value; // We don't verify that this Observable comes from Fetch#getLoadingCount$() to avoid complex mocking expect(loadingServiceSetup.addLoadingCountSource).toHaveBeenCalledWith(expect.any(Observable)); @@ -59,7 +62,8 @@ describe('#stop()', () => { const injectedMetadata = injectedMetadataServiceMock.createSetupContract(); const fatalErrors = fatalErrorsServiceMock.createSetupContract(); const httpService = new HttpService(); - httpService.setup({ fatalErrors, injectedMetadata }); + const executionContext = executionContextServiceMock.createSetupContract(); + httpService.setup({ fatalErrors, injectedMetadata, executionContext }); httpService.start(); httpService.stop(); expect(loadingServiceMock.stop).toHaveBeenCalled(); diff --git a/src/core/public/http/http_service.ts b/src/core/public/http/http_service.ts index a9719cfce67aff..390130da4e07dd 100644 --- a/src/core/public/http/http_service.ts +++ b/src/core/public/http/http_service.ts @@ -15,10 +15,12 @@ import { LoadingCountService } from './loading_count_service'; import { Fetch } from './fetch'; import { CoreService } from '../../types'; import { ExternalUrlService } from './external_url_service'; +import { ExecutionContextSetup } from '../execution_context'; interface HttpDeps { injectedMetadata: InjectedMetadataSetup; fatalErrors: FatalErrorsSetup; + executionContext: ExecutionContextSetup; } /** @internal */ @@ -27,14 +29,15 @@ export class HttpService implements CoreService { private readonly loadingCount = new LoadingCountService(); private service?: HttpSetup; - public setup({ injectedMetadata, fatalErrors }: HttpDeps): HttpSetup { + public setup({ injectedMetadata, fatalErrors, executionContext }: HttpDeps): HttpSetup { const kibanaVersion = injectedMetadata.getKibanaVersion(); const basePath = new BasePath( injectedMetadata.getBasePath(), injectedMetadata.getServerBasePath(), injectedMetadata.getPublicBaseUrl() ); - const fetchService = new Fetch({ basePath, kibanaVersion }); + + const fetchService = new Fetch({ basePath, kibanaVersion, executionContext }); const loadingCount = this.loadingCount.setup({ fatalErrors }); loadingCount.addLoadingCountSource(fetchService.getRequestCount$()); diff --git a/src/core/public/index.ts b/src/core/public/index.ts index ded7db9c6f892d..50d8bf304ddf8f 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -65,6 +65,7 @@ import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; import { DeprecationsServiceStart } from './deprecations'; import type { ThemeServiceSetup, ThemeServiceStart } from './theme'; +import { ExecutionContextSetup, ExecutionContextStart } from './execution_context'; export type { PackageInfo, @@ -194,7 +195,11 @@ export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './type export { URL_MAX_LENGTH } from './core_app'; -export type { KibanaExecutionContext } from './execution_context'; +export type { + KibanaExecutionContext, + ExecutionContextSetup, + ExecutionContextStart, +} from './execution_context'; /** * Core services exposed to the `Plugin` setup lifecycle @@ -221,6 +226,8 @@ export interface CoreSetup, any, any]>, []>(() => Promise.resolve([createCoreStartMock({ basePath }), pluginStartDeps, pluginStartContract]) @@ -76,6 +78,7 @@ function createCoreStartMock({ basePath = '' } = {}) { application: applicationServiceMock.createStartContract(), chrome: chromeServiceMock.createStartContract(), docLinks: docLinksServiceMock.createStartContract(), + executionContext: executionContextServiceMock.createStartContract(), http: httpServiceMock.createStartContract({ basePath }), i18n: i18nServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index 345aea4b6cac87..8c085d3de23693 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -88,6 +88,7 @@ export function createPluginSetupContext< registerAppUpdater: (statusUpdater$) => deps.application.registerAppUpdater(statusUpdater$), }, fatalErrors: deps.fatalErrors, + executionContext: deps.executionContext, http: deps.http, notifications: deps.notifications, uiSettings: deps.uiSettings, @@ -129,6 +130,7 @@ export function createPluginStartContext< getUrlForApp: deps.application.getUrlForApp, }, docLinks: deps.docLinks, + executionContext: deps.executionContext, http: deps.http, chrome: omit(deps.chrome, 'getComponent'), i18n: deps.i18n, diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index c4e3b7990ba32b..40976424b7edd7 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -36,6 +36,7 @@ import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock'; import { themeServiceMock } from '../theme/theme_service.mock'; +import { executionContextServiceMock } from '../execution_context/execution_context_service.mock'; export let mockPluginInitializers: Map; @@ -85,6 +86,7 @@ describe('PluginsService', () => { mockSetupDeps = { application: applicationServiceMock.createInternalSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), + executionContext: executionContextServiceMock.createSetupContract(), http: httpServiceMock.createSetupContract(), injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createSetupContract(), @@ -100,6 +102,7 @@ describe('PluginsService', () => { mockStartDeps = { application: applicationServiceMock.createInternalStartContract(), docLinks: docLinksServiceMock.createStartContract(), + executionContext: executionContextServiceMock.createStartContract(), http: httpServiceMock.createStartContract(), chrome: chromeServiceMock.createStartContract(), i18n: i18nServiceMock.createStartContract(), diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 4cf845de4617db..e3f2822b5a7c8d 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -401,6 +401,8 @@ export interface CoreSetup; @@ -429,6 +431,8 @@ export interface CoreStart { // (undocumented) docLinks: DocLinksStart; // (undocumented) + executionContext: ExecutionContextStart; + // (undocumented) fatalErrors: FatalErrorsStart; // (undocumented) http: HttpStart; @@ -461,6 +465,7 @@ export class CoreSystem { // (undocumented) start(): Promise<{ application: InternalApplicationStart; + executionContext: ExecutionContextSetup; } | undefined>; // (undocumented) stop(): void; @@ -511,6 +516,20 @@ export interface ErrorToastOptions extends ToastOptions { toastMessage?: string; } +// @public +export interface ExecutionContextSetup { + clear(): void; + context$: Observable; + get(): KibanaExecutionContext; + // Warning: (ae-forgotten-export) The symbol "Labels" needs to be exported by the entry point index.d.ts + getAsLabels(): Labels_2; + set(c$: KibanaExecutionContext): void; + withGlobalContext(context?: KibanaExecutionContext): KibanaExecutionContext; +} + +// @public +export type ExecutionContextStart = ExecutionContextSetup; + // @public export interface FatalErrorInfo { // (undocumented) @@ -751,9 +770,10 @@ export interface IUiSettingsClient { // @public export type KibanaExecutionContext = { - readonly type: string; - readonly name: string; - readonly id: string; + readonly type?: string; + readonly name?: string; + readonly page?: string; + readonly id?: string; readonly description?: string; readonly url?: string; child?: KibanaExecutionContext; @@ -1522,6 +1542,6 @@ export interface UserProvidedValues { // Warnings were encountered during analysis: // -// src/core/public/core_system.ts:173:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts +// src/core/public/core_system.ts:183:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/server/execution_context/execution_context_container.ts b/src/core/server/execution_context/execution_context_container.ts index de895bcff5ecbd..1528df6c231408 100644 --- a/src/core/server/execution_context/execution_context_container.ts +++ b/src/core/server/execution_context/execution_context_container.ts @@ -50,9 +50,10 @@ export interface IExecutionContextContainer { } function stringify(ctx: KibanaExecutionContext): string { - const stringifiedCtx = `${encodeURIComponent(ctx.type)}:${encodeURIComponent( + const encodeURIComponentIfNotEmpty = (val?: string) => encodeURIComponent(val || ''); + const stringifiedCtx = `${encodeURIComponentIfNotEmpty(ctx.type)}:${encodeURIComponentIfNotEmpty( ctx.name - )}:${encodeURIComponent(ctx.id!)}`; + )}:${encodeURIComponentIfNotEmpty(ctx.id)}`; return ctx.child ? `${stringifiedCtx};${stringify(ctx.child)}` : stringifiedCtx; } diff --git a/src/core/server/execution_context/execution_context_service.mock.ts b/src/core/server/execution_context/execution_context_service.mock.ts index 68aab7a5b84f84..85768eb423f26b 100644 --- a/src/core/server/execution_context/execution_context_service.mock.ts +++ b/src/core/server/execution_context/execution_context_service.mock.ts @@ -26,6 +26,7 @@ const createExecutionContextMock = () => { get: jest.fn(), getParentContextFrom: jest.fn(), getAsHeader: jest.fn(), + getAsLabels: jest.fn(), }; mock.withContext.mockImplementation(withContextMock); return mock; @@ -38,6 +39,7 @@ const createInternalSetupContractMock = () => { const createSetupContractMock = () => { const mock: jest.Mocked = { withContext: jest.fn(), + getAsLabels: jest.fn(), }; mock.withContext.mockImplementation(withContextMock); return mock; diff --git a/src/core/server/execution_context/execution_context_service.ts b/src/core/server/execution_context/execution_context_service.ts index 6e2b809e230431..03ae2cb36c9ec2 100644 --- a/src/core/server/execution_context/execution_context_service.ts +++ b/src/core/server/execution_context/execution_context_service.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ import { AsyncLocalStorage } from 'async_hooks'; +import apm from 'elastic-apm-node'; +import { isUndefined, omitBy } from 'lodash'; import type { Subscription } from 'rxjs'; import type { CoreService, KibanaExecutionContext } from '../../types'; @@ -39,6 +41,10 @@ export interface IExecutionContext { * returns serialized representation to send as a header **/ getAsHeader(): string | undefined; + /** + * returns apm labels + **/ + getAsLabels(): apm.Labels; } /** @@ -61,6 +67,7 @@ export interface ExecutionContextSetup { * The nested calls stack the registered context on top of each other. **/ withContext(context: KibanaExecutionContext | undefined, fn: (...args: any[]) => R): R; + getAsLabels(): apm.Labels; } /** @@ -97,6 +104,7 @@ export class ExecutionContextService setRequestId: this.setRequestId.bind(this), get: this.get.bind(this), getAsHeader: this.getAsHeader.bind(this), + getAsLabels: this.getAsLabels.bind(this), }; } @@ -108,6 +116,7 @@ export class ExecutionContextService withContext: this.withContext.bind(this), get: this.get.bind(this), getAsHeader: this.getAsHeader.bind(this), + getAsLabels: this.getAsLabels.bind(this), }; } @@ -161,4 +170,18 @@ export class ExecutionContextService return `${requestId}${executionContextStr}`; } + + private getAsLabels() { + if (!this.enabled) return {}; + const executionContext = this.contextStore.getStore()?.toJSON(); + + return omitBy( + { + name: executionContext?.name, + id: executionContext?.id, + page: executionContext?.page, + }, + isUndefined + ); + } } diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 4623b09b19e297..813f8e97843326 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -21,6 +21,7 @@ import agent from 'elastic-apm-node'; import type { Duration } from 'moment'; import { Observable } from 'rxjs'; import { take } from 'rxjs/operators'; +import apm from 'elastic-apm-node'; import { Logger, LoggerFactory } from '../logging'; import { HttpConfig } from './http_config'; import type { InternalExecutionContextSetup } from '../execution_context'; @@ -338,7 +339,11 @@ export class HttpServer { const requestId = getRequestId(request, config.requestId); const parentContext = executionContext?.getParentContextFrom(request.headers); - if (parentContext) executionContext?.set(parentContext); + + if (executionContext && parentContext) { + executionContext.set(parentContext); + apm.addLabels(executionContext.getAsLabels()); + } executionContext?.setRequestId(requestId); diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index 18abbe88c49135..983a12627b7f38 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -161,6 +161,7 @@ export function createPluginSetupContext( }, executionContext: { withContext: deps.executionContext.withContext, + getAsLabels: deps.executionContext.getAsLabels, }, http: { createCookieSessionStorageFactory: deps.http.createCookieSessionStorageFactory, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index d7ed4928e1cf5d..5fe1942ed8453b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -7,6 +7,7 @@ /// import { AddConfigDeprecation } from '@kbn/config'; +import apm from 'elastic-apm-node'; import Boom from '@hapi/boom'; import { ByteSizeValue } from '@kbn/config-schema'; import { CliArgs } from '@kbn/config'; @@ -994,6 +995,8 @@ export class EventLoopDelaysMonitor { // @public (undocumented) export interface ExecutionContextSetup { + // (undocumented) + getAsLabels(): apm.Labels; withContext(context: KibanaExecutionContext | undefined, fn: (...args: any[]) => R): R; } @@ -1319,9 +1322,10 @@ export interface IUiSettingsClient { // @public export type KibanaExecutionContext = { - readonly type: string; - readonly name: string; - readonly id: string; + readonly type?: string; + readonly name?: string; + readonly page?: string; + readonly id?: string; readonly description?: string; readonly url?: string; child?: KibanaExecutionContext; diff --git a/src/core/test_helpers/http_test_setup.ts b/src/core/test_helpers/http_test_setup.ts index 468034dffceb9b..67b340898aab47 100644 --- a/src/core/test_helpers/http_test_setup.ts +++ b/src/core/test_helpers/http_test_setup.ts @@ -9,6 +9,7 @@ import { HttpService } from '../public/http'; import { fatalErrorsServiceMock } from '../public/fatal_errors/fatal_errors_service.mock'; import { injectedMetadataServiceMock } from '../public/injected_metadata/injected_metadata_service.mock'; +import { executionContextServiceMock } from '../public/execution_context/execution_context_service.mock'; export type SetupTap = ( injectedMetadata: ReturnType, @@ -28,7 +29,8 @@ export function setup(tap: SetupTap = defaultTap) { tap(injectedMetadata, fatalErrors); const httpService = new HttpService(); - const http = httpService.setup({ fatalErrors, injectedMetadata }); + const executionContext = executionContextServiceMock.createSetupContract(); + const http = httpService.setup({ fatalErrors, injectedMetadata, executionContext }); return { httpService, injectedMetadata, fatalErrors, http }; } diff --git a/src/core/test_helpers/kbn_server.ts b/src/core/test_helpers/kbn_server.ts index a63a8d406db406..87026fc3fb9b2d 100644 --- a/src/core/test_helpers/kbn_server.ts +++ b/src/core/test_helpers/kbn_server.ts @@ -229,10 +229,6 @@ export function createTestServers({ writeTo: process.stdout, }); - log.indent(6); - log.info('starting elasticsearch'); - log.indent(4); - const es = createTestEsCluster( defaultsDeep({}, settings.es ?? {}, { log, @@ -240,8 +236,6 @@ export function createTestServers({ }) ); - log.indent(-4); - // Add time for KBN and adding users adjustTimeout(es.getStartTimeout() + 100000); diff --git a/src/core/types/execution_context.ts b/src/core/types/execution_context.ts index 1b985a73f410bd..d790b8d855fd4e 100644 --- a/src/core/types/execution_context.ts +++ b/src/core/types/execution_context.ts @@ -16,11 +16,13 @@ export type KibanaExecutionContext = { /** * Kibana application initated an operation. * */ - readonly type: string; // 'visualization' | 'actions' | 'server' | ..; - /** public name of a user-facing feature */ - readonly name: string; // 'TSVB' | 'Lens' | 'action_execution' | ..; + readonly type?: string; // 'visualization' | 'actions' | 'server' | ..; + /** public name of an application or a user-facing feature */ + readonly name?: string; // 'TSVB' | 'Lens' | 'action_execution' | ..; + /** a stand alone, logical unit such as an application page or tab */ + readonly page?: string; /** unique value to identify the source */ - readonly id: string; + readonly id?: string; /** human readable description. For example, a vis title, action name */ readonly description?: string; /** in browser - url to navigate to a current page, on server - endpoint path, for task: task SO url */ diff --git a/src/dev/build/lib/runner.ts b/src/dev/build/lib/runner.ts index 1fccd884cc4f95..e12f7d24cfc491 100644 --- a/src/dev/build/lib/runner.ts +++ b/src/dev/build/lib/runner.ts @@ -33,29 +33,30 @@ export interface Task { export function createRunner({ config, log }: Options) { async function execTask(desc: string, task: Task | GlobalTask, lastArg: any) { log.info(desc); - log.indent(4); - - const start = Date.now(); - const time = () => { - const sec = (Date.now() - start) / 1000; - const minStr = sec > 60 ? `${Math.floor(sec / 60)} min ` : ''; - const secStr = `${Math.round(sec % 60)} sec`; - return chalk.dim(`${minStr}${secStr}`); - }; - try { - await task.run(config, log, lastArg); - log.success(chalk.green('✓'), time()); - } catch (error) { - if (!isErrorLogged(error)) { - log.error(`failure ${time()}`); - log.error(error); - markErrorLogged(error); - } + await log.indent(4, async () => { + const start = Date.now(); + const time = () => { + const sec = (Date.now() - start) / 1000; + const minStr = sec > 60 ? `${Math.floor(sec / 60)} min ` : ''; + const secStr = `${Math.round(sec % 60)} sec`; + return chalk.dim(`${minStr}${secStr}`); + }; + + try { + await task.run(config, log, lastArg); + log.success(chalk.green('✓'), time()); + } catch (error) { + if (!isErrorLogged(error)) { + log.error(`failure ${time()}`); + log.error(error); + markErrorLogged(error); + } - throw error; + throw error; + } + }); } finally { - log.indent(-4); log.write(''); } } diff --git a/src/dev/build/tasks/notice_file_task.ts b/src/dev/build/tasks/notice_file_task.ts index 43d95858e7b8de..2a446e73723e89 100644 --- a/src/dev/build/tasks/notice_file_task.ts +++ b/src/dev/build/tasks/notice_file_task.ts @@ -18,13 +18,15 @@ export const CreateNoticeFile: Task = { async run(config, log, build) { log.info('Generating notice from source'); - log.indent(4); - const noticeFromSource = await generateNoticeFromSource({ - productName: 'Kibana', - directory: build.resolvePath(), - log, - }); - log.indent(-4); + const noticeFromSource = await log.indent( + 4, + async () => + await generateNoticeFromSource({ + productName: 'Kibana', + directory: build.resolvePath(), + log, + }) + ); log.info('Discovering installed packages'); const packages = await getInstalledPackages({ diff --git a/src/dev/eslint/run_eslint_with_types.ts b/src/dev/eslint/run_eslint_with_types.ts index 0f2a10d07d681a..d7f2482fcb26b9 100644 --- a/src/dev/eslint/run_eslint_with_types.ts +++ b/src/dev/eslint/run_eslint_with_types.ts @@ -109,9 +109,9 @@ export function runEslintWithTypes() { return undefined; } else { log.error(`${project.name} failed`); - log.indent(4); - log.write(proc.all); - log.indent(-4); + log.indent(4, () => { + log.write(proc.all); + }); return project; } }, concurrency), diff --git a/src/dev/prs/run_update_prs_cli.ts b/src/dev/prs/run_update_prs_cli.ts index 4d82c704cad275..cde7f495b1eb60 100644 --- a/src/dev/prs/run_update_prs_cli.ts +++ b/src/dev/prs/run_update_prs_cli.ts @@ -148,12 +148,9 @@ run( await init(); for (const pr of prs) { log.info('pr #%s', pr.number); - log.indent(4); - try { + await log.indent(4, async () => { await updatePr(pr); - } finally { - log.indent(-4); - } + }); } }, { diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index e5657dd4663a38..b4d350c44174cb 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -45,7 +45,7 @@ export const PROJECTS = [ { name: 'enterprise_search/shared/cypress' } ), createProject( - 'x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress/tsconfig.json', + 'x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/tsconfig.json', { name: 'enterprise_search/overview/cypress' } ), createProject( diff --git a/src/plugins/custom_integrations/common/index.ts b/src/plugins/custom_integrations/common/index.ts index 7881a4a0ca8805..46cf778bf0139a 100755 --- a/src/plugins/custom_integrations/common/index.ts +++ b/src/plugins/custom_integrations/common/index.ts @@ -27,6 +27,7 @@ export const INTEGRATION_CATEGORY_DISPLAY = { kubernetes: 'Kubernetes', languages: 'Languages', message_queue: 'Message queue', + microsoft_365: 'Microsoft 365', monitoring: 'Monitoring', network: 'Network', notification: 'Notification', @@ -41,6 +42,7 @@ export const INTEGRATION_CATEGORY_DISPLAY = { // Kibana added communications: 'Communications', + enterprise_search: 'Enterprise search', file_storage: 'File storage', language_client: 'Language client', upload_file: 'Upload a file', diff --git a/src/plugins/dashboard/public/application/dashboard_app.tsx b/src/plugins/dashboard/public/application/dashboard_app.tsx index 7aedbe9e110019..a32e6643a4e3a1 100644 --- a/src/plugins/dashboard/public/application/dashboard_app.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app.tsx @@ -11,7 +11,7 @@ import React, { useEffect, useMemo } from 'react'; import { useDashboardSelector } from './state'; import { useDashboardAppState } from './hooks'; -import { useKibana } from '../../../kibana_react/public'; +import { useKibana, useExecutionContext } from '../../../kibana_react/public'; import { getDashboardBreadcrumb, getDashboardTitle, @@ -48,6 +48,12 @@ export function DashboardApp({ [core.notifications.toasts, history, uiSettings] ); + useExecutionContext(core.executionContext, { + type: 'application', + page: 'app', + id: savedDashboardId || 'new', + }); + const dashboardState = useDashboardSelector((state) => state.dashboardStateReducer); const dashboardAppState = useDashboardAppState({ history, diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts index 98b3d761f350ec..26641dc52e3d54 100644 --- a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts +++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts @@ -220,11 +220,7 @@ export const useDashboardAppState = ({ savedDashboard, data, executionContext: { - type: 'application', - name: 'dashboard', - id: savedDashboard.id ?? 'unsaved_dashboard', description: savedDashboard.title, - url: history.location.pathname, }, }); if (canceled || !dashboardContainer) { diff --git a/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx b/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx index 5b53fc47e06a41..65374ad723f232 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx +++ b/src/plugins/dashboard/public/application/listing/dashboard_listing.tsx @@ -35,6 +35,7 @@ import { DashboardUnsavedListing } from './dashboard_unsaved_listing'; import { confirmCreateWithUnsaved, confirmDiscardUnsavedChanges } from './confirm_overlays'; import { getDashboardListItemLink } from './get_dashboard_list_item_link'; import { DASHBOARD_PANELS_UNSAVED_ID } from '../lib/dashboard_session_storage'; +import { useExecutionContext } from '../../../../kibana_react/public'; export interface DashboardListingProps { kbnUrlStateStorage: IKbnUrlStateStorage; @@ -67,6 +68,11 @@ export const DashboardListing = ({ dashboardSessionStorage.getDashboardIdsWithUnsavedChanges() ); + useExecutionContext(core.executionContext, { + type: 'application', + page: 'list', + }); + // Set breadcrumbs useEffect useEffect(() => { setBreadcrumbs([ diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts index 8510acf1572c79..963fe024c1f8fc 100644 --- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts +++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts @@ -126,7 +126,7 @@ describe('getAggsFormats', () => { const mapping = { id: 'multi_terms', params: { - paramsPerField: Array(terms.length).fill({ id: 'terms' }), + paramsPerField: [{ id: 'terms' }, { id: 'terms' }, { id: 'terms' }], }, }; @@ -141,7 +141,7 @@ describe('getAggsFormats', () => { const mapping = { id: 'multi_terms', params: { - paramsPerField: Array(terms.length).fill({ id: 'terms' }), + paramsPerField: [{ id: 'terms' }, { id: 'terms' }, { id: 'terms' }], separator: ' - ', }, }; diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts index f14f981fdec65c..e514cc24f93cad 100644 --- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts +++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts @@ -12,6 +12,7 @@ import { i18n } from '@kbn/i18n'; import { FieldFormat, FieldFormatInstanceType, + FieldFormatParams, FieldFormatsContentType, IFieldFormat, SerializedFieldFormat, @@ -133,11 +134,20 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta static id = 'multi_terms'; static hidden = true; + private formatCache: Map, FieldFormat> = new Map(); + convert = (val: unknown, type: FieldFormatsContentType) => { const params = this._params; - const formats = (params.paramsPerField as SerializedFieldFormat[]).map((fieldParams) => - getFieldFormat({ id: fieldParams.id, params: fieldParams }) - ); + const formats = (params.paramsPerField as SerializedFieldFormat[]).map((fieldParams) => { + const isCached = this.formatCache.has(fieldParams); + const cachedFormat = + this.formatCache.get(fieldParams) || + getFieldFormat({ id: fieldParams.id, params: fieldParams }); + if (!isCached) { + this.formatCache.set(fieldParams, cachedFormat); + } + return cachedFormat; + }); if (String(val) === '__other__') { return params.otherBucketLabel; diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts index 968dd870489fe0..f1e2e903cadde3 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts @@ -119,6 +119,7 @@ describe('SearchInterceptor', () => { }), uiSettings: mockCoreSetup.uiSettings, http: mockCoreSetup.http, + executionContext: mockCoreSetup.executionContext, session: sessionService, theme: themeServiceMock.createSetupContract(), }); @@ -543,7 +544,12 @@ describe('SearchInterceptor', () => { .catch(() => {}); expect(fetchMock.mock.calls[0][0]).toEqual( expect.objectContaining({ - options: { sessionId, isStored: true, isRestore: true, strategy: 'ese' }, + options: { + sessionId, + isStored: true, + isRestore: true, + strategy: 'ese', + }, }) ); diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts index 7dc1ce6dee0786..251e191d589e3d 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts @@ -61,6 +61,7 @@ import { SearchAbortController } from './search_abort_controller'; export interface SearchInterceptorDeps { bfetch: BfetchPublicSetup; http: CoreSetup['http']; + executionContext: CoreSetup['executionContext']; uiSettings: CoreSetup['uiSettings']; startServices: Promise<[CoreStart, any, unknown]>; toasts: ToastsSetup; @@ -297,10 +298,14 @@ export class SearchInterceptor { } }) as Promise; } else { + const { executionContext, ...rest } = options || {}; return this.batchedFetch( { request, - options: this.getSerializableOptions(options), + options: this.getSerializableOptions({ + ...rest, + executionContext: this.deps.executionContext.withGlobalContext(executionContext), + }), }, abortSignal ); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 961599de713df8..b21ad44c7bd6de 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -89,7 +89,7 @@ export class SearchService implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} public setup( - { http, getStartServices, notifications, uiSettings, theme }: CoreSetup, + { http, getStartServices, notifications, uiSettings, executionContext, theme }: CoreSetup, { bfetch, expressions, usageCollection, nowProvider }: SearchServiceSetupDependencies ): ISearchSetup { this.usageCollector = createUsageCollector(getStartServices, usageCollection); @@ -108,6 +108,7 @@ export class SearchService implements Plugin { this.searchInterceptor = new SearchInterceptor({ bfetch, toasts: notifications.toasts, + executionContext, http, uiSettings, startServices: getStartServices(), diff --git a/src/plugins/data/server/search/routes/bsearch.ts b/src/plugins/data/server/search/routes/bsearch.ts index 314de4254851fb..25b1bd0d7009d4 100644 --- a/src/plugins/data/server/search/routes/bsearch.ts +++ b/src/plugins/data/server/search/routes/bsearch.ts @@ -9,6 +9,7 @@ import { catchError, first } from 'rxjs/operators'; import { BfetchServerSetup } from 'src/plugins/bfetch/server'; import type { ExecutionContextSetup } from 'src/core/server'; +import apm from 'elastic-apm-node'; import { IKibanaSearchRequest, IKibanaSearchResponse, @@ -33,9 +34,10 @@ export function registerBsearchRoute( */ onBatchItem: async ({ request: requestData, options }) => { const { executionContext, ...restOptions } = options || {}; + return executionContextService.withContext(executionContext, () => { + apm.addLabels(executionContextService.getAsLabels()); - return executionContextService.withContext(executionContext, () => - search + return search .search(requestData, restOptions) .pipe( first(), @@ -49,8 +51,8 @@ export function registerBsearchRoute( }; }) ) - .toPromise() - ); + .toPromise(); + }); }, }; }); diff --git a/src/plugins/dev_tools/public/application.tsx b/src/plugins/dev_tools/public/application.tsx index a3ec8fc0a9af20..bcfde68abd99c1 100644 --- a/src/plugins/dev_tools/public/application.tsx +++ b/src/plugins/dev_tools/public/application.tsx @@ -15,8 +15,14 @@ import { I18nProvider } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; -import { ApplicationStart, ChromeStart, ScopedHistory, CoreTheme } from 'src/core/public'; -import { KibanaThemeProvider } from '../../kibana_react/public'; +import type { + ApplicationStart, + ChromeStart, + ScopedHistory, + CoreTheme, + ExecutionContextStart, +} from 'src/core/public'; +import { KibanaThemeProvider, useExecutionContext } from '../../kibana_react/public'; import type { DocTitleService, BreadcrumbService } from './services'; import { DevToolApp } from './dev_tool'; @@ -24,6 +30,7 @@ import { DevToolApp } from './dev_tool'; export interface AppServices { docTitleService: DocTitleService; breadcrumbService: BreadcrumbService; + executionContext: ExecutionContextStart; } interface DevToolsWrapperProps { @@ -64,6 +71,11 @@ function DevToolsWrapper({ breadcrumbService.setBreadcrumbs(activeDevTool.title); }, [activeDevTool, docTitleService, breadcrumbService]); + useExecutionContext(appServices.executionContext, { + type: 'application', + page: activeDevTool.id, + }); + return (
diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 1876bf278513e6..ee729c8f4400c0 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -61,7 +61,7 @@ export class DevToolsPlugin implements Plugin { element.classList.add('devAppWrapper'); const [core] = await getStartServices(); - const { application, chrome } = core; + const { application, chrome, executionContext } = core; this.docTitleService.setup(chrome.docTitle.change); this.breadcrumbService.setup(chrome.setBreadcrumbs); @@ -69,6 +69,7 @@ export class DevToolsPlugin implements Plugin { const appServices = { breadcrumbService: this.breadcrumbService, docTitleService: this.docTitleService, + executionContext, }; const { renderApp } = await import('./application'); diff --git a/src/plugins/discover/public/application/context/context_app.test.tsx b/src/plugins/discover/public/application/context/context_app.test.tsx index c9089a6c1111c1..cf1e7a98e01a37 100644 --- a/src/plugins/discover/public/application/context/context_app.test.tsx +++ b/src/plugins/discover/public/application/context/context_app.test.tsx @@ -46,6 +46,9 @@ describe('ContextApp test', () => { toastNotifications: { addDanger: () => {} }, navigation: mockNavigationPlugin, core: { + executionContext: { + set: jest.fn(), + }, notifications: { toasts: [] }, theme: { theme$: themeServiceMock.createStartContract().theme$ }, }, diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index 8d2a6b2c048155..dcf1c6b11e68ed 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -25,6 +25,7 @@ import { ContextAppContent } from './context_app_content'; import { SurrDocType } from './services/context'; import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; import { useDiscoverServices } from '../../utils/use_discover_services'; +import { useExecutionContext } from '../../../../kibana_react/public'; import { generateFilters } from '../../../../data/public'; const ContextAppContentMemoized = memo(ContextAppContent); @@ -36,11 +37,17 @@ export interface ContextAppProps { export const ContextApp = ({ indexPattern, anchorId }: ContextAppProps) => { const services = useDiscoverServices(); - const { uiSettings, capabilities, indexPatterns, navigation, filterManager } = services; + const { uiSettings, capabilities, indexPatterns, navigation, filterManager, core } = services; const isLegacy = useMemo(() => uiSettings.get(DOC_TABLE_LEGACY), [uiSettings]); const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); + useExecutionContext(core.executionContext, { + type: 'application', + page: 'context', + id: indexPattern.id || '', + }); + /** * Context app state */ diff --git a/src/plugins/discover/public/application/doc/single_doc_route.tsx b/src/plugins/discover/public/application/doc/single_doc_route.tsx index d11c6bdca76a04..e2bdc6dc799e6d 100644 --- a/src/plugins/discover/public/application/doc/single_doc_route.tsx +++ b/src/plugins/discover/public/application/doc/single_doc_route.tsx @@ -16,6 +16,7 @@ import { withQueryParams } from '../../utils/with_query_params'; import { useMainRouteBreadcrumb } from '../../utils/use_navigation_props'; import { Doc } from './components/doc'; import { useDiscoverServices } from '../../utils/use_discover_services'; +import { useExecutionContext } from '../../../../kibana_react/public'; export interface SingleDocRouteProps { /** @@ -31,11 +32,17 @@ export interface DocUrlParams { const SingleDoc = ({ id }: SingleDocRouteProps) => { const services = useDiscoverServices(); - const { chrome, timefilter } = services; + const { chrome, timefilter, core } = services; const { indexPatternId, index } = useParams(); const breadcrumb = useMainRouteBreadcrumb(); + useExecutionContext(core.executionContext, { + type: 'application', + page: 'single-doc', + id: indexPatternId, + }); + useEffect(() => { chrome.setBreadcrumbs([ ...getRootBreadcrumbs(breadcrumb), diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx index d5950085b94c72..dcf229d36b1e0e 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -24,6 +24,7 @@ import { LoadingIndicator } from '../../components/common/loading_indicator'; import { DiscoverError } from '../../components/common/error_alert'; import { useDiscoverServices } from '../../utils/use_discover_services'; import { getUrlTracker } from '../../kibana_services'; +import { useExecutionContext } from '../../../../kibana_react/public'; const DiscoverMainAppMemoized = memo(DiscoverMainApp); @@ -50,6 +51,12 @@ export function DiscoverMainRoute() { >([]); const { id } = useParams(); + useExecutionContext(core.executionContext, { + type: 'application', + page: 'app', + id: id || 'new', + }); + const navigateToOverview = useCallback(() => { core.application.navigateToApp('kibanaOverview', { path: '#' }); }, [core.application]); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts index 4c68eff54f579f..b1f736fa4b2242 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts @@ -117,7 +117,7 @@ describe('test fetchCharts', () => { }); }); - test('fetch$ is called with execution context containing savedSearch id', async () => { + test('fetch$ is called with request specific execution context', async () => { const fetch$Mock = jest.fn().mockReturnValue(of(requestResult)); savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; @@ -126,10 +126,6 @@ describe('test fetchCharts', () => { expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` Object { "description": "fetch chart data and total hits", - "id": "the-saved-search-id-with-timefield", - "name": "discover", - "type": "application", - "url": "/", } `); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.ts index 00cb9c43caccf2..1ea2594a89d97f 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_chart.ts @@ -40,11 +40,7 @@ export function fetchChart( const chartAggConfigs = updateSearchSource(searchSource, interval, data); const executionContext = { - type: 'application', - name: 'discover', description: 'fetch chart data and total hits', - url: window.location.pathname, - id: savedSearch.id ?? '', }; const fetch$ = searchSource diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts index 000d3282c38b3c..1e73f5de3a3f66 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts @@ -57,10 +57,6 @@ describe('test fetchDocuments', () => { expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` Object { "description": "fetch total hits", - "id": "the-saved-search-id", - "name": "discover", - "type": "application", - "url": "/", } `); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.ts index dbf972265547ee..8338839e8b0acd 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.ts @@ -32,11 +32,7 @@ export const fetchDocuments = ( } const executionContext = { - type: 'application', - name: 'discover', description: 'fetch documents', - url: window.location.pathname, - id: savedSearch.id ?? '', }; const fetch$ = searchSource diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts index ba7b6a765aa2e9..a5485c1a2e2e90 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts @@ -51,10 +51,6 @@ describe('test fetchTotalHits', () => { expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` Object { "description": "fetch total hits", - "id": "the-saved-search-id", - "name": "discover", - "type": "application", - "url": "/", } `); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts index af2d55e23cf323..e696570f05cf0b 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts @@ -30,11 +30,7 @@ export function fetchTotalHits( } const executionContext = { - type: 'application', - name: 'discover', description: 'fetch total hits', - url: window.location.pathname, - id: savedSearch.id ?? '', }; const fetch$ = searchSource diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index baed839d411239..94e8b505f1dd20 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -39,6 +39,8 @@ export { createReactOverlays } from './overlays'; export { useUiSetting, useUiSetting$ } from './ui_settings'; +export { useExecutionContext } from './use_execution_context'; + export type { TableListViewProps, TableListViewState } from './table_list_view'; export { TableListView } from './table_list_view'; diff --git a/src/plugins/kibana_react/public/use_execution_context/index.ts b/src/plugins/kibana_react/public/use_execution_context/index.ts new file mode 100644 index 00000000000000..f36d094eb86d44 --- /dev/null +++ b/src/plugins/kibana_react/public/use_execution_context/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export { useExecutionContext } from './use_execution_context'; diff --git a/src/plugins/kibana_react/public/use_execution_context/use_execution_context.ts b/src/plugins/kibana_react/public/use_execution_context/use_execution_context.ts new file mode 100644 index 00000000000000..e2c538056153c3 --- /dev/null +++ b/src/plugins/kibana_react/public/use_execution_context/use_execution_context.ts @@ -0,0 +1,28 @@ +/* + * 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 type { KibanaExecutionContext, CoreStart } from 'kibana/public'; +import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect'; + +/** + * Set and clean up application level execution context + * @param executionContext + * @param context + */ +export function useExecutionContext( + executionContext: CoreStart['executionContext'], + context: KibanaExecutionContext +) { + useDeepCompareEffect(() => { + executionContext.set(context); + + return () => { + executionContext.clear(); + }; + }, [context]); +} diff --git a/src/plugins/vis_types/timeseries/common/calculate_label.test.ts b/src/plugins/vis_types/timeseries/common/calculate_label.test.ts index 7083711246e7bc..7e612ed1aaddd6 100644 --- a/src/plugins/vis_types/timeseries/common/calculate_label.test.ts +++ b/src/plugins/vis_types/timeseries/common/calculate_label.test.ts @@ -9,6 +9,7 @@ import { calculateLabel } from './calculate_label'; import type { Metric } from './types'; import { SanitizedFieldType } from './types'; +import { KBN_FIELD_TYPES } from '../../../data/common'; describe('calculateLabel(metric, metrics)', () => { test('returns the metric.alias if set', () => { @@ -90,7 +91,7 @@ describe('calculateLabel(metric, metrics)', () => { { id: 1, type: 'max', field: 'network.out.bytes', alias: 'Outbound Traffic' }, metric, ] as unknown as Metric[]; - const fields: SanitizedFieldType[] = [{ name: '2', label: '2', type: 'field' }]; + const fields: SanitizedFieldType[] = [{ name: '2', label: '2', type: KBN_FIELD_TYPES.DATE }]; expect(() => calculateLabel(metric, metrics, fields)).toThrowError('Field "3" not found'); }); @@ -101,7 +102,7 @@ describe('calculateLabel(metric, metrics)', () => { { id: 1, type: 'max', field: 'network.out.bytes', alias: 'Outbound Traffic' }, metric, ] as unknown as Metric[]; - const fields: SanitizedFieldType[] = [{ name: '2', label: '2', type: 'field' }]; + const fields: SanitizedFieldType[] = [{ name: '2', label: '2', type: KBN_FIELD_TYPES.DATE }]; expect(calculateLabel(metric, metrics, fields, false)).toBe('Max of 3'); }); diff --git a/src/plugins/vis_types/timeseries/common/fields_utils.test.ts b/src/plugins/vis_types/timeseries/common/fields_utils.test.ts index 228dfbfd2db9df..6dd00d803b7c33 100644 --- a/src/plugins/vis_types/timeseries/common/fields_utils.test.ts +++ b/src/plugins/vis_types/timeseries/common/fields_utils.test.ts @@ -6,8 +6,16 @@ * Side Public License, v 1. */ -import { toSanitizedFieldType } from './fields_utils'; -import type { FieldSpec } from '../../../data/common'; +import { + getFieldsForTerms, + toSanitizedFieldType, + getMultiFieldLabel, + createCachedFieldValueFormatter, +} from './fields_utils'; +import { FieldSpec, KBN_FIELD_TYPES } from '../../../data/common'; +import { DataView } from '../../../data_views/common'; +import { stubLogstashDataView } from '../../../data/common/stubs'; +import { FieldFormatsRegistry, StringFormat } from '../../../field_formats/common'; describe('fields_utils', () => { describe('toSanitizedFieldType', () => { @@ -59,4 +67,92 @@ describe('fields_utils', () => { expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); }); }); + + describe('getFieldsForTerms', () => { + test('should return fields as array', () => { + expect(getFieldsForTerms('field')).toEqual(['field']); + expect(getFieldsForTerms(['field', 'field1'])).toEqual(['field', 'field1']); + }); + + test('should exclude empty values', () => { + expect(getFieldsForTerms([null, ''])).toEqual([]); + }); + + test('should return empty array in case of undefined field', () => { + expect(getFieldsForTerms(undefined)).toEqual([]); + }); + }); + + describe('getMultiFieldLabel', () => { + test('should return label for single field', () => { + expect( + getMultiFieldLabel( + ['field'], + [{ name: 'field', label: 'Label', type: KBN_FIELD_TYPES.DATE }] + ) + ).toBe('Label'); + }); + + test('should return label for multi fields', () => { + expect( + getMultiFieldLabel( + ['field', 'field1'], + [ + { name: 'field', label: 'Label', type: KBN_FIELD_TYPES.DATE }, + { name: 'field2', label: 'Label1', type: KBN_FIELD_TYPES.DATE }, + ] + ) + ).toBe('Label + 1 other'); + }); + + test('should return label for multi fields (2 others)', () => { + expect( + getMultiFieldLabel( + ['field', 'field1', 'field2'], + [ + { name: 'field', label: 'Label', type: KBN_FIELD_TYPES.DATE }, + { name: 'field1', label: 'Label1', type: KBN_FIELD_TYPES.DATE }, + { name: 'field3', label: 'Label2', type: KBN_FIELD_TYPES.DATE }, + ] + ) + ).toBe('Label + 2 others'); + }); + }); + + describe('createCachedFieldValueFormatter', () => { + let dataView: DataView; + + beforeEach(() => { + dataView = stubLogstashDataView; + }); + + test('should use data view formatters', () => { + const getFormatterForFieldSpy = jest.spyOn(dataView, 'getFormatterForField'); + + const cache = createCachedFieldValueFormatter(dataView); + + cache('bytes', '10001'); + cache('bytes', '20002'); + + expect(getFormatterForFieldSpy).toHaveBeenCalledTimes(1); + }); + + test('should use default formatters in case of Data view not defined', () => { + const fieldFormatServiceMock = { + getDefaultInstance: jest.fn().mockReturnValue(new StringFormat()), + } as unknown as FieldFormatsRegistry; + + const cache = createCachedFieldValueFormatter( + null, + [{ name: 'field', label: 'Label', type: KBN_FIELD_TYPES.STRING }], + fieldFormatServiceMock + ); + + cache('field', '10001'); + cache('field', '20002'); + + expect(fieldFormatServiceMock.getDefaultInstance).toHaveBeenCalledTimes(1); + expect(fieldFormatServiceMock.getDefaultInstance).toHaveBeenCalledWith('string'); + }); + }); }); diff --git a/src/plugins/vis_types/timeseries/common/fields_utils.ts b/src/plugins/vis_types/timeseries/common/fields_utils.ts index d6987b9cdae9c0..02a62b9246d547 100644 --- a/src/plugins/vis_types/timeseries/common/fields_utils.ts +++ b/src/plugins/vis_types/timeseries/common/fields_utils.ts @@ -5,11 +5,12 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { i18n } from '@kbn/i18n'; -import { FieldSpec } from '../../../data/common'; -import { isNestedField } from '../../../data/common'; -import { FetchedIndexPattern, SanitizedFieldType } from './types'; +import { isNestedField, FieldSpec, DataView } from '../../../data/common'; import { FieldNotFoundError } from './errors'; +import type { FetchedIndexPattern, SanitizedFieldType } from './types'; +import { FieldFormat, FieldFormatsRegistry, FIELD_FORMAT_IDS } from '../../../field_formats/common'; export const extractFieldLabel = ( fields: SanitizedFieldType[], @@ -49,3 +50,63 @@ export const toSanitizedFieldType = (fields: FieldSpec[]) => type: field.type, } as SanitizedFieldType) ); + +export const getFieldsForTerms = (fields: string | Array | undefined): string[] => { + return fields ? ([fields].flat().filter(Boolean) as string[]) : []; +}; + +export const getMultiFieldLabel = (fieldForTerms: string[], fields?: SanitizedFieldType[]) => { + const firstFieldLabel = fields ? extractFieldLabel(fields, fieldForTerms[0]) : fieldForTerms[0]; + + if (fieldForTerms.length > 1) { + return i18n.translate('visTypeTimeseries.fieldUtils.multiFieldLabel', { + defaultMessage: '{firstFieldLabel} + {count} {count, plural, one {other} other {others}}', + values: { + firstFieldLabel, + count: fieldForTerms.length - 1, + }, + }); + } + return firstFieldLabel ?? ''; +}; + +export const createCachedFieldValueFormatter = ( + dataView?: DataView | null, + fields?: SanitizedFieldType[], + fieldFormatService?: FieldFormatsRegistry, + excludedFieldFormatsIds: FIELD_FORMAT_IDS[] = [] +) => { + const cache = new Map(); + + return (fieldName: string, value: string, contentType: 'text' | 'html' = 'text') => { + const cachedFormatter = cache.get(fieldName); + if (cachedFormatter) { + return cachedFormatter.convert(value, contentType); + } + + if (dataView && !excludedFieldFormatsIds.includes(dataView.fieldFormatMap?.[fieldName]?.id)) { + const field = dataView.fields.getByName(fieldName); + if (field) { + const formatter = dataView.getFormatterForField(field); + + if (formatter) { + cache.set(fieldName, formatter); + return formatter.convert(value, contentType); + } + } + } else if (fieldFormatService && fields) { + const f = fields.find((item) => item.name === fieldName); + + if (f) { + const formatter = fieldFormatService.getDefaultInstance(f.type); + + if (formatter) { + cache.set(fieldName, formatter); + return formatter.convert(value, contentType); + } + } + } + }; +}; + +export const MULTI_FIELD_VALUES_SEPARATOR = ' › '; diff --git a/src/plugins/vis_types/timeseries/common/types/index.ts b/src/plugins/vis_types/timeseries/common/types/index.ts index 01b200c6774d1a..001ea02eb355aa 100644 --- a/src/plugins/vis_types/timeseries/common/types/index.ts +++ b/src/plugins/vis_types/timeseries/common/types/index.ts @@ -7,7 +7,7 @@ */ import { Filter } from '@kbn/es-query'; -import { IndexPattern, Query } from '../../../../data/common'; +import { IndexPattern, KBN_FIELD_TYPES, Query } from '../../../../data/common'; import { Panel } from './panel_model'; export type { Metric, Series, Panel, MetricType } from './panel_model'; @@ -28,7 +28,7 @@ export interface FetchedIndexPattern { export interface SanitizedFieldType { name: string; - type: string; + type: KBN_FIELD_TYPES; label?: string; } diff --git a/src/plugins/vis_types/timeseries/common/types/panel_model.ts b/src/plugins/vis_types/timeseries/common/types/panel_model.ts index 40bd5632c3a80d..1ccf7412a3e98f 100644 --- a/src/plugins/vis_types/timeseries/common/types/panel_model.ts +++ b/src/plugins/vis_types/timeseries/common/types/panel_model.ts @@ -6,10 +6,15 @@ * Side Public License, v 1. */ -import { METRIC_TYPES, Query } from '../../../../data/common'; +import { Query, METRIC_TYPES, KBN_FIELD_TYPES } from '../../../../data/common'; import { PANEL_TYPES, TOOLTIP_MODES, TSVB_METRIC_TYPES } from '../enums'; -import { IndexPatternValue, Annotation } from './index'; -import { ColorRules, BackgroundColorRules, BarColorRules, GaugeColorRules } from './color_rules'; +import type { IndexPatternValue, Annotation } from './index'; +import type { + ColorRules, + BackgroundColorRules, + BarColorRules, + GaugeColorRules, +} from './color_rules'; interface MetricVariable { field?: string; @@ -109,7 +114,7 @@ export interface Series { steps: number; terms_direction?: string; terms_exclude?: string; - terms_field?: string; + terms_field?: string | Array; terms_include?: string; terms_order_by?: string; terms_size?: string; @@ -155,10 +160,10 @@ export interface Panel { markdown_scrollbars: number; markdown_vertical_align?: string; max_bars: number; - pivot_id?: string; + pivot_id?: string | Array; pivot_label?: string; pivot_rows?: string; - pivot_type?: string; + pivot_type?: KBN_FIELD_TYPES | Array; series: Series[]; show_grid: number; show_legend: number; diff --git a/src/plugins/vis_types/timeseries/common/types/vis_data.ts b/src/plugins/vis_types/timeseries/common/types/vis_data.ts index 07c078a6e8aaec..de507fb9ecc33e 100644 --- a/src/plugins/vis_types/timeseries/common/types/vis_data.ts +++ b/src/plugins/vis_types/timeseries/common/types/vis_data.ts @@ -46,7 +46,7 @@ export interface PanelSeries { export interface PanelData { id: string; - label: string; + label: string | string[]; labelFormatted?: string; data: PanelDataArray[]; seriesId: string; diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select.tsx deleted file mode 100644 index d5665211b7f732..00000000000000 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select.tsx +++ /dev/null @@ -1,149 +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 { i18n } from '@kbn/i18n'; -import React, { ReactNode } from 'react'; -import { - EuiComboBox, - EuiComboBoxProps, - EuiComboBoxOptionOption, - EuiFormRow, - htmlIdGenerator, -} from '@elastic/eui'; -import { getIndexPatternKey } from '../../../../common/index_patterns_utils'; -import type { SanitizedFieldType, IndexPatternValue } from '../../../../common/types'; -import type { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions'; - -import { isFieldEnabled } from '../../../../common/check_ui_restrictions'; - -interface FieldSelectProps { - label: string | ReactNode; - type: string; - fields: Record; - indexPattern: IndexPatternValue; - value?: string | null; - onChange: (options: Array>) => void; - disabled?: boolean; - restrict?: string[]; - placeholder?: string; - uiRestrictions?: TimeseriesUIRestrictions; - 'data-test-subj'?: string; -} - -const defaultPlaceholder = i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', { - defaultMessage: 'Select field...', -}); - -const isFieldTypeEnabled = (fieldRestrictions: string[], fieldType: string) => - fieldRestrictions.length ? fieldRestrictions.includes(fieldType) : true; - -const sortByLabel = (a: EuiComboBoxOptionOption, b: EuiComboBoxOptionOption) => { - const getNormalizedString = (option: EuiComboBoxOptionOption) => - (option.label || '').toLowerCase(); - - return getNormalizedString(a).localeCompare(getNormalizedString(b)); -}; - -export function FieldSelect({ - label, - type, - fields, - indexPattern = '', - value = '', - onChange, - disabled = false, - restrict = [], - placeholder = defaultPlaceholder, - uiRestrictions, - 'data-test-subj': dataTestSubj = 'metricsIndexPatternFieldsSelect', -}: FieldSelectProps) { - const htmlId = htmlIdGenerator(); - - let selectedOptions: Array> = []; - let newPlaceholder = placeholder; - const fieldsSelector = getIndexPatternKey(indexPattern); - - const groupedOptions: EuiComboBoxProps['options'] = Object.values( - (fields[fieldsSelector] || []).reduce>>( - (acc, field) => { - if (placeholder === field?.name) { - newPlaceholder = field.label ?? field.name; - } - - if ( - isFieldTypeEnabled(restrict, field.type) && - isFieldEnabled(field.name, type, uiRestrictions) - ) { - const item: EuiComboBoxOptionOption = { - value: field.name, - label: field.label ?? field.name, - }; - - const fieldTypeOptions = acc[field.type]?.options; - - if (fieldTypeOptions) { - fieldTypeOptions.push(item); - } else { - acc[field.type] = { - options: [item], - label: field.type, - }; - } - - if (value === item.value) { - selectedOptions.push(item); - } - } - - return acc; - }, - {} - ) - ); - - // sort groups - groupedOptions.sort(sortByLabel); - - // sort items - groupedOptions.forEach((group) => { - if (Array.isArray(group.options)) { - group.options.sort(sortByLabel); - } - }); - - const isInvalid = Boolean(value && fields[fieldsSelector] && !selectedOptions.length); - - if (value && !selectedOptions.length) { - selectedOptions = [{ label: value, id: 'INVALID_FIELD' }]; - } - - return ( - - - - ); -} diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select.tsx new file mode 100644 index 00000000000000..27f4d96381fda4 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select.tsx @@ -0,0 +1,185 @@ +/* + * 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 React, { useCallback, useMemo, ReactNode } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiComboBoxOptionOption, + EuiComboBoxProps, + EuiFormRow, + htmlIdGenerator, + DragDropContextProps, +} from '@elastic/eui'; + +import { FieldSelectItem } from './field_select_item'; +import { IndexPatternValue, SanitizedFieldType } from '../../../../../common/types'; +import { TimeseriesUIRestrictions } from '../../../../../common/ui_restrictions'; +import { getIndexPatternKey } from '../../../../../common/index_patterns_utils'; +import { MultiFieldSelect } from './multi_field_select'; +import { + addNewItem, + deleteItem, + swapItems, + getGroupedOptions, + findInGroupedOptions, + INVALID_FIELD_ID, + MAX_MULTI_FIELDS_ITEMS, + updateItem, +} from './field_select_utils'; + +interface FieldSelectProps { + label: string | ReactNode; + type: string; + uiRestrictions?: TimeseriesUIRestrictions; + restrict?: string[]; + value?: string | Array | null; + fields: Record; + indexPattern: IndexPatternValue; + onChange: (selectedValues: Array) => void; + disabled?: boolean; + placeholder?: string; + allowMultiSelect?: boolean; + 'data-test-subj'?: string; + fullWidth?: boolean; +} + +const getPreselectedFields = ( + placeholder?: string, + options?: Array> +) => placeholder && findInGroupedOptions(options, placeholder)?.label; + +export function FieldSelect({ + label, + fullWidth, + type, + value, + fields, + indexPattern, + uiRestrictions, + restrict, + onChange, + disabled, + placeholder, + allowMultiSelect = false, + 'data-test-subj': dataTestSubj, +}: FieldSelectProps) { + const htmlId = htmlIdGenerator(); + const fieldsSelector = getIndexPatternKey(indexPattern); + const selectedIds = useMemo(() => [value ?? null].flat(), [value]); + + const groupedOptions = useMemo( + () => getGroupedOptions(type, selectedIds, fields[fieldsSelector], uiRestrictions, restrict), + [fields, fieldsSelector, restrict, selectedIds, type, uiRestrictions] + ); + + const selectedOptionsMap = useMemo(() => { + const map = new Map['selectedOptions']>(); + if (selectedIds) { + const addIntoSet = (item: string) => { + const option = findInGroupedOptions(groupedOptions, item); + if (option) { + map.set(item, [option]); + } else { + map.set(item, [{ label: item, id: INVALID_FIELD_ID }]); + } + }; + + selectedIds.forEach((v) => v && addIntoSet(v)); + } + return map; + }, [groupedOptions, selectedIds]); + + const invalidSelectedOptions = useMemo( + () => + [...selectedOptionsMap.values()] + .flat() + .filter((item) => item?.label && item?.id === INVALID_FIELD_ID) + .map((item) => item!.label), + [selectedOptionsMap] + ); + + const onFieldSelectItemChange = useCallback( + (index: number = 0, [selectedItem]) => { + onChange(updateItem(selectedIds, selectedItem?.value, index)); + }, + [selectedIds, onChange] + ); + + const onNewItemAdd = useCallback( + (index?: number) => onChange(addNewItem(selectedIds, index)), + [selectedIds, onChange] + ); + + const onDeleteItem = useCallback( + (index?: number) => onChange(deleteItem(selectedIds, index)), + [onChange, selectedIds] + ); + + const onDragEnd: DragDropContextProps['onDragEnd'] = useCallback( + ({ source, destination }) => { + if (destination && source.index !== destination?.index) { + onChange(swapItems(selectedIds, source.index, destination.index)); + } + }, + [onChange, selectedIds] + ); + + const FieldSelectItemFactory = useMemo( + () => (props: { value?: string | null; index?: number }) => + ( + = MAX_MULTI_FIELDS_ITEMS} + disableDelete={!allowMultiSelect || selectedIds?.length <= 1} + /> + ), + [ + groupedOptions, + selectedOptionsMap, + disabled, + onNewItemAdd, + onDeleteItem, + onFieldSelectItemChange, + placeholder, + allowMultiSelect, + selectedIds?.length, + ] + ); + + return ( + + {selectedIds?.length > 1 ? ( + + ) : ( + + )} + + ); +} diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_item.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_item.tsx new file mode 100644 index 00000000000000..79ebd247fffa89 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_item.tsx @@ -0,0 +1,76 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiComboBoxProps, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; + +import { AddDeleteButtons } from '../../add_delete_buttons'; +import { INVALID_FIELD_ID } from './field_select_utils'; + +export interface FieldSelectItemProps { + onChange: (options: Array>) => void; + options: EuiComboBoxProps['options']; + selectedOptions: EuiComboBoxProps['selectedOptions']; + placeholder?: string; + disabled?: boolean; + disableAdd?: boolean; + disableDelete?: boolean; + onNewItemAdd?: () => void; + onDeleteItem?: () => void; +} + +const defaultPlaceholder = i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', { + defaultMessage: 'Select field...', +}); + +export function FieldSelectItem({ + options, + selectedOptions, + placeholder = defaultPlaceholder, + disabled, + disableAdd, + disableDelete, + + onChange, + onDeleteItem, + onNewItemAdd, +}: FieldSelectItemProps) { + const isInvalid = Boolean(selectedOptions?.find((item) => item.id === INVALID_FIELD_ID)); + + return ( + + + + + + + + + ); +} diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_utils.ts b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_utils.ts new file mode 100644 index 00000000000000..40d80a014e36b2 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/field_select_utils.ts @@ -0,0 +1,109 @@ +/* + * 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 type { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; +import { isFieldEnabled } from '../../../../../common/check_ui_restrictions'; + +import type { SanitizedFieldType } from '../../../../..//common/types'; +import type { TimeseriesUIRestrictions } from '../../../../../common/ui_restrictions'; + +export const INVALID_FIELD_ID = 'INVALID_FIELD'; +export const MAX_MULTI_FIELDS_ITEMS = 4; + +export const getGroupedOptions = ( + type: string, + selectedIds: Array, + fields: SanitizedFieldType[] = [], + uiRestrictions: TimeseriesUIRestrictions | undefined, + restrict: string[] = [] +): EuiComboBoxProps['options'] => { + const isFieldTypeEnabled = (fieldType: string) => + restrict.length ? restrict.includes(fieldType) : true; + + const sortByLabel = (a: EuiComboBoxOptionOption, b: EuiComboBoxOptionOption) => { + const getNormalizedString = (option: EuiComboBoxOptionOption) => + (option.label || '').toLowerCase(); + + return getNormalizedString(a).localeCompare(getNormalizedString(b)); + }; + + const groupedOptions: EuiComboBoxProps['options'] = Object.values( + fields.reduce>>((acc, field) => { + if (isFieldTypeEnabled(field.type) && isFieldEnabled(field.name, type, uiRestrictions)) { + const item: EuiComboBoxOptionOption = { + value: field.name, + label: field.label ?? field.name, + disabled: selectedIds.includes(field.name), + }; + + const fieldTypeOptions = acc[field.type]?.options; + + if (fieldTypeOptions) { + fieldTypeOptions.push(item); + } else { + acc[field.type] = { + options: [item], + label: field.type, + }; + } + } + + return acc; + }, {}) + ); + + // sort groups + groupedOptions.sort(sortByLabel); + + // sort items + groupedOptions.forEach((group) => { + if (Array.isArray(group.options)) { + group.options.sort(sortByLabel); + } + }); + + return groupedOptions; +}; + +export const findInGroupedOptions = ( + groupedOptions: EuiComboBoxProps['options'], + fieldName: string +) => + (groupedOptions || []) + .map((i) => i.options) + .flat() + .find((i) => i?.value === fieldName); + +export const updateItem = ( + existingItems: Array, + value: string | null = null, + index: number = 0 +) => { + const arr = [...existingItems]; + arr[index] = value; + return arr; +}; + +export const addNewItem = (existingItems: Array, insertAfter: number = 0) => { + const arr = [...existingItems]; + arr.splice(insertAfter + 1, 0, null); + return arr; +}; + +export const deleteItem = (existingItems: Array, index: number = 0) => + existingItems.filter((item, i) => i !== index); + +export const swapItems = ( + existingItems: Array, + source: number = 0, + destination: number = 0 +) => { + const arr = [...existingItems]; + arr.splice(destination, 0, arr.splice(source, 1)[0]); + return arr; +}; diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/index.ts b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/index.ts new file mode 100644 index 00000000000000..5dc0b1edaaff39 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export { FieldSelect } from './field_select'; diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/multi_field_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/multi_field_select.tsx new file mode 100644 index 00000000000000..7b96a599c8a4fa --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/field_select/multi_field_select.tsx @@ -0,0 +1,65 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { + EuiDragDropContext, + EuiDroppable, + DragDropContextProps, + EuiDraggable, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiIcon, +} from '@elastic/eui'; +import React, { FunctionComponent } from 'react'; + +const DROPPABLE_ID = 'onDragEnd'; + +const dragAriaLabel = i18n.translate('visTypeTimeseries.fieldSelect.dragAriaLabel', { + defaultMessage: 'Drag field', +}); + +export function MultiFieldSelect(props: { + values: Array; + onDragEnd: DragDropContextProps['onDragEnd']; + WrappedComponent: FunctionComponent<{ value?: string | null; index?: number }>; +}) { + return ( + + + {props.values.map((value, index) => ( + + {(provided) => ( + + + + + + + + + + + )} + + ))} + + + ); +} diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.js index 9f8285bc97e297..b24ac14717561c 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.js @@ -168,7 +168,11 @@ export const FilterRatioAgg = (props) => { restrict={getSupportedFieldsByMetricType(model.metric_agg)} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } /> ) : null} diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.test.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.test.js index 38305395bfbb6b..bebbbc6f8614f7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.test.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/filter_ratio.test.js @@ -72,6 +72,7 @@ describe('TSVB Filter Ratio', () => { label: 'number', options: [ { + disabled: false, label: 'system.cpu.user.pct', value: 'system.cpu.user.pct', }, @@ -95,6 +96,7 @@ describe('TSVB Filter Ratio', () => { "label": "date", "options": Array [ Object { + "disabled": false, "label": "@timestamp", "value": "@timestamp", }, @@ -104,6 +106,7 @@ describe('TSVB Filter Ratio', () => { "label": "number", "options": Array [ Object { + "disabled": false, "label": "system.cpu.user.pct", "value": "system.cpu.user.pct", }, diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile.js index b9512249de9454..c098eb83ddf982 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile.js @@ -90,7 +90,11 @@ export function PercentileAgg(props) { restrict={RESTRICT_FIELDS} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx index 664c59b27fa397..57dfa23c815d8e 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx @@ -45,7 +45,7 @@ interface PercentileRankAggProps { series: Series; dragHandleProps: DragHandleProps; onAdd(): void; - onChange(): void; + onChange(partialModel: Record): void; onDelete(): void; } @@ -111,7 +111,11 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => { restrict={RESTRICT_FIELDS} indexPattern={indexPattern} value={model.field ?? ''} - onChange={handleSelectChange('field')} + onChange={(value) => + props.onChange({ + field: value?.[0], + }) + } /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/positive_rate.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/positive_rate.js index 20ae5ecd24310e..35786efa98c5fa 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/positive_rate.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/positive_rate.js @@ -111,7 +111,11 @@ export const PositiveRateAgg = (props) => { restrict={[KBN_FIELD_TYPES.NUMBER]} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } uiRestrictions={props.uiRestrictions} fullWidth /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/std_agg.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/std_agg.js index 722e9021b8a60f..61579c9656d5e7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/std_agg.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/std_agg.js @@ -68,7 +68,11 @@ export function StandardAgg(props) { restrict={restrictFields} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } uiRestrictions={uiRestrictions} fullWidth /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/std_deviation.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/std_deviation.js index f9a54cb1117407..375d576f8cf285 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/std_deviation.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/std_deviation.js @@ -119,7 +119,11 @@ const StandardDeviationAggUi = (props) => { restrict={RESTRICT_FIELDS} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/top_hit.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/top_hit.js index 7fa708331ac55e..7dec7d94236e02 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/top_hit.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/top_hit.js @@ -180,7 +180,11 @@ const TopHitAggUi = (props) => { restrict={aggWithOptionsRestrictFields} indexPattern={indexPattern} value={model.field} - onChange={handleSelectChange('field')} + onChange={(value) => + handleChange({ + field: value?.[0], + }) + } /> @@ -242,7 +246,11 @@ const TopHitAggUi = (props) => { } restrict={ORDER_DATE_RESTRICT_FIELDS} value={model.order_by} - onChange={handleSelectChange('order_by')} + onChange={(value) => + handleChange({ + order_by: value?.[0], + }) + } indexPattern={indexPattern} fields={fields} data-test-subj="topHitOrderByFieldSelect" diff --git a/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx b/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx index 856948cb7601ec..562fb75089e194 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/annotation_row.tsx @@ -148,8 +148,12 @@ export const AnnotationRow = ({ /> } restrict={RESTRICT_FIELDS} - value={model.time_field} - onChange={handleChange(TIME_FIELD_KEY)} + value={model[TIME_FIELD_KEY]} + onChange={(value) => + onChange({ + [TIME_FIELD_KEY]: value?.[0] ?? undefined, + }) + } indexPattern={model.index_pattern} fields={fields} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/index_pattern.js b/src/plugins/vis_types/timeseries/public/application/components/index_pattern.js index 217b3948e1cd83..7b3ae5f3e16ef7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/index_pattern.js +++ b/src/plugins/vis_types/timeseries/public/application/components/index_pattern.js @@ -259,7 +259,11 @@ export const IndexPattern = ({ restrict={RESTRICT_FIELDS} value={model[timeFieldName]} disabled={disabled} - onChange={handleSelectChange(timeFieldName)} + onChange={(value) => + onChange({ + [timeFieldName]: value?.[0], + }) + } indexPattern={model[indexPatternName]} fields={fields} placeholder={ diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/check_if_numeric_metric.test.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/check_if_numeric_metric.test.ts index eb6ea561fec840..2eaee960991109 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/check_if_numeric_metric.test.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/check_if_numeric_metric.test.ts @@ -11,6 +11,7 @@ import { TSVB_METRIC_TYPES } from '../../../../common/enums'; import { checkIfNumericMetric } from './check_if_numeric_metric'; import type { Metric } from '../../../../common/types'; +import type { VisFields } from '../../lib/fetch_fields'; describe('checkIfNumericMetric(metric, fields, indexPattern)', () => { const indexPattern = { id: 'some_id' }; @@ -20,7 +21,7 @@ describe('checkIfNumericMetric(metric, fields, indexPattern)', () => { { name: 'string field', type: 'string' }, { name: 'date field', type: 'date' }, ], - }; + } as VisFields; it('should return true for Count metric', () => { const metric = { type: METRIC_TYPES.COUNT } as Metric; diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts index 15151a9e21bc5a..08ee275d144ea3 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts @@ -201,11 +201,11 @@ describe('convert series to datatables', () => { expect(tables.series1.rows.length).toEqual(8); const expected1 = series[0].data.map((d) => { - d.push(parseInt(series[0].label, 10)); + d.push(parseInt([series[0].label].flat()[0], 10)); return d; }); const expected2 = series[1].data.map((d) => { - d.push(parseInt(series[1].label, 10)); + d.push(parseInt([series[1].label].flat()[0], 10)); return d; }); expect(tables.series1.rows).toEqual([...expected1, ...expected2]); diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts index 8e7c1694357c8f..62397e3b1d8c2b 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts @@ -10,6 +10,7 @@ import { DatatableRow, DatatableColumn, DatatableColumnType } from 'src/plugins/ import { Query } from 'src/plugins/data/common'; import { TimeseriesVisParams } from '../../../types'; import type { PanelData, Metric } from '../../../../common/types'; +import { getMultiFieldLabel, getFieldsForTerms } from '../../../../common/fields_utils'; import { BUCKET_TYPES, TSVB_METRIC_TYPES } from '../../../../common/enums'; import { fetchIndexPattern } from '../../../../common/index_patterns_utils'; import { getDataStart } from '../../../services'; @@ -131,7 +132,7 @@ export const convertSeriesToDataTable = async ( id++; columns.push({ id, - name: layer.terms_field || '', + name: getMultiFieldLabel(getFieldsForTerms(layer.terms_field)), isMetric: false, type: BUCKET_TYPES.TERMS, }); @@ -154,7 +155,7 @@ export const convertSeriesToDataTable = async ( const row: DatatableRow = [rowData[0], rowData[1]]; // If the layer is split by terms aggregation, the data array should also contain the split value. if (isGroupedByTerms || filtersColumn) { - row.push(seriesPerLayer[j].label); + row.push([seriesPerLayer[j].label].flat()[0]); } return row; }); diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_vars.js b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_vars.js index 867ba673cf1dd9..34efcf678d7a66 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_vars.js +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_vars.js @@ -16,6 +16,7 @@ import { getMetricsField } from './get_metrics_field'; import { createFieldFormatter } from './create_field_formatter'; import { labelDateFormatter } from './label_date_formatter'; import moment from 'moment'; +import { getFieldsForTerms } from '../../../../common/fields_utils'; export const convertSeriesToVars = (series, model, getConfig = null, fieldFormatMap) => { const variables = {}; @@ -50,10 +51,16 @@ export const convertSeriesToVars = (series, model, getConfig = null, fieldFormat }), }, }; - const rowLabel = - seriesModel.split_mode === BUCKET_TYPES.TERMS - ? createFieldFormatter(seriesModel.terms_field, fieldFormatMap)(row.label) - : row.label; + + let rowLabel = row.label; + if (seriesModel.split_mode === BUCKET_TYPES.TERMS) { + const fieldsForTerms = getFieldsForTerms(seriesModel.terms_field); + + if (fieldsForTerms.length === 1) { + rowLabel = createFieldFormatter(fieldsForTerms[0], fieldFormatMap)(row.label); + } + } + set(variables, varName, data); set(variables, `${label}.label`, rowLabel); diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx index 57ae699d281a01..cefcd9c2e54219 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx @@ -23,7 +23,6 @@ import { EuiHorizontalRule, EuiCode, EuiText, - EuiComboBoxOptionOption, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -65,16 +64,27 @@ export class TablePanelConfig extends Component< this.setState({ selectedTab }); } - handlePivotChange = (selectedOption: Array>) => { + handlePivotChange = (selectedOptions: Array) => { const { fields, model } = this.props; - const pivotId = get(selectedOption, '[0].value', null); - const field = fields[getIndexPatternKey(model.index_pattern)].find((f) => f.name === pivotId); - const pivotType = get(field, 'type', model.pivot_type); - this.props.onChange({ - pivot_id: pivotId, - pivot_type: pivotType, - }); + const getPivotType = (fieldName?: string | null): KBN_FIELD_TYPES | null => { + const field = fields[getIndexPatternKey(model.index_pattern)].find( + (f) => f.name === fieldName + ); + return get(field, 'type', null); + }; + + this.props.onChange( + selectedOptions.length === 1 + ? { + pivot_id: selectedOptions[0] || undefined, + pivot_type: getPivotType(selectedOptions[0]) || undefined, + } + : { + pivot_id: selectedOptions, + pivot_type: selectedOptions.map((item) => getPivotType(item)), + } + ); }; handleTextChange = @@ -129,6 +139,8 @@ export class TablePanelConfig extends Component< onChange={this.handlePivotChange} uiRestrictions={this.context.uiRestrictions} type={BUCKET_TYPES.TERMS} + allowMultiSelect={true} + fullWidth={true} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap b/src/plugins/vis_types/timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap index 524e35f9d29e1b..b7c5095535fbc4 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap @@ -20,13 +20,14 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js } labelType="label" > - ({ - ...field, - disabled: !isGroupByFieldsEnabled(field.value, uiRestrictions), - })); - - const selectedValue = props.value || 'everything'; - const selectedOption = modeOptions.find((option) => { - return selectedValue === option.value; - }); - - return ( - - ); -} - -GroupBySelectUi.propTypes = { - onChange: PropTypes.func, - value: PropTypes.string, - uiRestrictions: PropTypes.object, -}; - -export const GroupBySelect = injectI18n(GroupBySelectUi); diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/group_by_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/splits/group_by_select.tsx new file mode 100644 index 00000000000000..9c0e26b642f8b4 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/group_by_select.tsx @@ -0,0 +1,75 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import React from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; +import { isGroupByFieldsEnabled } from '../../../../common/check_ui_restrictions'; +import type { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions'; + +interface GroupBySelectProps { + id: string; + onChange: EuiComboBoxProps['onChange']; + value?: string; + uiRestrictions: TimeseriesUIRestrictions; +} + +const getAvailableOptions = () => [ + { + label: i18n.translate('visTypeTimeseries.splits.groupBySelect.modeOptions.everythingLabel', { + defaultMessage: 'Everything', + }), + value: 'everything', + }, + { + label: i18n.translate('visTypeTimeseries.splits.groupBySelect.modeOptions.filterLabel', { + defaultMessage: 'Filter', + }), + value: 'filter', + }, + { + label: i18n.translate('visTypeTimeseries.splits.groupBySelect.modeOptions.filtersLabel', { + defaultMessage: 'Filters', + }), + value: 'filters', + }, + { + label: i18n.translate('visTypeTimeseries.splits.groupBySelect.modeOptions.termsLabel', { + defaultMessage: 'Terms', + }), + value: 'terms', + }, +]; + +export const GroupBySelect = ({ + id, + onChange, + value = 'everything', + uiRestrictions, +}: GroupBySelectProps) => { + const modeOptions = getAvailableOptions().map((field) => ({ + ...field, + disabled: !isGroupByFieldsEnabled(field.value, uiRestrictions), + })); + + const selectedOption: EuiComboBoxOptionOption | undefined = modeOptions.find( + (option) => value === option.value + ); + + return ( + + ); +}; diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js b/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js index 80810f552d3a19..4810932c9b4ac9 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js @@ -7,7 +7,7 @@ */ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useCallback } from 'react'; import { get, find } from 'lodash'; import { GroupBySelect } from './group_by_select'; import { createTextHandler } from '../lib/create_text_handler'; @@ -91,6 +91,15 @@ export const SplitByTermsUI = ({ const selectedField = find(fields[fieldsSelector], ({ name }) => name === model.terms_field); const selectedFieldType = get(selectedField, 'type'); + const onTermsFieldChange = useCallback( + (selectedOptions) => { + onChange({ + terms_field: selectedOptions.length === 1 ? selectedOptions[0] : selectedOptions, + }); + }, + [onChange] + ); + if ( seriesQuantity && model.stacked === STACKED_OPTIONS.PERCENT && @@ -142,11 +151,12 @@ export const SplitByTermsUI = ({ ]} data-test-subj="groupByField" indexPattern={indexPattern} - onChange={handleSelectChange('terms_field')} + onChange={onTermsFieldChange} value={model.terms_field} fields={fields} uiRestrictions={uiRestrictions} type={'terms'} + allowMultiSelect={true} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx index ae699880784a9a..7787f0f6929b25 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx @@ -190,6 +190,7 @@ function TimeseriesVisualization({ onUiState={handleUiState} syncColors={syncColors} palettesService={palettesService} + indexPattern={indexPattern} fieldFormatMap={indexPattern?.fieldFormatMap} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts b/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts index 653b2985ed1aeb..512a9d1ff9169d 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts @@ -15,6 +15,7 @@ import { PaletteRegistry } from 'src/plugins/charts/public'; import { TimeseriesVisParams } from '../../../types'; import type { TimeseriesVisData, PanelData } from '../../../../common/types'; import type { FieldFormatMap } from '../../../../../../data/common'; +import { FetchedIndexPattern } from '../../../../common/types'; /** * Lazy load each visualization type, since the only one is presented on the screen at the same time. @@ -62,5 +63,7 @@ export interface TimeseriesVisProps { getConfig: IUiSettingsClient['get']; syncColors: boolean; palettesService: PaletteRegistry; + indexPattern?: FetchedIndexPattern['indexPattern']; + /** @deprecated please use indexPattern.fieldFormatMap instead **/ fieldFormatMap?: FieldFormatMap; } diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js index f62120ed5f3ee7..f3cb92b31b3093 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js @@ -221,7 +221,11 @@ export class TableSeriesConfig extends Component { fields={this.props.fields} indexPattern={this.props.panel.index_pattern} value={model.aggregate_by} - onChange={handleSelectChange('aggregate_by')} + onChange={(value) => + this.props.onChange({ + aggregate_by: value?.[0], + }) + } fullWidth restrict={[ KBN_FIELD_TYPES.NUMBER, diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/vis.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/vis.js index 3e828a1b833bf0..549aa1b70082f8 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/vis.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/vis.js @@ -18,11 +18,17 @@ import { isSortable } from './is_sortable'; import { EuiToolTip, EuiIcon } from '@elastic/eui'; import { replaceVars } from '../../lib/replace_vars'; import { ExternalUrlErrorModal } from '../../lib/external_url_error_modal'; -import { FIELD_FORMAT_IDS } from '../../../../../../../../plugins/field_formats/common'; import { FormattedMessage } from '@kbn/i18n-react'; import { getFieldFormats, getCoreStart } from '../../../../services'; import { DATA_FORMATTERS } from '../../../../../common/enums'; -import { getValueOrEmpty } from '../../../../../common/empty_label'; +import { FIELD_FORMAT_IDS } from '../../../../../../../../plugins/field_formats/common'; + +import { + createCachedFieldValueFormatter, + getFieldsForTerms, + getMultiFieldLabel, + MULTI_FIELD_VALUES_SEPARATOR, +} from '../../../../../common/fields_utils'; function getColor(rules, colorKey, value) { let color; @@ -49,12 +55,7 @@ function sanitizeUrl(url) { class TableVis extends Component { constructor(props) { super(props); - - const fieldFormatsService = getFieldFormats(); - const DateFormat = fieldFormatsService.getType(FIELD_FORMAT_IDS.DATE); - - this.dateFormatter = new DateFormat({}, this.props.getConfig); - + this.fieldFormatsService = getFieldFormats(); this.state = { accessDeniedDrilldownUrl: null, }; @@ -74,17 +75,21 @@ class TableVis extends Component { } }; - renderRow = (row) => { + renderRow = (row, pivotIds, fieldValuesFormatter) => { const { model, fieldFormatMap, getConfig } = this.props; - let rowDisplay = getValueOrEmpty( - model.pivot_type === 'date' ? this.dateFormatter.convert(row.key) : row.key - ); + let rowDisplay = row.key; + + if (pivotIds.length) { + rowDisplay = pivotIds + .map((item, index) => { + const value = [row.key ?? null].flat()[index]; + const formatted = fieldValuesFormatter(item, value, 'html'); - // we should skip url field formatting for key if tsvb have drilldown_url - if (fieldFormatMap?.[model.pivot_id]?.id !== FIELD_FORMAT_IDS.URL || !model.drilldown_url) { - const formatter = createFieldFormatter(model?.pivot_id, fieldFormatMap, 'html'); - rowDisplay = ; // eslint-disable-line react/no-danger + // eslint-disable-next-line react/no-danger + return ; + }) + .reduce((prev, curr) => [prev, MULTI_FIELD_VALUES_SEPARATOR, curr]); } if (model.drilldown_url) { @@ -150,7 +155,7 @@ class TableVis extends Component { ); }; - renderHeader() { + renderHeader(pivotIds) { const { model, uiState, onUiState, visData } = this.props; const stateKey = `${model.type}.sort`; const sort = uiState.get(stateKey, { @@ -210,7 +215,7 @@ class TableVis extends Component { ); }); - const label = visData.pivot_label || model.pivot_label || model.pivot_id; + const label = visData.pivot_label || model.pivot_label || getMultiFieldLabel(pivotIds); let sortIcon; if (sort.column === '_default_') { sortIcon = sort.order === 'asc' ? 'sortUp' : 'sortDown'; @@ -240,13 +245,26 @@ class TableVis extends Component { closeExternalUrlErrorModal = () => this.setState({ accessDeniedDrilldownUrl: null }); render() { - const { visData } = this.props; + const { visData, model, indexPattern } = this.props; const { accessDeniedDrilldownUrl } = this.state; - const header = this.renderHeader(); + const fields = (model.pivot_type ? [model.pivot_type ?? null].flat() : []).map( + (type, index) => ({ + name: [model.pivot_id ?? null].flat()[index], + type, + }) + ); + const fieldValuesFormatter = createCachedFieldValueFormatter( + indexPattern, + fields, + this.fieldFormatsService, + model.drilldown_url ? [FIELD_FORMAT_IDS.URL] : [] + ); + const pivotIds = getFieldsForTerms(model.pivot_id); + const header = this.renderHeader(pivotIds); let rows = null; if (isArray(visData.series) && visData.series.length) { - rows = visData.series.map(this.renderRow); + rows = visData.series.map((item) => this.renderRow(item, pivotIds, fieldValuesFormatter)); } return ( @@ -285,6 +303,7 @@ TableVis.propTypes = { uiState: PropTypes.object, pageNumber: PropTypes.number, getConfig: PropTypes.func, + indexPattern: PropTypes.object, }; // default export required for React.Lazy diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/index.ts b/src/plugins/vis_types/timeseries/public/trigger_action/index.ts index d3329bee803a1c..8e757b98c125d3 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/index.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/index.ts @@ -16,6 +16,7 @@ import { getDataSourceInfo } from './get_datasource_info'; import { getFieldType } from './get_field_type'; import { getSeries } from './get_series'; import { getYExtents } from './get_extents'; +import { getFieldsForTerms } from '../../common/fields_utils'; const SUPPORTED_FORMATTERS = ['bytes', 'percent', 'number']; @@ -99,13 +100,21 @@ export const triggerTSVBtoLensConfiguration = async ( } const palette = layer.palette as PaletteOutput; + const splitFields = getFieldsForTerms(layer.terms_field); // in case of terms in a date field, we want to apply the date_histogram let splitWithDateHistogram = false; - if (layer.terms_field && layer.split_mode === 'terms') { - const fieldType = await getFieldType(indexPatternId, layer.terms_field); - if (fieldType === 'date') { - splitWithDateHistogram = true; + if (layer.terms_field && layer.split_mode === 'terms' && splitFields) { + for (const f of splitFields) { + const fieldType = await getFieldType(indexPatternId, f); + + if (fieldType === 'date') { + if (splitFields.length === 1) { + splitWithDateHistogram = true; + } else { + return null; + } + } } } @@ -114,7 +123,7 @@ export const triggerTSVBtoLensConfiguration = async ( timeFieldName: timeField, chartType, axisPosition: layer.separate_axis ? layer.axis_position : model.axis_position, - ...(layer.terms_field && { splitField: layer.terms_field }), + ...(layer.terms_field && { splitFields }), splitWithDateHistogram, ...(layer.split_mode !== 'everything' && { splitMode: layer.split_mode }), ...(splitFilters.length > 0 && { splitFilters }), diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts index 2b63749fac6427..9f8bf18683ca5b 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_table_data.ts @@ -14,7 +14,7 @@ import { handleErrorResponse } from './handle_error_response'; import { processBucket } from './table/process_bucket'; import { createFieldsFetcher } from '../search_strategies/lib/fields_fetcher'; -import { extractFieldLabel } from '../../../common/fields_utils'; +import { getFieldsForTerms, getMultiFieldLabel } from '../../../common/fields_utils'; import { isAggSupported } from './helpers/check_aggs'; import { isConfigurationFeatureEnabled } from '../../../common/check_ui_restrictions'; import { FilterCannotBeAppliedError, PivotNotSelectedForTableError } from '../../../common/errors'; @@ -62,12 +62,15 @@ export async function getTableData( }); const calculatePivotLabel = async () => { - if (panel.pivot_id && panelIndex.indexPattern?.id) { - const fields = await extractFields({ id: panelIndex.indexPattern.id }); + const pivotIds = getFieldsForTerms(panel.pivot_id); - return extractFieldLabel(fields, panel.pivot_id); + if (pivotIds.length) { + const fields = panelIndex.indexPattern?.id + ? await extractFields({ id: panelIndex.indexPattern.id }) + : []; + + return getMultiFieldLabel(pivotIds, fields); } - return panel.pivot_id; }; const meta: DataResponseMeta = { @@ -85,7 +88,7 @@ export async function getTableData( } }); - if (!panel.pivot_id) { + if (!getFieldsForTerms(panel.pivot_id).length) { throw new PivotNotSelectedForTableError(); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/helpers/get_splits.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/helpers/get_splits.ts index 1754fa6569dcd9..a28883b72980b2 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/helpers/get_splits.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/helpers/get_splits.ts @@ -54,7 +54,7 @@ export async function getSplits { expect(doc.aggs.test.meta).toMatchInlineSnapshot(` Object { - "index": undefined, + "dataViewId": undefined, + "indexPatternString": undefined, "intervalString": "900000ms", "panelId": "panelId", "seriesId": "test", diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_everything.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_everything.js index 497b0106deec47..6cefb08c23686f 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_everything.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_everything.js @@ -7,12 +7,13 @@ */ import { overwrite } from '../../helpers'; +import { getFieldsForTerms } from '../../../../../common/fields_utils'; export function splitByEverything(req, panel, series) { return (next) => (doc) => { if ( series.split_mode === 'everything' || - (series.split_mode === 'terms' && !series.terms_field) + (series.split_mode === 'terms' && !getFieldsForTerms(series.terms_field).length) ) { overwrite(doc, `aggs.${series.id}.filter.match_all`, {}); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js index 9c2bdbe03f8866..07e8ef4a0e5fde 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js @@ -10,25 +10,41 @@ import { overwrite } from '../../helpers'; import { basicAggs } from '../../../../../common/basic_aggs'; import { getBucketsPath } from '../../helpers/get_buckets_path'; import { bucketTransform } from '../../helpers/bucket_transform'; -import { validateField } from '../../../../../common/fields_utils'; +import { getFieldsForTerms, validateField } from '../../../../../common/fields_utils'; export function splitByTerms(req, panel, series, esQueryConfig, seriesIndex) { return (next) => (doc) => { - if (series.split_mode === 'terms' && series.terms_field) { - const termsField = series.terms_field; + const termsIds = getFieldsForTerms(series.terms_field); + + if (series.split_mode === 'terms' && termsIds.length) { + const termsType = termsIds.length > 1 ? 'multi_terms' : 'terms'; const orderByTerms = series.terms_order_by; - validateField(termsField, seriesIndex); + termsIds.forEach((termsField) => { + validateField(termsField, seriesIndex); + }); const direction = series.terms_direction || 'desc'; const metric = series.metrics.find((item) => item.id === orderByTerms); - overwrite(doc, `aggs.${series.id}.terms.field`, termsField); - overwrite(doc, `aggs.${series.id}.terms.size`, series.terms_size); + + if (termsType === 'multi_terms') { + overwrite( + doc, + `aggs.${series.id}.${termsType}.terms`, + termsIds.map((item) => ({ + field: item, + })) + ); + } else { + overwrite(doc, `aggs.${series.id}.${termsType}.field`, termsIds[0]); + } + + overwrite(doc, `aggs.${series.id}.${termsType}.size`, series.terms_size); if (series.terms_include) { - overwrite(doc, `aggs.${series.id}.terms.include`, series.terms_include); + overwrite(doc, `aggs.${series.id}.${termsType}.include`, series.terms_include); } if (series.terms_exclude) { - overwrite(doc, `aggs.${series.id}.terms.exclude`, series.terms_exclude); + overwrite(doc, `aggs.${series.id}.${termsType}.exclude`, series.terms_exclude); } if (metric && metric.type !== 'count' && ~basicAggs.indexOf(metric.type)) { const sortAggKey = `${orderByTerms}-SORT`; @@ -37,12 +53,12 @@ export function splitByTerms(req, panel, series, esQueryConfig, seriesIndex) { orderByTerms, sortAggKey ); - overwrite(doc, `aggs.${series.id}.terms.order`, { [bucketPath]: direction }); + overwrite(doc, `aggs.${series.id}.${termsType}.order`, { [bucketPath]: direction }); overwrite(doc, `aggs.${series.id}.aggs`, { [sortAggKey]: fn(metric) }); } else if (['_key', '_count'].includes(orderByTerms)) { - overwrite(doc, `aggs.${series.id}.terms.order`, { [orderByTerms]: direction }); + overwrite(doc, `aggs.${series.id}.${termsType}.order`, { [orderByTerms]: direction }); } else { - overwrite(doc, `aggs.${series.id}.terms.order`, { _count: direction }); + overwrite(doc, `aggs.${series.id}.${termsType}.order`, { _count: direction }); } } return next(doc); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/date_histogram.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/date_histogram.ts index a458c870be7d9a..246c133e936085 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/date_histogram.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/date_histogram.ts @@ -24,7 +24,8 @@ export const dateHistogram: TableRequestProcessorsFunction = const meta: TableSearchRequestMeta = { timeField, - index: panel.use_kibana_indexes ? seriesIndex.indexPattern?.id : undefined, + dataViewId: panel.use_kibana_indexes ? seriesIndex.indexPattern?.id : undefined, + indexPatternString: seriesIndex.indexPatternString, panelId: panel.id, }; diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/pivot.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/pivot.ts index 692d4ea23bc596..4c28cfb442e144 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/pivot.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/pivot.ts @@ -8,7 +8,7 @@ import { get, last } from 'lodash'; import { overwrite, getBucketsPath, bucketTransform } from '../../helpers'; - +import { getFieldsForTerms } from '../../../../../common/fields_utils'; import { basicAggs } from '../../../../../common/basic_aggs'; import type { TableRequestProcessorsFunction } from './types'; @@ -18,15 +18,29 @@ export const pivot: TableRequestProcessorsFunction = (next) => (doc) => { const { sort } = req.body.state; + const pivotIds = getFieldsForTerms(panel.pivot_id); + const termsType = pivotIds.length > 1 ? 'multi_terms' : 'terms'; + + if (pivotIds.length) { + if (termsType === 'multi_terms') { + overwrite( + doc, + `aggs.pivot.${termsType}.terms`, + pivotIds.map((item: string) => ({ + field: item, + })) + ); + } else { + overwrite(doc, `aggs.pivot.${termsType}.field`, pivotIds[0]); + } + + overwrite(doc, `aggs.pivot.${termsType}.size`, panel.pivot_rows); - if (panel.pivot_id) { - overwrite(doc, 'aggs.pivot.terms.field', panel.pivot_id); - overwrite(doc, 'aggs.pivot.terms.size', panel.pivot_rows); if (sort) { const series = panel.series.find((item) => item.id === sort.column); const metric = series && last(series.metrics); if (metric && metric.type === 'count') { - overwrite(doc, 'aggs.pivot.terms.order', { _count: sort.order }); + overwrite(doc, `aggs.pivot.${termsType}.order`, { _count: sort.order }); } else if (metric && series && basicAggs.includes(metric.type)) { const sortAggKey = `${metric.id}-SORT`; const fn = bucketTransform[metric.type]; @@ -34,10 +48,10 @@ export const pivot: TableRequestProcessorsFunction = metric.id, sortAggKey ); - overwrite(doc, `aggs.pivot.terms.order`, { [bucketPath]: sort.order }); + overwrite(doc, `aggs.pivot.${termsType}.order`, { [bucketPath]: sort.order }); overwrite(doc, `aggs.pivot.aggs`, { [sortAggKey]: fn(metric) }); } else { - overwrite(doc, 'aggs.pivot.terms.order', { + overwrite(doc, `aggs.pivot.${termsType}.order`, { _key: get(sort, 'order', 'asc'), }); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/types.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/types.ts index 58124c825e9166..2c6aa2a495766e 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/types.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/types.ts @@ -7,5 +7,6 @@ */ export interface BaseMeta { - index?: string; + dataViewId?: string; + indexPatternString?: string; } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/format_label.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/format_label.ts index 6d824c1c7f43ed..813cf1a5b9a6fa 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/format_label.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/format_label.ts @@ -6,46 +6,67 @@ * Side Public License, v 1. */ -import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { BUCKET_TYPES, PANEL_TYPES } from '../../../../../common/enums'; +import { BUCKET_TYPES, PANEL_TYPES, TSVB_METRIC_TYPES } from '../../../../../common/enums'; +import { + createCachedFieldValueFormatter, + getFieldsForTerms, + MULTI_FIELD_VALUES_SEPARATOR, +} from '../../../../../common/fields_utils'; import type { Panel, PanelData, Series } from '../../../../../common/types'; import type { FieldFormatsRegistry } from '../../../../../../../field_formats/common'; import type { createFieldsFetcher } from '../../../search_strategies/lib/fields_fetcher'; import type { CachedIndexPatternFetcher } from '../../../search_strategies/lib/cached_index_pattern_fetcher'; +import type { BaseMeta } from '../../request_processors/types'; +import { SanitizedFieldType } from '../../../../../common/types'; export function formatLabel( resp: unknown, panel: Panel, series: Series, - meta: any, + meta: BaseMeta, extractFields: ReturnType, fieldFormatService: FieldFormatsRegistry, cachedIndexPatternFetcher: CachedIndexPatternFetcher ) { return (next: (results: PanelData[]) => unknown) => async (results: PanelData[]) => { const { terms_field: termsField, split_mode: splitMode } = series; + const termsIds = getFieldsForTerms(termsField); - const isKibanaIndexPattern = panel.use_kibana_indexes || panel.index_pattern === ''; - // no need to format labels for markdown as they also used there as variables keys const shouldFormatLabels = - isKibanaIndexPattern && - termsField && + // no need to format labels for series_agg + !series.metrics.some((m) => m.type === TSVB_METRIC_TYPES.SERIES_AGG) && + termsIds.length && splitMode === BUCKET_TYPES.TERMS && + // no need to format labels for markdown as they also used there as variables keys panel.type !== PANEL_TYPES.MARKDOWN; if (shouldFormatLabels) { - const { indexPattern } = await cachedIndexPatternFetcher({ id: meta.index }); - const getFieldFormatByName = (fieldName: string) => - fieldFormatService.deserialize(indexPattern?.fieldFormatMap?.[fieldName]); + const fetchedIndex = meta.dataViewId + ? await cachedIndexPatternFetcher({ id: meta.dataViewId }) + : undefined; + + let fields: SanitizedFieldType[] = []; + + if (!fetchedIndex?.indexPattern && meta.indexPatternString) { + fields = await extractFields(meta.indexPatternString); + } + + const formatField = createCachedFieldValueFormatter( + fetchedIndex?.indexPattern, + fields, + fieldFormatService + ); results .filter(({ seriesId }) => series.id === seriesId) .forEach((item) => { - const formattedLabel = getFieldFormatByName(termsField!).convert(item.label); - item.label = formattedLabel; - const termsFieldType = indexPattern?.fields.find(({ name }) => name === termsField)?.type; - if (termsFieldType === KBN_FIELD_TYPES.DATE) { - item.labelFormatted = formattedLabel; + const formatted = termsIds + .map((i, index) => formatField(i, [item.label].flat()[index])) + .join(MULTI_FIELD_VALUES_SEPARATOR); + + if (formatted) { + item.label = formatted; + item.labelFormatted = formatted; } }); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/series_agg.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/series_agg.js index 532f5fd07f597d..305d6c6fc5b34c 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/series_agg.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/series_agg.js @@ -33,7 +33,7 @@ export function seriesAgg(resp, panel, series, meta, extractFields) { return (fn && fn(acc)) || acc; }, targetSeries); - const fieldsForSeries = meta.index ? await extractFields({ id: meta.index }) : []; + const fieldsForSeries = meta.dataViewId ? await extractFields({ id: meta.dataViewId }) : []; results.push({ id: `${series.id}`, diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/table/series_agg.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/table/series_agg.ts index b4bc082bab849a..45829a930605fd 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/table/series_agg.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/table/series_agg.ts @@ -36,7 +36,7 @@ export const seriesAgg: TableResponseProcessorsFunction = const fn = SeriesAgg[series.aggregate_function]; const data = fn(targetSeries); - const fieldsForSeries = meta.index ? await extractFields({ id: meta.index }) : []; + const fieldsForSeries = meta.dataViewId ? await extractFields({ id: meta.dataViewId }) : []; results.push({ id: `${series.id}`, diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx index efc3bbf8314f8a..3d3c98ce4aaeae 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx @@ -39,7 +39,7 @@ import { ExpressionAstExpression, } from '../../../../plugins/expressions/public'; import { Vis, SerializedVis } from '../vis'; -import { getExpressions, getTheme, getUiActions } from '../services'; +import { getExecutionContext, getExpressions, getTheme, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { getSavedVisualization } from '../utils/saved_visualize_utils'; @@ -398,20 +398,18 @@ export class VisualizeEmbeddable }; private async updateHandler() { - const parentContext = this.parent?.getInput().executionContext; + const parentContext = this.parent?.getInput().executionContext || getExecutionContext().get(); const child: KibanaExecutionContext = { type: 'visualization', name: this.vis.type.name, - id: this.vis.id ?? 'an_unsaved_vis', + id: this.vis.id ?? 'new', description: this.vis.title || this.input.title || this.vis.type.name, url: this.output.editUrl, }; - const context = parentContext - ? { - ...parentContext, - child, - } - : child; + const context = { + ...parentContext, + child, + }; const expressionParams: IExpressionLoaderParams = { searchContext: { diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 92bcf1dfe6a964..88b9d35d5255f9 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -36,6 +36,7 @@ import { setDocLinks, setSpaces, setTheme, + setExecutionContext, } from './services'; import { createVisEmbeddableFromObject, @@ -372,6 +373,7 @@ export class VisualizationsPlugin setTimeFilter(data.query.timefilter.timefilter); setAggs(data.search.aggs); setOverlays(core.overlays); + setExecutionContext(core.executionContext); setChrome(core.chrome); if (spaces) { diff --git a/src/plugins/visualizations/public/services.ts b/src/plugins/visualizations/public/services.ts index 37aea45fa3f589..8564c8225f1a79 100644 --- a/src/plugins/visualizations/public/services.ts +++ b/src/plugins/visualizations/public/services.ts @@ -16,6 +16,7 @@ import type { SavedObjectsStart, DocLinksStart, ThemeServiceStart, + ExecutionContextSetup, } from '../../../core/public'; import type { TypesStart } from './vis_types'; import { createGetterSetter } from '../../../plugins/kibana_utils/public'; @@ -65,4 +66,7 @@ export const [getOverlays, setOverlays] = createGetterSetter('Over export const [getChrome, setChrome] = createGetterSetter('Chrome'); +export const [getExecutionContext, setExecutionContext] = + createGetterSetter('ExecutionContext'); + export const [getSpaces, setSpaces] = createGetterSetter('Spaces', false); diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index b89af7bd2cdbf6..60332c0f66964b 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -98,7 +98,7 @@ export interface VisualizeEditorLayersContext { chartType?: string; axisPosition?: string; termsParams?: Record; - splitField?: string; + splitFields?: string[]; splitMode?: string; splitFilters?: SplitByFilters[]; palette?: PaletteOutput; diff --git a/src/plugins/visualizations/public/visualize_app/components/visualize_editor.tsx b/src/plugins/visualizations/public/visualize_app/components/visualize_editor.tsx index 45241ec501084c..c281b211768a10 100644 --- a/src/plugins/visualizations/public/visualize_app/components/visualize_editor.tsx +++ b/src/plugins/visualizations/public/visualize_app/components/visualize_editor.tsx @@ -11,7 +11,7 @@ import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { EventEmitter } from 'events'; -import { useKibana } from '../../../../kibana_react/public'; +import { useExecutionContext, useKibana } from '../../../../kibana_react/public'; import { useChromeVisibility, useSavedVisInstance, @@ -41,6 +41,14 @@ export const VisualizeEditor = ({ onAppLeave }: VisualizeAppProps) => { originatingApp, visualizationIdFromUrl ); + + const editorName = savedVisInstance?.vis.type.title.toLowerCase().replace(' ', '_') || ''; + useExecutionContext(services.executionContext, { + type: 'application', + page: `editor${editorName ? `:${editorName}` : ''}`, + id: visualizationIdFromUrl || 'new', + }); + const { appState, hasUnappliedChanges } = useVisualizeAppState( services, eventEmitter, diff --git a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx index cf219b1cda117d..a180cf78feeb2e 100644 --- a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx +++ b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx @@ -21,7 +21,7 @@ import { findListItems } from '../../utils/saved_visualize_utils'; import { showNewVisModal } from '../../wizard'; import { getTypes } from '../../services'; import { SavedObjectsFindOptionsReference } from '../../../../../core/public'; -import { useKibana, TableListView } from '../../../../kibana_react/public'; +import { useKibana, TableListView, useExecutionContext } from '../../../../kibana_react/public'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; import { VisualizeServices } from '../types'; import { VisualizeConstants } from '../../../common/constants'; @@ -31,6 +31,7 @@ export const VisualizeListing = () => { const { services: { application, + executionContext, chrome, history, toastNotifications, @@ -49,6 +50,11 @@ export const VisualizeListing = () => { const closeNewVisModal = useRef(() => {}); const listingLimit = savedObjectsPublic.settings.getListingLimit(); + useExecutionContext(executionContext, { + type: 'application', + page: 'list', + }); + useEffect(() => { if (pathname === '/new') { // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately diff --git a/test/api_integration/apis/custom_integration/integrations.ts b/test/api_integration/apis/custom_integration/integrations.ts index 4d3915f5f22946..c49aefe91925f8 100644 --- a/test/api_integration/apis/custom_integration/integrations.ts +++ b/test/api_integration/apis/custom_integration/integrations.ts @@ -22,7 +22,7 @@ export default function ({ getService }: FtrProviderContext) { expect(resp.body).to.be.an('array'); - expect(resp.body.length).to.be(35); + expect(resp.body.length).to.be(36); // Test for sample data card expect(resp.body.findIndex((c: { id: string }) => c.id === 'sample_data_all')).to.be.above( diff --git a/test/common/services/security/test_user.ts b/test/common/services/security/test_user.ts index 1161e7b493f419..7c4751220fa1f1 100644 --- a/test/common/services/security/test_user.ts +++ b/test/common/services/security/test_user.ts @@ -40,29 +40,33 @@ export class TestUser extends FtrService { super(ctx); } - async restoreDefaults(shouldRefreshBrowser: boolean = true) { - if (this.enabled) { - await this.setRoles(this.config.get('security.defaultRoles'), shouldRefreshBrowser); + async restoreDefaults(options?: { skipBrowserRefresh?: boolean }) { + if (!this.enabled) { + return; } + + await this.setRoles(this.config.get('security.defaultRoles'), options); } - async setRoles(roles: string[], shouldRefreshBrowser: boolean = true) { - if (this.enabled) { - this.log.debug(`set roles = ${roles}`); - await this.user.create(TEST_USER_NAME, { - password: TEST_USER_PASSWORD, - roles, - full_name: 'test user', - }); - - if (this.browser && this.testSubjects && shouldRefreshBrowser) { - if (await this.testSubjects.exists('kibanaChrome', { allowHidden: true })) { - await this.browser.refresh(); - // accept alert if it pops up - const alert = await this.browser.getAlert(); - await alert?.accept(); - await this.testSubjects.find('kibanaChrome', this.config.get('timeouts.find') * 10); - } + async setRoles(roles: string[], options?: { skipBrowserRefresh?: boolean }) { + if (!this.enabled) { + return; + } + + this.log.debug(`set roles = ${roles}`); + await this.user.create(TEST_USER_NAME, { + password: TEST_USER_PASSWORD, + roles, + full_name: 'test user', + }); + + if (this.browser && this.testSubjects && !options?.skipBrowserRefresh) { + if (await this.testSubjects.exists('kibanaChrome', { allowHidden: true })) { + await this.browser.refresh(); + // accept alert if it pops up + const alert = await this.browser.getAlert(); + await alert?.accept(); + await this.testSubjects.find('kibanaChrome', this.config.get('timeouts.find') * 10); } } } diff --git a/test/functional/apps/discover/_huge_fields.ts b/test/functional/apps/discover/_huge_fields.ts index 24b10e1df04956..3cca75234675bc 100644 --- a/test/functional/apps/discover/_huge_fields.ts +++ b/test/functional/apps/discover/_huge_fields.ts @@ -18,7 +18,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('test large number of fields in sidebar', function () { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/huge_fields'); - await security.testUser.setRoles(['kibana_admin', 'test_testhuge_reader'], false); + await security.testUser.setRoles(['kibana_admin', 'test_testhuge_reader'], { + skipBrowserRefresh: true, + }); await kibanaServer.uiSettings.update({ 'timepicker:timeDefaults': `{ "from": "2016-10-05T00:00:00", "to": "2016-10-06T00:00:00"}`, }); diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index 4080ca2a0ba75d..ec3852b309d3f7 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -34,7 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { beforeEach(async () => { await security.testUser.setRoles( ['kibana_admin', 'test_logstash_reader', 'kibana_sample_admin'], - false + { skipBrowserRefresh: true } ); await visualize.navigateToNewVisualization(); await visualize.clickVisualBuilder(); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 4054656028b6eb..f08845b230710d 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -802,9 +802,7 @@ export class VisualBuilderPageObject extends FtrService { } public async checkSelectedMetricsGroupByValue(value: string) { - const groupBy = await this.find.byCssSelector( - '.tvbAggRow--split [data-test-subj="comboBoxInput"]' - ); + const groupBy = await this.testSubjects.find('groupBySelect'); return await this.comboBox.isOptionSelected(groupBy, value); } diff --git a/x-pack/plugins/apm/common/environment_filter_values.ts b/x-pack/plugins/apm/common/environment_filter_values.ts index f0bd386f36de89..ddd1ffd9b8d451 100644 --- a/x-pack/plugins/apm/common/environment_filter_values.ts +++ b/x-pack/plugins/apm/common/environment_filter_values.ts @@ -12,6 +12,13 @@ import { Environment } from './environment_rt'; const ENVIRONMENT_ALL_VALUE = 'ENVIRONMENT_ALL' as const; const ENVIRONMENT_NOT_DEFINED_VALUE = 'ENVIRONMENT_NOT_DEFINED' as const; +export const allOptionText = i18n.translate( + 'xpack.apm.filter.environment.allLabel', + { + defaultMessage: 'All', + } +); + export function getEnvironmentLabel(environment: string) { if (!environment || environment === ENVIRONMENT_NOT_DEFINED_VALUE) { return i18n.translate('xpack.apm.filter.environment.notDefinedLabel', { @@ -20,19 +27,24 @@ export function getEnvironmentLabel(environment: string) { } if (environment === ENVIRONMENT_ALL_VALUE) { - return i18n.translate('xpack.apm.filter.environment.allLabel', { - defaultMessage: 'All', - }); + return allOptionText; } return environment; } -export const ENVIRONMENT_ALL = { +// #TODO Once we replace the select dropdown we can remove it +// EuiSelect > EuiSelectOption accepts text attribute +export const ENVIRONMENT_ALL_SELECT_OPTION = { value: ENVIRONMENT_ALL_VALUE, text: getEnvironmentLabel(ENVIRONMENT_ALL_VALUE), }; +export const ENVIRONMENT_ALL = { + value: ENVIRONMENT_ALL_VALUE, + label: getEnvironmentLabel(ENVIRONMENT_ALL_VALUE), +}; + export const ENVIRONMENT_NOT_DEFINED = { value: ENVIRONMENT_NOT_DEFINED_VALUE, text: getEnvironmentLabel(ENVIRONMENT_NOT_DEFINED_VALUE), diff --git a/x-pack/plugins/apm/dev_docs/testing.md b/x-pack/plugins/apm/dev_docs/testing.md index f6a8298ef9d0c5..6c35979add784d 100644 --- a/x-pack/plugins/apm/dev_docs/testing.md +++ b/x-pack/plugins/apm/dev_docs/testing.md @@ -37,6 +37,7 @@ Once the tests finish, the instances will be terminated. ``` node scripts/test/api --server ``` + Start Elasticsearch and Kibana instances. ### Run all tests @@ -44,6 +45,7 @@ Start Elasticsearch and Kibana instances. ``` node scripts/test/api --runner ``` + Run all tests. The test server needs to be running, see [Start Test Server](#start-test-server). ### Update snapshots (from Kibana root) @@ -53,6 +55,7 @@ To update snapshots append `--updateSnapshots` to the `functional_test_runner` c ``` node scripts/functional_test_runner --config x-pack/test/apm_api_integration/[basic | trial]/config.ts --quiet --updateSnapshots ``` + The test server needs to be running, see [Start Test Server](#start-test-server). The API tests are located in [`x-pack/test/apm_api_integration/`](/x-pack/test/apm_api_integration/). @@ -66,11 +69,23 @@ The API tests are located in [`x-pack/test/apm_api_integration/`](/x-pack/test/a ## E2E Tests (Cypress) +The E2E tests are located in [`x-pack/plugins/apm/ftr_e2e`](../ftr_e2e) + +### Start test server + ``` -node scripts/test/e2e [--trial] [--help] +node x-pack/plugins/apm/scripts/test/e2e.js --server ``` -The E2E tests are located in [`x-pack/plugins/apm/ftr_e2e`](../ftr_e2e) +### Run tests + +``` +node x-pack/plugins/apm/scripts/test/e2e.js --open +``` + +### A11y checks + +Accessibility tests are added on the e2e with `checkA11y()`, they will run together with cypress. --- diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts index 2c2e93d463c508..22ac5a72733e40 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts @@ -6,6 +6,7 @@ */ import { synthtrace } from '../../../synthtrace'; import { opbeans } from '../../fixtures/synthtrace/opbeans'; +import { checkA11y } from '../../support/commands'; const start = '2021-10-10T00:00:00.000Z'; const end = '2021-10-10T00:15:00.000Z'; @@ -43,6 +44,17 @@ describe('Dependencies', () => { cy.contains('h1', 'postgresql'); }); + + it('has no detectable a11y violations on load', () => { + cy.visit( + `/app/apm/services/opbeans-java/dependencies?${new URLSearchParams( + timeRange + )}` + ); + cy.contains('a[role="tab"]', 'Dependencies'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); }); describe('dependency overview page', () => { @@ -62,6 +74,18 @@ describe('Dependencies', () => { cy.contains('h1', 'opbeans-java'); }); + + it('has no detectable a11y violations on load', () => { + cy.visit( + `/app/apm/backends/overview?${new URLSearchParams({ + ...timeRange, + backendName: 'postgresql', + })}` + ); + cy.contains('h1', 'postgresql'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); }); describe('service overview page', () => { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts index f2479b74007322..beaf1837c834c8 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts @@ -7,6 +7,7 @@ import url from 'url'; import { synthtrace } from '../../../../synthtrace'; +import { checkA11y } from '../../../support/commands'; import { generateData } from './generate_data'; const start = '2021-10-10T00:00:00.000Z'; @@ -39,6 +40,13 @@ describe('Error details', () => { await synthtrace.clean(); }); + it('has no detectable a11y violations on load', () => { + cy.visit(errorDetailsPageHref); + cy.contains('Error group 00000'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); + describe('when error has no occurrences', () => { it('shows an empty message', () => { cy.visit( diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts index d08e22092d5927..6ff4795cbcb18b 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts @@ -7,6 +7,7 @@ import url from 'url'; import { synthtrace } from '../../../../synthtrace'; +import { checkA11y } from '../../../support/commands'; import { generateData } from './generate_data'; const start = '2021-10-10T00:00:00.000Z'; @@ -41,6 +42,13 @@ describe('Errors page', () => { await synthtrace.clean(); }); + it('has no detectable a11y violations on load', () => { + cy.visit(javaServiceErrorsPageHref); + cy.contains('Error occurrences'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); + describe('when service has no errors', () => { it('shows empty message', () => { cy.visit(nodeServiceErrorsPageHref); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts index f74a1d122e4266..40afece0ce908c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts @@ -7,6 +7,7 @@ import url from 'url'; import { synthtrace } from '../../../../synthtrace'; import { opbeans } from '../../../fixtures/synthtrace/opbeans'; +import { checkA11y } from '../../../support/commands'; const timeRange = { rangeFrom: '2021-10-10T00:00:00.000Z', @@ -53,6 +54,12 @@ describe('When navigating to the service inventory', () => { cy.visit(serviceInventoryHref); }); + it('has no detectable a11y violations on load', () => { + cy.contains('h1', 'Services'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); + it('has a list of services', () => { cy.contains('opbeans-node'); cy.contains('opbeans-java'); @@ -93,7 +100,7 @@ describe('When navigating to the service inventory', () => { cy.wait(aliasNames); }); - it.skip('when selecting a different time range and clicking the update button', () => { + it('when selecting a different time range and clicking the update button', () => { cy.wait(aliasNames); cy.selectAbsoluteTimeRange( diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts index 31586651cbb846..fcd9e472cc7eb4 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts @@ -8,6 +8,7 @@ import url from 'url'; import { synthtrace } from '../../../../synthtrace'; import { opbeans } from '../../../fixtures/synthtrace/opbeans'; +import { checkA11y } from '../../../support/commands'; const start = '2021-10-10T00:00:00.000Z'; const end = '2021-10-10T00:15:00.000Z'; @@ -102,6 +103,13 @@ describe('Service Overview', () => { cy.loginAsReadOnlyUser(); cy.visit(baseUrl); }); + + it('has no detectable a11y violations on load', () => { + cy.contains('opbeans-node'); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); + it('transaction latency chart', () => { cy.get('[data-test-subj="latencyChart"]'); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts index 3deb4b8619f603..fb8468f42474ec 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts @@ -8,11 +8,12 @@ import url from 'url'; import { synthtrace } from '../../../../synthtrace'; import { opbeans } from '../../../fixtures/synthtrace/opbeans'; +import { checkA11y } from '../../../support/commands'; const start = '2021-10-10T00:00:00.000Z'; const end = '2021-10-10T00:15:00.000Z'; -const serviceOverviewHref = url.format({ +const serviceTransactionsHref = url.format({ pathname: '/app/apm/services/opbeans-node/transactions', query: { rangeFrom: start, rangeTo: end }, }); @@ -35,8 +36,18 @@ describe('Transactions Overview', () => { cy.loginAsReadOnlyUser(); }); + it('has no detectable a11y violations on load', () => { + cy.visit(serviceTransactionsHref); + cy.contains('aria-selected="true"', 'Transactions').should( + 'have.class', + 'euiTab-isSelected' + ); + // set skipFailures to true to not fail the test when there are accessibility failures + checkA11y({ skipFailures: true }); + }); + it('persists transaction type selected when navigating to Overview tab', () => { - cy.visit(serviceOverviewHref); + cy.visit(serviceTransactionsHref); cy.get('[data-test-subj="headerFilterTransactionType"]').should( 'have.value', 'request' diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts index cb66d6db809f34..91edae9046f6d9 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts @@ -6,6 +6,11 @@ */ import 'cypress-real-events/support'; import { Interception } from 'cypress/types/net-stubbing'; +import 'cypress-axe'; +import { + AXE_CONFIG, + AXE_OPTIONS, +} from 'test/accessibility/services/a11y/constants'; Cypress.Commands.add('loginAsReadOnlyUser', () => { cy.loginAs({ username: 'apm_read_user', password: 'changeme' }); @@ -78,3 +83,25 @@ Cypress.Commands.add( }); } ); + +// A11y configuration + +const axeConfig = { + ...AXE_CONFIG, +}; +const axeOptions = { + ...AXE_OPTIONS, + runOnly: [...AXE_OPTIONS.runOnly, 'best-practice'], +}; + +export const checkA11y = ({ skipFailures }: { skipFailures: boolean }) => { + // https://github.com/component-driven/cypress-axe#cychecka11y + cy.injectAxe(); + cy.configureAxe(axeConfig); + const context = '.kbnAppWrapper'; // Scopes a11y checks to only our app + /** + * We can get rid of the last two params when we don't need to add skipFailures + * params = (context, options, violationCallback, skipFailures) + */ + cy.checkA11y(context, axeOptions, undefined, skipFailures); +}; diff --git a/x-pack/plugins/apm/public/components/alerting/fields.tsx b/x-pack/plugins/apm/public/components/alerting/fields.tsx index 171953ea522eb4..4abbd97d98db46 100644 --- a/x-pack/plugins/apm/public/components/alerting/fields.tsx +++ b/x-pack/plugins/apm/public/components/alerting/fields.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiComboBoxOptionOption, EuiFieldNumber } from '@elastic/eui'; +import { EuiFieldNumber } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { @@ -16,22 +16,11 @@ import { import { ENVIRONMENT_ALL, getEnvironmentLabel, + allOptionText, } from '../../../common/environment_filter_values'; import { SuggestionsSelect } from '../shared/suggestions_select'; import { PopoverExpression } from './service_alert_trigger/popover_expression'; -const allOptionText = i18n.translate('xpack.apm.alerting.fields.allOption', { - defaultMessage: 'All', -}); -const allOption: EuiComboBoxOptionOption = { - label: allOptionText, - value: allOptionText, -}; -const environmentAllOption: EuiComboBoxOptionOption = { - label: ENVIRONMENT_ALL.text, - value: ENVIRONMENT_ALL.value, -}; - export function ServiceField({ allowAll = true, currentValue, @@ -43,13 +32,13 @@ export function ServiceField({ }) { return ( + >; + isDisabled: boolean; value?: string; - disabled: boolean; - onChange: (event: React.ChangeEvent) => void; + onChange: (value?: string) => void; } export function FormRowSelect({ @@ -30,10 +30,25 @@ export function FormRowSelect({ fieldLabel, isLoading, options, - value, - disabled, + isDisabled, onChange, }: Props) { + const [selectedOptions, setSelected] = useState< + Array> | undefined + >([]); + + const handleOnChange = ( + nextSelectedOptions: Array> + ) => { + const [selectedOption] = nextSelectedOptions; + setSelected(nextSelectedOptions); + onChange(selectedOption.value); + }; + + useEffect(() => { + setSelected(undefined); + }, [isLoading]); + return ( - diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx new file mode 100644 index 00000000000000..f3f680ff4a9ffa --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx @@ -0,0 +1,54 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { SuggestionsSelect } from '../../../../../shared/suggestions_select'; +import { ENVIRONMENT_ALL } from '../../../../../../../common/environment_filter_values'; + +interface Props { + title: string; + field: string; + description: string; + fieldLabel: string; + value?: string; + allowAll?: boolean; + onChange: (value?: string) => void; +} + +export function FormRowSuggestionsSelect({ + title, + field, + description, + fieldLabel, + value, + allowAll = true, + onChange, +}: Props) { + return ( + {title}} + description={description} + > + + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx index 6f141a0ad8d566..9f8d3ca1318b56 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx @@ -18,7 +18,8 @@ import { import { useFetcher, FETCH_STATUS } from '../../../../../../hooks/use_fetcher'; import { FormRowSelect } from './form_row_select'; import { APMLink } from '../../../../../shared/links/apm/apm_link'; - +import { FormRowSuggestionsSelect } from './form_row_suggestions_select'; +import { SERVICE_NAME } from '../../../../../../../common/elasticsearch_fieldnames'; interface Props { newConfig: AgentConfigurationIntake; setNewConfig: React.Dispatch>; @@ -26,17 +27,6 @@ interface Props { } export function ServicePage({ newConfig, setNewConfig, onClickNext }: Props) { - const { data: serviceNamesData, status: serviceNamesStatus } = useFetcher( - (callApmApi) => { - return callApmApi('GET /api/apm/settings/agent-configuration/services', { - isCachable: true, - }); - }, - [], - { preservePreviousData: false } - ); - const serviceNames = serviceNamesData?.serviceNames ?? []; - const { data: environmentsData, status: environmentsStatus } = useFetcher( (callApmApi) => { if (newConfig.service.name) { @@ -81,14 +71,10 @@ export function ServicePage({ newConfig, setNewConfig, onClickNext }: Props) { { defaultMessage: 'already configured' } ); - const serviceNameOptions = serviceNames.map((name) => ({ - text: getOptionLabel(name), - value: name, - })); const environmentOptions = environments.map( ({ name, alreadyConfigured }) => ({ disabled: alreadyConfigured, - text: `${getOptionLabel(name)} ${ + label: `${getOptionLabel(name)} ${ alreadyConfigured ? `(${ALREADY_CONFIGURED_TRANSLATED})` : '' }`, value: name, @@ -98,7 +84,7 @@ export function ServicePage({ newConfig, setNewConfig, onClickNext }: Props) { return ( <> {/* Service name options */} - { - e.preventDefault(); - const name = e.target.value; + onChange={(name) => { setNewConfig((prev) => ({ ...prev, service: { name, environment: '' }, })); }} /> - {/* Environment options */} { - e.preventDefault(); - const environment = e.target.value; + onChange={(environment) => { setNewConfig((prev) => ({ ...prev, service: { name: prev.service.name, environment }, })); }} /> - - {/* Cancel button */} diff --git a/x-pack/plugins/apm/public/components/app/settings/custom_link/create_edit_custom_link_flyout/filters_section.tsx b/x-pack/plugins/apm/public/components/app/settings/custom_link/create_edit_custom_link_flyout/filters_section.tsx index 3ef8697cde8d98..3b1438b4dddb04 100644 --- a/x-pack/plugins/apm/public/components/app/settings/custom_link/create_edit_custom_link_flyout/filters_section.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/custom_link/create_edit_custom_link_flyout/filters_section.tsx @@ -7,7 +7,6 @@ import { EuiButtonEmpty, - EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiSelect, @@ -27,6 +26,7 @@ import { FILTER_SELECT_OPTIONS, getSelectOptions, } from './helper'; +import { SuggestionsSelect } from '../../../../shared/suggestions_select'; export function FiltersSection({ filters, @@ -117,15 +117,17 @@ export function FiltersSection({ /> - onChangeFilter(key, e.target.value, idx)} - value={value} + onChange={(selectedValue) => + onChangeFilter(key, selectedValue as string, idx) + } + defaultValue={value} isInvalid={!isEmpty(key) && isEmpty(value)} /> diff --git a/x-pack/plugins/apm/public/components/shared/environment_filter/index.tsx b/x-pack/plugins/apm/public/components/shared/environment_filter/index.tsx index 64d137cae0c27e..9a3d677b3f0788 100644 --- a/x-pack/plugins/apm/public/components/shared/environment_filter/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/environment_filter/index.tsx @@ -11,7 +11,7 @@ import { History } from 'history'; import React from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { - ENVIRONMENT_ALL, + ENVIRONMENT_ALL_SELECT_OPTION, ENVIRONMENT_NOT_DEFINED, } from '../../../../common/environment_filter_values'; import { fromQuery, toQuery } from '../links/url_helpers'; @@ -51,7 +51,7 @@ function getOptions(environments: string[]) { })); return [ - ENVIRONMENT_ALL, + ENVIRONMENT_ALL_SELECT_OPTION, ...(environments.includes(ENVIRONMENT_NOT_DEFINED.value) ? [ENVIRONMENT_NOT_DEFINED] : []), diff --git a/x-pack/plugins/apm/public/components/shared/suggestions_select/index.tsx b/x-pack/plugins/apm/public/components/shared/suggestions_select/index.tsx index 2d735ec4ea7083..8b8907af4bc215 100644 --- a/x-pack/plugins/apm/public/components/shared/suggestions_select/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/suggestions_select/index.tsx @@ -6,17 +6,20 @@ */ import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { debounce } from 'lodash'; +import { throttle } from 'lodash'; import React, { useCallback, useState } from 'react'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; interface SuggestionsSelectProps { allOption?: EuiComboBoxOptionOption; - customOptionText: string; + customOptionText?: string; defaultValue?: string; field: string; onChange: (value?: string) => void; + isClearable?: boolean; + isInvalid?: boolean; placeholder: string; + dataTestSubj?: string; } export function SuggestionsSelect({ @@ -26,13 +29,12 @@ export function SuggestionsSelect({ field, onChange, placeholder, + isInvalid, + dataTestSubj, + isClearable = true, }: SuggestionsSelectProps) { - const allowAll = !!allOption; let defaultOption: EuiComboBoxOptionOption | undefined; - if (allowAll && !defaultValue) { - defaultOption = allOption; - } if (defaultValue) { defaultOption = { label: defaultValue, value: defaultValue }; } @@ -57,6 +59,11 @@ export function SuggestionsSelect({ const handleChange = useCallback( (changedOptions: Array>) => { setSelectedOptions(changedOptions); + + if (changedOptions.length === 0) { + onChange(''); + } + if (changedOptions.length === 1) { onChange( changedOptions[0].value @@ -91,17 +98,19 @@ export function SuggestionsSelect({ return ( ); } diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx index 851472cfedabe4..f2919fc12cad6a 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx @@ -375,8 +375,12 @@ describe('TransactionActionMenu component', () => { const getFilterKeyValue = (key: string) => { return { [(component.getAllByText(key)[0] as HTMLOptionElement).text]: ( - component.getAllByTestId(`${key}.value`)[0] as HTMLInputElement - ).value, + component + .getByTestId(`${key}.value`) + .querySelector( + '[data-test-subj="comboBoxInput"] span' + ) as HTMLSpanElement + ).textContent, }; }; expect(getFilterKeyValue('service.name')).toEqual({ diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap index b6b4f2208d04f5..6009dd3ad7b969 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap @@ -148,31 +148,6 @@ Object { } `; -exports[`agent configuration queries getServiceNames fetches service names 1`] = ` -Object { - "apm": Object { - "events": Array [ - "transaction", - "error", - "metric", - ], - }, - "body": Object { - "aggs": Object { - "services": Object { - "terms": Object { - "field": "service.name", - "min_doc_count": 0, - "size": 50, - }, - }, - }, - "size": 0, - "timeout": "1ms", - }, -} -`; - exports[`agent configuration queries listConfigurations fetches configurations 1`] = ` Object { "index": "myIndex", diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts deleted file mode 100644 index 18e359c5b94259..00000000000000 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts +++ /dev/null @@ -1,57 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../../lib/helpers/setup_request'; -import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; -import { ALL_OPTION_VALUE } from '../../../../common/agent_configuration/all_option'; -import { getProcessorEventForTransactions } from '../../../lib/helpers/transactions'; - -export async function getServiceNames({ - setup, - searchAggregatedTransactions, - size, -}: { - setup: Setup; - searchAggregatedTransactions: boolean; - size: number; -}) { - const { apmEventClient } = setup; - - const params = { - apm: { - events: [ - getProcessorEventForTransactions(searchAggregatedTransactions), - ProcessorEvent.error, - ProcessorEvent.metric, - ], - }, - body: { - timeout: '1ms', - size: 0, - aggs: { - services: { - terms: { - field: SERVICE_NAME, - min_doc_count: 0, - size, - }, - }, - }, - }, - }; - - const resp = await apmEventClient.search( - 'get_service_names_for_agent_config', - params - ); - const serviceNames = - resp.aggregations?.services.buckets - .map((bucket) => bucket.key as string) - .sort() || []; - return [ALL_OPTION_VALUE, ...serviceNames]; -} diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts index 4ffc8ed98184bb..49a97c1ca4f774 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts @@ -6,7 +6,6 @@ */ import { getExistingEnvironmentsForService } from './get_environments/get_existing_environments_for_service'; -import { getServiceNames } from './get_service_names'; import { listConfigurations } from './list_configurations'; import { searchConfigurations } from './search_configurations'; import { @@ -52,20 +51,6 @@ describe('agent configuration queries', () => { }); }); - describe('getServiceNames', () => { - it('fetches service names', async () => { - mock = await inspectSearchParams((setup) => - getServiceNames({ - setup, - searchAggregatedTransactions: false, - size: 50, - }) - ); - - expect(mock.params).toMatchSnapshot(); - }); - }); - describe('listConfigurations', () => { it('fetches configurations', async () => { mock = await inspectSearchParams((setup) => diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts index 53a55cc1b99b42..f2cfbe857ba48c 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts @@ -10,7 +10,6 @@ import Boom from '@hapi/boom'; import { toBooleanRt } from '@kbn/io-ts-utils'; import { maxSuggestions } from '../../../../../observability/common'; import { setupRequest } from '../../../lib/helpers/setup_request'; -import { getServiceNames } from './get_service_names'; import { createOrUpdateConfiguration } from './create_or_update_configuration'; import { searchConfigurations } from './search_configurations'; import { findExactConfiguration } from './find_exact_configuration'; @@ -256,33 +255,6 @@ const agentConfigurationSearchRoute = createApmServerRoute({ * Utility endpoints (not documented as part of the public API) */ -// get list of services -const listAgentConfigurationServicesRoute = createApmServerRoute({ - endpoint: 'GET /api/apm/settings/agent-configuration/services', - options: { tags: ['access:apm'] }, - handler: async (resources): Promise<{ serviceNames: string[] }> => { - const setup = await setupRequest(resources); - const { start, end } = resources.params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ - apmEventClient: setup.apmEventClient, - config: setup.config, - kuery: '', - start, - end, - }); - const size = await resources.context.core.uiSettings.client.get( - maxSuggestions - ); - const serviceNames = await getServiceNames({ - searchAggregatedTransactions, - setup, - size, - }); - - return { serviceNames }; - }, -}); - // get environments for service const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration/environments', @@ -342,7 +314,6 @@ export const agentConfigurationRouteRepository = { ...deleteAgentConfigurationRoute, ...createOrUpdateAgentConfigurationRoute, ...agentConfigurationSearchRoute, - ...listAgentConfigurationServicesRoute, ...listAgentConfigurationEnvironmentsRoute, ...agentConfigurationAgentNameRoute, }; diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 95135f4a0e9a09..8abc0805b8a3fc 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -185,7 +185,7 @@ export interface RuleEcs { id?: string[]; rule_id?: string[]; name?: string[]; - false_positives: string[]; + false_positives?: string[]; saved_id?: string[]; timeline_id?: string[]; timeline_title?: string[]; diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index c4535c8f8da2f6..046eb67d38b248 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -254,3 +254,17 @@ export const MAX_LENGTH_ERROR = (field: string, length: number) => export const LINK_APPROPRIATE_LICENSE = i18n.translate('xpack.cases.common.appropriateLicense', { defaultMessage: 'appropriate license', }); + +export const CASE_SUCCESS_TOAST = (title: string) => + i18n.translate('xpack.cases.actions.caseSuccessToast', { + values: { title }, + defaultMessage: 'An alert has been added to "{title}"', + }); + +export const CASE_SUCCESS_SYNC_TEXT = i18n.translate('xpack.cases.actions.caseSuccessSyncText', { + defaultMessage: 'Alerts in this case have their status synched with the case status', +}); + +export const VIEW_CASE = i18n.translate('xpack.cases.actions.viewCase', { + defaultMessage: 'View Case', +}); diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx new file mode 100644 index 00000000000000..9bd6a6675a5c16 --- /dev/null +++ b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx @@ -0,0 +1,75 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { useToasts } from '../common/lib/kibana'; +import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../common/mock'; +import { CaseToastSuccessContent, useCasesToast } from './use_cases_toast'; +import { mockCase } from '../containers/mock'; +import React from 'react'; +import userEvent from '@testing-library/user-event'; + +jest.mock('../common/lib/kibana'); + +const useToastsMock = useToasts as jest.Mock; + +describe('Use cases toast hook', () => { + describe('Toast hook', () => { + const successMock = jest.fn(); + useToastsMock.mockImplementation(() => { + return { + addSuccess: successMock, + }; + }); + it('should create a success tost when invoked with a case', () => { + const { result } = renderHook( + () => { + return useCasesToast(); + }, + { wrapper: TestProviders } + ); + result.current.showSuccessAttach(mockCase); + expect(successMock).toHaveBeenCalled(); + }); + }); + describe('Toast content', () => { + let appMockRender: AppMockRenderer; + const onViewCaseClick = jest.fn(); + beforeEach(() => { + appMockRender = createAppMockRenderer(); + onViewCaseClick.mockReset(); + }); + + it('renders a correct successfull message with synced alerts', () => { + const result = appMockRender.render( + + ); + expect(result.getByTestId('toaster-content-sync-text')).toHaveTextContent( + 'Alerts in this case have their status synched with the case status' + ); + expect(result.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View Case'); + expect(onViewCaseClick).not.toHaveBeenCalled(); + }); + + it('renders a correct successfull message with not synced alerts', () => { + const result = appMockRender.render( + + ); + expect(result.queryByTestId('toaster-content-sync-text')).toBeFalsy(); + expect(result.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View Case'); + expect(onViewCaseClick).not.toHaveBeenCalled(); + }); + + it('Calls the onViewCaseClick when clicked', () => { + const result = appMockRender.render( + + ); + userEvent.click(result.getByTestId('toaster-content-case-view-link')); + expect(onViewCaseClick).toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.tsx new file mode 100644 index 00000000000000..98cc7fa1d8faa0 --- /dev/null +++ b/x-pack/plugins/cases/public/common/use_cases_toast.tsx @@ -0,0 +1,82 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButtonEmpty, EuiText } from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; +import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; +import { Case } from '../../common'; +import { useToasts } from '../common/lib/kibana'; +import { useCaseViewNavigation } from '../common/navigation'; +import { CASE_SUCCESS_SYNC_TEXT, CASE_SUCCESS_TOAST, VIEW_CASE } from './translations'; + +const LINE_CLAMP = 3; +const Title = styled.span` + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: ${LINE_CLAMP}; + -webkit-box-orient: vertical; + overflow: hidden; +`; +const EuiTextStyled = styled(EuiText)` + ${({ theme }) => ` + margin-bottom: ${theme.eui?.paddingSizes?.s ?? 8}px; + `} +`; + +export const useCasesToast = () => { + const { navigateToCaseView } = useCaseViewNavigation(); + + const toasts = useToasts(); + + return { + showSuccessAttach: (theCase: Case) => { + const onViewCaseClick = () => { + navigateToCaseView({ + detailName: theCase.id, + }); + }; + return toasts.addSuccess({ + color: 'success', + iconType: 'check', + title: toMountPoint({CASE_SUCCESS_TOAST(theCase.title)}), + text: toMountPoint( + + ), + }); + }, + }; +}; +export const CaseToastSuccessContent = ({ + syncAlerts, + onViewCaseClick, +}: { + syncAlerts: boolean; + onViewCaseClick: () => void; +}) => { + return ( + <> + {syncAlerts && ( + + {CASE_SUCCESS_SYNC_TEXT} + + )} + + {VIEW_CASE} + + + ); +}; +CaseToastSuccessContent.displayName = 'CaseToastSuccessContent'; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx index 08c99c51593997..ba553b28a34e09 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx @@ -26,7 +26,7 @@ export interface AllCasesSelectorModalProps { */ alertData?: Omit; hiddenStatuses?: CaseStatusWithAllStatus[]; - onRowClick: (theCase?: Case) => void; + onRowClick?: (theCase?: Case) => void; updateCase?: (newCase: Case) => void; onClose?: () => void; attachments?: CaseAttachments; @@ -52,7 +52,9 @@ export const AllCasesSelectorModal = React.memo( const onClick = useCallback( (theCase?: Case) => { closeModal(); - onRowClick(theCase); + if (onRowClick) { + onRowClick(theCase); + } }, [closeModal, onRowClick] ); diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/uses_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx similarity index 89% rename from x-pack/plugins/cases/public/components/all_cases/selector_modal/uses_cases_add_to_existing_case_modal.test.tsx rename to x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx index 6eeff6102ae6a3..6a224949db8be2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/uses_cases_add_to_existing_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx @@ -12,6 +12,7 @@ import React from 'react'; import { CasesContext } from '../../cases_context'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesAddToExistingCaseModal } from './use_cases_add_to_existing_case_modal'; +jest.mock('../../../common/use_cases_toast'); describe('use cases add to existing case modal hook', () => { const dispatch = jest.fn(); @@ -65,7 +66,7 @@ describe('use cases add to existing case modal hook', () => { ); }); - it('should dispatch the close action when invoked', () => { + it('should dispatch the close action for modal and flyout when invoked', () => { const { result } = renderHook( () => { return useCasesAddToExistingCaseModal(defaultParams()); @@ -78,5 +79,10 @@ describe('use cases add to existing case modal hook', () => { type: CasesContextStoreActionsList.CLOSE_ADD_TO_CASE_MODAL, }) ); + expect(dispatch).toHaveBeenCalledWith( + expect.objectContaining({ + type: CasesContextStoreActionsList.CLOSE_CREATE_CASE_FLYOUT, + }) + ); }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx index b2ad07c2375dfe..5341f5be4183d5 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx @@ -7,15 +7,36 @@ import { useCallback } from 'react'; import { AllCasesSelectorModalProps } from '.'; +import { useCasesToast } from '../../../common/use_cases_toast'; +import { Case } from '../../../containers/types'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesContext } from '../../cases_context/use_cases_context'; +import { useCasesAddToNewCaseFlyout } from '../../create/flyout/use_cases_add_to_new_case_flyout'; export const useCasesAddToExistingCaseModal = (props: AllCasesSelectorModalProps) => { + const createNewCaseFlyout = useCasesAddToNewCaseFlyout({ + attachments: props.attachments, + onClose: props.onClose, + // TODO there's no need for onSuccess to be async. This will be fixed + // in a follow up clean up + onSuccess: async (theCase?: Case) => { + if (props.onRowClick) { + return props.onRowClick(theCase); + } + }, + }); const { dispatch } = useCasesContext(); + const casesToasts = useCasesToast(); + const closeModal = useCallback(() => { dispatch({ type: CasesContextStoreActionsList.CLOSE_ADD_TO_CASE_MODAL, }); + // in case the flyout was also open when selecting + // create a new case + dispatch({ + type: CasesContextStoreActionsList.CLOSE_CREATE_CASE_FLYOUT, + }); }, [dispatch]); const openModal = useCallback(() => { @@ -23,6 +44,19 @@ export const useCasesAddToExistingCaseModal = (props: AllCasesSelectorModalProps type: CasesContextStoreActionsList.OPEN_ADD_TO_CASE_MODAL, payload: { ...props, + onRowClick: (theCase?: Case) => { + // when the case is undefined in the modal + // the user clicked "create new case" + if (theCase === undefined) { + closeModal(); + createNewCaseFlyout.open(); + } else { + casesToasts.showSuccessAttach(theCase); + if (props.onRowClick) { + props.onRowClick(theCase); + } + } + }, onClose: () => { closeModal(); if (props.onClose) { @@ -37,7 +71,7 @@ export const useCasesAddToExistingCaseModal = (props: AllCasesSelectorModalProps }, }, }); - }, [closeModal, dispatch, props]); + }, [casesToasts, closeModal, createNewCaseFlyout, dispatch, props]); return { open: openModal, close: closeModal, diff --git a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx index 103e24c4b7a656..e569b1ee799526 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx @@ -12,6 +12,7 @@ import React from 'react'; import { CasesContext } from '../../cases_context'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesAddToNewCaseFlyout } from './use_cases_add_to_new_case_flyout'; +jest.mock('../../../common/use_cases_toast'); describe('use cases add to new case flyout hook', () => { const dispatch = jest.fn(); diff --git a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx index e4ae4d72f48dab..5422ab9be995d9 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx @@ -6,12 +6,15 @@ */ import { useCallback } from 'react'; +import { useCasesToast } from '../../../common/use_cases_toast'; +import { Case } from '../../../containers/types'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesContext } from '../../cases_context/use_cases_context'; import { CreateCaseFlyoutProps } from './create_case_flyout'; export const useCasesAddToNewCaseFlyout = (props: CreateCaseFlyoutProps) => { const { dispatch } = useCasesContext(); + const casesToasts = useCasesToast(); const closeFlyout = useCallback(() => { dispatch({ @@ -30,6 +33,14 @@ export const useCasesAddToNewCaseFlyout = (props: CreateCaseFlyoutProps) => { return props.onClose(); } }, + onSuccess: async (theCase: Case) => { + if (theCase) { + casesToasts.showSuccessAttach(theCase); + } + if (props.onSuccess) { + return props.onSuccess(theCase); + } + }, afterCaseCreated: async (...args) => { closeFlyout(); if (props.afterCaseCreated) { @@ -38,7 +49,7 @@ export const useCasesAddToNewCaseFlyout = (props: CreateCaseFlyoutProps) => { }, }, }); - }, [closeFlyout, dispatch, props]); + }, [casesToasts, closeFlyout, dispatch, props]); return { open: openFlyout, close: closeFlyout, diff --git a/x-pack/plugins/cases/public/index.tsx b/x-pack/plugins/cases/public/index.tsx index 0190df8204fc1a..42dd1a94199917 100644 --- a/x-pack/plugins/cases/public/index.tsx +++ b/x-pack/plugins/cases/public/index.tsx @@ -21,7 +21,7 @@ export type { GetCreateCaseFlyoutProps } from './methods/get_create_case_flyout' export type { GetAllCasesSelectorModalProps } from './methods/get_all_cases_selector_modal'; export type { GetRecentCasesProps } from './methods/get_recent_cases'; -export type { CaseAttachments } from './types'; +export type { CaseAttachments, SupportedCaseAttachment } from './types'; export type { ICasesDeepLinkId } from './common/navigation'; export { diff --git a/x-pack/plugins/cases/public/methods/get_rule_id_from_event.ts b/x-pack/plugins/cases/public/methods/get_rule_id_from_event.ts new file mode 100644 index 00000000000000..b07ba032e7b191 --- /dev/null +++ b/x-pack/plugins/cases/public/methods/get_rule_id_from_event.ts @@ -0,0 +1,46 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { get } from 'lodash/fp'; +import { Ecs } from '../../common'; + +type Maybe = T | null; +interface Event { + data: EventNonEcsData[]; + ecs: Ecs; +} +interface EventNonEcsData { + field: string; + value?: Maybe; +} + +export function getRuleIdFromEvent(event: Event): { + id: string; + name: string; +} { + const ruleUuidData = event && event.data.find(({ field }) => field === ALERT_RULE_UUID); + const ruleNameData = event && event.data.find(({ field }) => field === ALERT_RULE_NAME); + const ruleUuidValueData = ruleUuidData && ruleUuidData.value && ruleUuidData.value[0]; + const ruleNameValueData = ruleNameData && ruleNameData.value && ruleNameData.value[0]; + + const ruleUuid = + ruleUuidValueData ?? + get(`ecs.${ALERT_RULE_UUID}[0]`, event) ?? + get(`ecs.signal.rule.id[0]`, event) ?? + null; + const ruleName = + ruleNameValueData ?? + get(`ecs.${ALERT_RULE_NAME}[0]`, event) ?? + get(`ecs.signal.rule.name[0]`, event) ?? + null; + + return { + id: ruleUuid, + name: ruleName, + }; +} diff --git a/x-pack/plugins/cases/public/mocks.ts b/x-pack/plugins/cases/public/mocks.ts index f7f80170a87750..a3876e9e19322e 100644 --- a/x-pack/plugins/cases/public/mocks.ts +++ b/x-pack/plugins/cases/public/mocks.ts @@ -5,12 +5,13 @@ * 2.0. */ +import { mockCasesContext } from './mocks/mock_cases_context'; import { CasesUiStart } from './types'; -const createStartContract = (): jest.Mocked => ({ +export const mockCasesContract = (): jest.Mocked => ({ canUseCases: jest.fn(), getCases: jest.fn(), - getCasesContext: jest.fn(), + getCasesContext: jest.fn().mockImplementation(() => mockCasesContext), getAllCasesSelectorModal: jest.fn(), getAllCasesSelectorModalNoProvider: jest.fn(), getCreateCaseFlyout: jest.fn(), @@ -20,8 +21,11 @@ const createStartContract = (): jest.Mocked => ({ getUseCasesAddToNewCaseFlyout: jest.fn(), getUseCasesAddToExistingCaseModal: jest.fn(), }, + helpers: { + getRuleIdFromEvent: jest.fn(), + }, }); export const casesPluginMock = { - createStartContract, + createStartContract: mockCasesContract, }; diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_cases_context.tsx b/x-pack/plugins/cases/public/mocks/mock_cases_context.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/mock/mock_cases_context.tsx rename to x-pack/plugins/cases/public/mocks/mock_cases_context.tsx diff --git a/x-pack/plugins/cases/public/plugin.ts b/x-pack/plugins/cases/public/plugin.ts index 9dbc6ea35125ad..31185ae78f076c 100644 --- a/x-pack/plugins/cases/public/plugin.ts +++ b/x-pack/plugins/cases/public/plugin.ts @@ -21,6 +21,7 @@ import { CasesUiConfigType } from '../common/ui/types'; import { getCasesContextLazy } from './methods/get_cases_context'; import { useCasesAddToNewCaseFlyout } from './components/create/flyout/use_cases_add_to_new_case_flyout'; import { useCasesAddToExistingCaseModal } from './components/all_cases/selector_modal/use_cases_add_to_existing_case_modal'; +import { getRuleIdFromEvent } from './methods/get_rule_id_from_event'; /** * @public @@ -52,6 +53,9 @@ export class CasesUiPlugin implements Plugin ({ type TableProps = PropsOf; -describe('', () => { +// FLAKY: https://github.com/elastic/kibana/issues/126664 +describe.skip('', () => { it('renders the zero state when status success and data has a length of zero ', async () => { const props: TableProps = { status: 'success', diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index f84668068f413a..7a6203c994f4d9 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -7,21 +7,37 @@ import { i18n } from '@kbn/i18n'; -export const ENTERPRISE_SEARCH_PLUGIN = { +export const ENTERPRISE_SEARCH_OVERVIEW_PLUGIN = { ID: 'enterpriseSearch', - NAME: i18n.translate('xpack.enterpriseSearch.productName', { + NAME: i18n.translate('xpack.enterpriseSearch.overview.productName', { defaultMessage: 'Enterprise Search', }), - NAV_TITLE: i18n.translate('xpack.enterpriseSearch.navTitle', { + NAV_TITLE: i18n.translate('xpack.enterpriseSearch.overview.navTitle', { defaultMessage: 'Overview', }), - DESCRIPTION: i18n.translate('xpack.enterpriseSearch.FeatureCatalogue.description', { + DESCRIPTION: i18n.translate('xpack.enterpriseSearch.overview.description', { defaultMessage: 'Create search experiences with a refined set of APIs and tools.', }), URL: '/app/enterprise_search/overview', LOGO: 'logoEnterpriseSearch', }; +export const ENTERPRISE_SEARCH_CONTENT_PLUGIN = { + ID: 'enterpriseSearchContent', + NAME: i18n.translate('xpack.enterpriseSearch.content.productName', { + defaultMessage: 'Enterprise Search', + }), + NAV_TITLE: i18n.translate('xpack.enterpriseSearch.content.navTitle', { + defaultMessage: 'Content', + }), + DESCRIPTION: i18n.translate('xpack.enterpriseSearch.content.description', { + defaultMessage: + 'Enterprise search offers a number of ways to easily make your data searchable. Choose from the web crawler, Elasticsearch indices, API, direct uploads, or thrid party connectors.', // TODO: Make sure this content is correct. + }), + URL: '/app/enterprise_search/content', + LOGO: 'logoEnterpriseSearch', +}; + export const APP_SEARCH_PLUGIN = { ID: 'appSearch', NAME: i18n.translate('xpack.enterpriseSearch.appSearch.productName', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx index dce56a05f8f8cc..c2b40a2c0aa084 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx @@ -14,7 +14,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { EnterpriseSearchPageTemplate } from '../../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper } from '../../../../shared/layout'; import { rerender } from '../../../../test_helpers'; jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); @@ -55,7 +55,7 @@ describe('Curation', () => { setMockValues({ dataLoading: true }); const wrapper = shallow(); - expect(wrapper.is(EnterpriseSearchPageTemplate)).toBe(true); + expect(wrapper.is(EnterpriseSearchPageTemplateWrapper)).toBe(true); }); it('renders a view for automated curations', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx index d1b0f43d976a8a..1c49c077e7a6aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx @@ -10,7 +10,7 @@ import { useParams } from 'react-router-dom'; import { useValues, useActions } from 'kea'; -import { EnterpriseSearchPageTemplate } from '../../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper } from '../../../../shared/layout'; import { AutomatedCuration } from './automated_curation'; import { CurationLogic } from './curation_logic'; @@ -26,7 +26,7 @@ export const Curation: React.FC = () => { }, [curationId]); if (dataLoading) { - return ; + return ; } return isAutomated ? : ; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.test.tsx index 8f47d5f1c46444..b26cc00379f34d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.test.tsx @@ -14,7 +14,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { SetAppSearchChrome } from '../../../shared/kibana_chrome'; -import { EnterpriseSearchPageTemplate } from '../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper } from '../../../shared/layout'; import { SendAppSearchTelemetry } from '../../../shared/telemetry'; import { AppSearchPageTemplate } from './page_template'; @@ -27,7 +27,7 @@ describe('AppSearchPageTemplate', () => { ); - expect(wrapper.type()).toEqual(EnterpriseSearchPageTemplate); + expect(wrapper.type()).toEqual(EnterpriseSearchPageTemplateWrapper); expect(wrapper.prop('solutionNav')).toEqual({ name: 'App Search', items: [] }); expect(wrapper.find('.hello').text()).toEqual('world'); }); @@ -35,7 +35,9 @@ describe('AppSearchPageTemplate', () => { describe('page chrome', () => { it('takes a breadcrumb array & renders a product-specific page chrome', () => { const wrapper = shallow(); - const setPageChrome = wrapper.find(EnterpriseSearchPageTemplate).prop('setPageChrome') as any; + const setPageChrome = wrapper + .find(EnterpriseSearchPageTemplateWrapper) + .prop('setPageChrome') as any; expect(setPageChrome.type).toEqual(SetAppSearchChrome); expect(setPageChrome.props.trail).toEqual(['Some page']); @@ -51,7 +53,7 @@ describe('AppSearchPageTemplate', () => { }); }); - it('passes down any ...pageTemplateProps that EnterpriseSearchPageTemplate accepts', () => { + it('passes down any ...pageTemplateProps that EnterpriseSearchPageTemplateWrapper accepts', () => { const wrapper = shallow( { /> ); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('pageHeader')!.pageTitle).toEqual( + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('pageHeader')!.pageTitle).toEqual( 'hello world' ); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('isLoading')).toEqual(false); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('emptyState')).toEqual(
); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('isLoading')).toEqual(false); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('emptyState')).toEqual(
); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.tsx index 31f2eb3215e05a..d336bcc6a4c5fb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/page_template.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; import { SetAppSearchChrome } from '../../../shared/kibana_chrome'; -import { EnterpriseSearchPageTemplate, PageTemplateProps } from '../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; import { SendAppSearchTelemetry } from '../../../shared/telemetry'; import { useAppSearchNav } from './nav'; @@ -21,7 +21,7 @@ export const AppSearchPageTemplate: React.FC = ({ ...pageTemplateProps }) => { return ( - = ({ > {pageViewTelemetry && } {children} - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/assets/app_search.png b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/app_search.png similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/assets/app_search.png rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/app_search.png diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/assets/workplace_search.png b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/workplace_search.png similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/assets/workplace_search.png rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/workplace_search.png diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/constants.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/constants.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/constants.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/constants.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/license_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/license_callout.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/license_callout.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/license_callout.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/license_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/license_callout.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/license_callout/license_callout.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/license_callout/license_callout.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.scss similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.scss diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/lock_light.svg b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/lock_light.svg similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/lock_light.svg rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/lock_light.svg diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/assets/getting_started.png b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/assets/getting_started.png similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/assets/getting_started.png rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/assets/getting_started.png diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide.tsx similarity index 93% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide.tsx index 1a25d1a7a8d1e2..c8889320bb3464 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide.tsx @@ -11,7 +11,7 @@ import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { ENTERPRISE_SEARCH_OVERVIEW_PLUGIN } from '../../../../../common/constants'; import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuideLayout, SETUP_GUIDE_TITLE } from '../../../shared/setup_guide'; import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; @@ -20,7 +20,7 @@ import GettingStarted from './assets/getting_started.png'; export const SetupGuide: React.FC = () => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.scss rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.scss diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/setup_guide/setup_guide_cta.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/index.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/trial_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/trial_callout.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/trial_callout.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/trial_callout.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/trial_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/trial_callout.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/trial_callout/trial_callout.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/trial_callout/trial_callout.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/constants.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/constants.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/constants.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress.json b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress.json rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress/integration/overview.spec.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/integration/overview.spec.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress/integration/overview.spec.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/integration/overview.spec.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress/tsconfig.json b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/tsconfig.json similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/cypress/tsconfig.json rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/tsconfig.json diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.test.tsx similarity index 87% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.test.tsx index 4aef227582d318..e5d883ee819f77 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.test.tsx @@ -18,15 +18,15 @@ import { ErrorConnecting } from './components/error_connecting'; import { ProductSelector } from './components/product_selector'; import { SetupGuide } from './components/setup_guide'; -import { EnterpriseSearch } from './'; +import { EnterpriseSearchOverview } from './'; -describe('EnterpriseSearch', () => { +describe('EnterpriseSearchOverview', () => { it('renders the Setup Guide and Product Selector', () => { setMockValues({ errorConnectingMessage: '', config: { host: 'localhost' }, }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(SetupGuide)).toHaveLength(1); expect(wrapper.find(ProductSelector)).toHaveLength(1); @@ -37,7 +37,7 @@ describe('EnterpriseSearch', () => { errorConnectingMessage: '502 Bad Gateway', config: { host: 'localhost' }, }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(VersionMismatchPage)).toHaveLength(0); const errorConnecting = wrapper.find(ErrorConnecting); @@ -61,7 +61,7 @@ describe('EnterpriseSearch', () => { config: { host: 'localhost' }, }); const wrapper = shallow( - + ); expect(wrapper.find(VersionMismatchPage)).toHaveLength(1); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx similarity index 96% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx index 5f1c7b5072be23..ca4b91d0e03b97 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx @@ -21,7 +21,7 @@ import { ProductSelector } from './components/product_selector'; import { SetupGuide } from './components/setup_guide'; import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes'; -export const EnterpriseSearch: React.FC = ({ +export const EnterpriseSearchOverview: React.FC = ({ access = {}, workplaceSearch, enterpriseSearchVersion, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/routes.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search/routes.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/routes.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx index 356a3c26b910e9..cb47dfe124780e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx @@ -15,7 +15,7 @@ import { licensingMock } from '../../../licensing/public/mocks'; import { securityMock } from '../../../security/public/mocks'; import { AppSearch } from './app_search'; -import { EnterpriseSearch } from './enterprise_search'; +import { EnterpriseSearchOverview } from './enterprise_search_overview'; import { KibanaLogic } from './shared/kibana'; import { WorkplaceSearch } from './workplace_search'; @@ -62,8 +62,8 @@ describe('renderApp', () => { describe('Enterprise Search apps', () => { afterEach(() => unmount()); - it('renders EnterpriseSearch', () => { - mount(EnterpriseSearch); + it('renders EnterpriseSearchOverview', () => { + mount(EnterpriseSearchOverview); expect(mockContainer.querySelector('.kbnPageTemplate')).not.toBeNull(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts index 5855dc6990f6a7..8864600475c122 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts @@ -10,7 +10,7 @@ import { useValues } from 'kea'; import { EuiBreadcrumb } from '@elastic/eui'; import { - ENTERPRISE_SEARCH_PLUGIN, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, } from '../../../../common/constants'; @@ -97,8 +97,8 @@ export const useEuiBreadcrumbs = (breadcrumbs: Breadcrumbs): EuiBreadcrumb[] => export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) => useEuiBreadcrumbs([ { - text: ENTERPRISE_SEARCH_PLUGIN.NAME, - path: ENTERPRISE_SEARCH_PLUGIN.URL, + text: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME, + path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, shouldNotCreateHref: true, }, ...breadcrumbs, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts index 650aa00d1801d9..8b91b7e57a7813 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts @@ -6,7 +6,7 @@ */ import { - ENTERPRISE_SEARCH_PLUGIN, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, } from '../../../../common/constants'; @@ -30,7 +30,7 @@ export const generateTitle = (pages: Title) => pages.join(' - '); */ export const enterpriseSearchTitle = (page: Title = []) => - generateTitle([...page, ENTERPRISE_SEARCH_PLUGIN.NAME]); + generateTitle([...page, ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME]); export const appSearchTitle = (page: Title = []) => generateTitle([...page, APP_SEARCH_PLUGIN.NAME]); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts index 79919e925c625e..790d72943a1bc8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts @@ -6,5 +6,5 @@ */ export type { PageTemplateProps } from './page_template'; -export { EnterpriseSearchPageTemplate } from './page_template'; +export { EnterpriseSearchPageTemplateWrapper } from './page_template'; export { generateNavLink } from './nav_link_helpers'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.test.tsx index 8d480b69b3fe53..22c976dfa7638f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.test.tsx @@ -17,25 +17,25 @@ import { KibanaPageTemplate } from '../../../../../../../src/plugins/kibana_reac import { FlashMessages } from '../flash_messages'; import { Loading } from '../loading'; -import { EnterpriseSearchPageTemplate } from './page_template'; +import { EnterpriseSearchPageTemplateWrapper } from './page_template'; -describe('EnterpriseSearchPageTemplate', () => { +describe('EnterpriseSearchPageTemplateWrapper', () => { beforeEach(() => { jest.clearAllMocks(); setMockValues({ readOnlyMode: false }); }); it('renders', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.type()).toEqual(KibanaPageTemplate); }); it('renders children', () => { const wrapper = shallow( - +
world
-
+
); expect(wrapper.find('.hello').text()).toEqual('world'); @@ -44,9 +44,9 @@ describe('EnterpriseSearchPageTemplate', () => { describe('loading state', () => { it('renders a loading icon in place of children', () => { const wrapper = shallow( - +
- + ); expect(wrapper.find(Loading).exists()).toBe(true); @@ -55,9 +55,9 @@ describe('EnterpriseSearchPageTemplate', () => { it('renders children & does not render a loading icon when the page is done loading', () => { const wrapper = shallow( - +
- + ); expect(wrapper.find(Loading).exists()).toBe(false); @@ -68,12 +68,12 @@ describe('EnterpriseSearchPageTemplate', () => { describe('empty state', () => { it('renders a custom empty state in place of children', () => { const wrapper = shallow( - Nothing here yet!
} >
- + ); expect(wrapper.find('.emptyState').exists()).toBe(true); @@ -85,12 +85,12 @@ describe('EnterpriseSearchPageTemplate', () => { it('does not render the custom empty state if the page is not empty', () => { const wrapper = shallow( - Nothing here yet!
} >
- + ); expect(wrapper.find('.emptyState').exists()).toBe(false); @@ -99,7 +99,7 @@ describe('EnterpriseSearchPageTemplate', () => { it('does not render an empty state if the page is still loading', () => { const wrapper = shallow( - } @@ -114,14 +114,14 @@ describe('EnterpriseSearchPageTemplate', () => { describe('read-only mode', () => { it('renders a callout if in read-only mode', () => { setMockValues({ readOnlyMode: true }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(EuiCallOut).exists()).toBe(true); }); it('does not render a callout if not in read-only mode', () => { setMockValues({ readOnlyMode: false }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(EuiCallOut).exists()).toBe(false); }); @@ -129,7 +129,7 @@ describe('EnterpriseSearchPageTemplate', () => { describe('flash messages', () => { it('renders FlashMessages by default', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(FlashMessages).exists()).toBe(true); }); @@ -137,7 +137,7 @@ describe('EnterpriseSearchPageTemplate', () => { it('does not render FlashMessages if hidden', () => { // Example use case: manually showing flash messages in an open flyout or modal // and not wanting to duplicate flash messages on the overlayed page - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(FlashMessages).exists()).toBe(false); }); @@ -147,14 +147,16 @@ describe('EnterpriseSearchPageTemplate', () => { const SetPageChrome = () =>
; it('renders a product-specific ', () => { - const wrapper = shallow(} />); + const wrapper = shallow( + } /> + ); expect(wrapper.find(SetPageChrome).exists()).toBe(true); }); it('invokes page chrome immediately (without waiting for isLoading to be finished)', () => { const wrapper = shallow( - } isLoading /> + } isLoading /> ); expect(wrapper.find(SetPageChrome).exists()).toBe(true); @@ -166,14 +168,14 @@ describe('EnterpriseSearchPageTemplate', () => { describe('EuiPageTemplate props', () => { it('overrides the restrictWidth prop', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(KibanaPageTemplate).prop('restrictWidth')).toEqual(true); }); it('passes down any ...pageTemplateProps that EuiPageTemplate accepts', () => { const wrapper = shallow( - { it('sets enterpriseSearchPageTemplate classNames while still accepting custom classNames', () => { const wrapper = shallow( - + ); expect(wrapper.find(KibanaPageTemplate).prop('className')).toEqual( @@ -200,7 +205,9 @@ describe('EnterpriseSearchPageTemplate', () => { it('automatically sets the Enterprise Search logo onto passed solution navs', () => { const wrapper = shallow( - + ); expect(wrapper.find(KibanaPageTemplate).prop('solutionNav')).toEqual({ diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx index 7528fa14b7ae4f..934d571418d0e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx @@ -26,7 +26,7 @@ import { Loading } from '../loading'; import './page_template.scss'; /* - * EnterpriseSearchPageTemplate is a light wrapper for KibanaPageTemplate (which + * EnterpriseSearchPageTemplateWrapper is a light wrapper for KibanaPageTemplate (which * is a light wrapper for EuiPageTemplate). It should contain only concerns shared * between both AS & WS, which should have their own AppSearchPageTemplate & * WorkplaceSearchPageTemplate sitting on top of this template (:nesting_dolls:), @@ -46,7 +46,7 @@ export type PageTemplateProps = KibanaPageTemplateProps & { pageViewTelemetry?: string; }; -export const EnterpriseSearchPageTemplate: React.FC = ({ +export const EnterpriseSearchPageTemplateWrapper: React.FC = ({ children, className, hideFlashMessages, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.test.tsx index 622fddc449ca7d..57611e1bacdc16 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.test.tsx @@ -14,7 +14,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { SetWorkplaceSearchChrome } from '../../../shared/kibana_chrome'; -import { EnterpriseSearchPageTemplate } from '../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper } from '../../../shared/layout'; import { SendWorkplaceSearchTelemetry } from '../../../shared/telemetry'; import { WorkplaceSearchPageTemplate } from './page_template'; @@ -27,7 +27,7 @@ describe('WorkplaceSearchPageTemplate', () => { ); - expect(wrapper.type()).toEqual(EnterpriseSearchPageTemplate); + expect(wrapper.type()).toEqual(EnterpriseSearchPageTemplateWrapper); expect(wrapper.prop('solutionNav')).toEqual({ name: 'Workplace Search', items: [] }); expect(wrapper.find('.hello').text()).toEqual('world'); }); @@ -35,7 +35,9 @@ describe('WorkplaceSearchPageTemplate', () => { describe('page chrome', () => { it('takes a breadcrumb array & renders a product-specific page chrome', () => { const wrapper = shallow(); - const setPageChrome = wrapper.find(EnterpriseSearchPageTemplate).prop('setPageChrome') as any; + const setPageChrome = wrapper + .find(EnterpriseSearchPageTemplateWrapper) + .prop('setPageChrome') as any; expect(setPageChrome.type).toEqual(SetWorkplaceSearchChrome); expect(setPageChrome.props.trail).toEqual(['Some page']); @@ -54,13 +56,15 @@ describe('WorkplaceSearchPageTemplate', () => { describe('props', () => { it('allows overriding the restrictWidth default', () => { const wrapper = shallow(); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('restrictWidth')).toEqual(true); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('restrictWidth')).toEqual(true); wrapper.setProps({ restrictWidth: false }); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('restrictWidth')).toEqual(false); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('restrictWidth')).toEqual( + false + ); }); - it('passes down any ...pageTemplateProps that EnterpriseSearchPageTemplate accepts', () => { + it('passes down any ...pageTemplateProps that EnterpriseSearchPageTemplateWrapper accepts', () => { const wrapper = shallow( { /> ); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('pageHeader')!.pageTitle).toEqual( - 'hello world' - ); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('isLoading')).toEqual(false); - expect(wrapper.find(EnterpriseSearchPageTemplate).prop('emptyState')).toEqual(
); + expect( + wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('pageHeader')!.pageTitle + ).toEqual('hello world'); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('isLoading')).toEqual(false); + expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('emptyState')).toEqual(
); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.tsx index 4a6e0d9c6e2ddc..f2a522b1b1d67c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/page_template.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; import { SetWorkplaceSearchChrome } from '../../../shared/kibana_chrome'; -import { EnterpriseSearchPageTemplate, PageTemplateProps } from '../../../shared/layout'; +import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; import { SendWorkplaceSearchTelemetry } from '../../../shared/telemetry'; import { useWorkplaceSearchNav } from './nav'; @@ -21,7 +21,7 @@ export const WorkplaceSearchPageTemplate: React.FC = ({ ...pageTemplateProps }) => { return ( - = ({ )} {children} - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_server.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_server.svg new file mode 100644 index 00000000000000..aebfd7a8e49c0f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index 1cc96be1b40f87..5b193d3e809640 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -26,7 +26,7 @@ import { SecurityPluginSetup, SecurityPluginStart } from '../../security/public' import { APP_SEARCH_PLUGIN, - ENTERPRISE_SEARCH_PLUGIN, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, WORKPLACE_SEARCH_PLUGIN, } from '../common/constants'; import { InitialAppData } from '../common/types'; @@ -67,30 +67,32 @@ export class EnterpriseSearchPlugin implements Plugin { const { cloud } = plugins; core.application.register({ - id: ENTERPRISE_SEARCH_PLUGIN.ID, - title: ENTERPRISE_SEARCH_PLUGIN.NAV_TITLE, - euiIconType: ENTERPRISE_SEARCH_PLUGIN.LOGO, - appRoute: ENTERPRISE_SEARCH_PLUGIN.URL, + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE, + euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, + appRoute: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { const kibanaDeps = await this.getKibanaDeps(core, params, cloud); const { chrome, http } = kibanaDeps.core; - chrome.docTitle.change(ENTERPRISE_SEARCH_PLUGIN.NAME); + chrome.docTitle.change(ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME); await this.getInitialData(http); const pluginData = this.getPluginData(); const { renderApp } = await import('./applications'); - const { EnterpriseSearch } = await import('./applications/enterprise_search'); + const { EnterpriseSearchOverview } = await import( + './applications/enterprise_search_overview' + ); - return renderApp(EnterpriseSearch, kibanaDeps, pluginData); + return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData); }, }); core.application.register({ id: APP_SEARCH_PLUGIN.ID, title: APP_SEARCH_PLUGIN.NAME, - euiIconType: ENTERPRISE_SEARCH_PLUGIN.LOGO, + euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, appRoute: APP_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { @@ -111,7 +113,7 @@ export class EnterpriseSearchPlugin implements Plugin { core.application.register({ id: WORKPLACE_SEARCH_PLUGIN.ID, title: WORKPLACE_SEARCH_PLUGIN.NAME, - euiIconType: ENTERPRISE_SEARCH_PLUGIN.LOGO, + euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, appRoute: WORKPLACE_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { @@ -134,11 +136,11 @@ export class EnterpriseSearchPlugin implements Plugin { if (plugins.home) { plugins.home.featureCatalogue.registerSolution({ - id: ENTERPRISE_SEARCH_PLUGIN.ID, - title: ENTERPRISE_SEARCH_PLUGIN.NAME, + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME, icon: 'logoEnterpriseSearch', - description: ENTERPRISE_SEARCH_PLUGIN.DESCRIPTION, - path: ENTERPRISE_SEARCH_PLUGIN.URL, + description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, + path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, order: 100, }); diff --git a/x-pack/plugins/enterprise_search/server/integrations.ts b/x-pack/plugins/enterprise_search/server/integrations.ts index fe8e584b65bedc..ebe98d4e805ac1 100644 --- a/x-pack/plugins/enterprise_search/server/integrations.ts +++ b/x-pack/plugins/enterprise_search/server/integrations.ts @@ -235,6 +235,24 @@ const workplaceSearchIntegrations: WorkplaceSearchIntegration[] = [ categories: ['file_storage'], uiInternalPath: '/app/enterprise_search/workplace_search/sources/add/share_point', }, + { + id: 'sharepoint_server', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.sharepointServerName', + { + defaultMessage: 'SharePoint Server', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.sharepointServerDescription', + { + defaultMessage: + 'Search over your files stored on Microsoft SharePoint Server with Workplace Search.', + } + ), + categories: ['enterprise_search', 'file_storage', 'microsoft_365'], + uiInternalPath: '/app/enterprise_search/workplace_search/sources/add/sharepoint_server', + }, { id: 'slack', title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.slackName', { diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 29a744e487f404..ef9a0cea9da60f 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -23,7 +23,7 @@ import { SecurityPluginSetup } from '../../security/server'; import { SpacesPluginStart } from '../../spaces/server'; import { - ENTERPRISE_SEARCH_PLUGIN, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, LOGS_SOURCE_ID, @@ -101,17 +101,21 @@ export class EnterpriseSearchPlugin implements Plugin { * Register space/feature control */ features.registerKibanaFeature({ - id: ENTERPRISE_SEARCH_PLUGIN.ID, - name: ENTERPRISE_SEARCH_PLUGIN.NAME, + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + name: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME, order: 0, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, app: [ 'kibana', - ENTERPRISE_SEARCH_PLUGIN.ID, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + APP_SEARCH_PLUGIN.ID, + WORKPLACE_SEARCH_PLUGIN.ID, + ], + catalogue: [ + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, APP_SEARCH_PLUGIN.ID, WORKPLACE_SEARCH_PLUGIN.ID, ], - catalogue: [ENTERPRISE_SEARCH_PLUGIN.ID, APP_SEARCH_PLUGIN.ID, WORKPLACE_SEARCH_PLUGIN.ID], privileges: null, }); diff --git a/x-pack/plugins/fleet/.storybook/context/execution_context.ts b/x-pack/plugins/fleet/.storybook/context/execution_context.ts new file mode 100644 index 00000000000000..d3a15e200129bb --- /dev/null +++ b/x-pack/plugins/fleet/.storybook/context/execution_context.ts @@ -0,0 +1,27 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { ExecutionContextSetup } from 'kibana/public'; +import { of } from 'rxjs'; + +export const getExecutionContext = () => { + const exec: ExecutionContextSetup = { + context$: of({}), + get: () => { + return {}; + }, + clear: () => {}, + set: (context: Record) => {}, + getAsLabels: () => { + return {}; + }, + withGlobalContext: () => { + return {}; + }, + }; + + return exec; +}; diff --git a/x-pack/plugins/fleet/.storybook/context/index.tsx b/x-pack/plugins/fleet/.storybook/context/index.tsx index eb19a1145ba751..fbcbd4fd3a0811 100644 --- a/x-pack/plugins/fleet/.storybook/context/index.tsx +++ b/x-pack/plugins/fleet/.storybook/context/index.tsx @@ -31,6 +31,7 @@ import { stubbedStartServices } from './stubs'; import { getDocLinks } from './doc_links'; import { getCloud } from './cloud'; import { getShare } from './share'; +import { getExecutionContext } from './execution_context'; // TODO: clintandrewhall - this is not ideal, or complete. The root context of Fleet applications // requires full start contracts of its dependencies. As a result, we have to mock all of those contracts @@ -52,6 +53,7 @@ export const StorybookContext: React.FC<{ storyContext?: StoryContext }> = ({ () => ({ ...stubbedStartServices, application: getApplication(), + executionContext: getExecutionContext(), chrome: getChrome(), cloud: { ...getCloud({ isCloudEnabled }), diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx index 3a1c2dd36812f6..89f7d4795429a5 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx @@ -25,11 +25,13 @@ import { init as initHttp } from '../public/application/services/http'; import { init as initUiMetric } from '../public/application/services/ui_metric'; import { KibanaContextProvider } from '../public/shared_imports'; import { PolicyListContextProvider } from '../public/application/sections/policy_list/policy_list_context'; +import { executionContextServiceMock } from 'src/core/public/execution_context/execution_context_service.mock'; initHttp( new HttpService().setup({ injectedMetadata: injectedMetadataServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), + executionContext: executionContextServiceMock.createSetupContract(), }) ); initUiMetric(usageCollectionPluginMock.createSetupContract()); diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts index 11811c7b7d26cd..b14dd17d3c11c9 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts @@ -74,6 +74,7 @@ async function fetchTemplates( const response = isLegacy ? await client.indices.getTemplate({}, options) : await client.indices.getIndexTemplate({}, options); + // @ts-expect-error TemplateSerialized.index_patterns not compatible with IndicesIndexTemplate.index_patterns return response; } diff --git a/x-pack/plugins/index_management/server/routes/api/component_templates/register_get_route.ts b/x-pack/plugins/index_management/server/routes/api/component_templates/register_get_route.ts index 039eb24f4d9d6b..9e54e80c714849 100644 --- a/x-pack/plugins/index_management/server/routes/api/component_templates/register_get_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/component_templates/register_get_route.ts @@ -36,6 +36,7 @@ export function registerGetAllRoute({ router, lib: { handleEsError } }: RouteDep const body = componentTemplates.map((componentTemplate: ComponentTemplateFromEs) => { const deserializedComponentTemplateListItem = deserializeComponentTemplateList( componentTemplate, + // @ts-expect-error TemplateSerialized.index_patterns not compatible with IndicesIndexTemplate.index_patterns indexTemplates ); return deserializedComponentTemplateListItem; @@ -70,6 +71,7 @@ export function registerGetAllRoute({ router, lib: { handleEsError } }: RouteDep await client.asCurrentUser.indices.getIndexTemplate(); return response.ok({ + // @ts-expect-error TemplateSerialized.index_patterns not compatible with IndicesIndexTemplate.index_patterns body: deserializeComponentTemplate(componentTemplates[0], indexTemplates), }); } catch (error) { diff --git a/x-pack/plugins/index_management/server/routes/api/templates/register_get_routes.ts b/x-pack/plugins/index_management/server/routes/api/templates/register_get_routes.ts index 8eedcee590fd58..93d65e162da710 100644 --- a/x-pack/plugins/index_management/server/routes/api/templates/register_get_routes.ts +++ b/x-pack/plugins/index_management/server/routes/api/templates/register_get_routes.ts @@ -34,6 +34,7 @@ export function registerGetAllRoute({ router, lib: { handleEsError } }: RouteDep legacyTemplatesEs, cloudManagedTemplatePrefix ); + // @ts-expect-error TemplateSerialized.index_patterns not compatible with IndicesIndexTemplate.index_patterns const templates = deserializeTemplateList(templatesEs, cloudManagedTemplatePrefix); const body = { @@ -92,6 +93,7 @@ export function registerGetOneRoute({ router, lib: { handleEsError } }: RouteDep if (indexTemplates.length > 0) { return response.ok({ body: deserializeTemplate( + // @ts-expect-error TemplateSerialized.index_patterns not compatible with IndicesIndexTemplate.index_patterns { ...indexTemplates[0].index_template, name }, cloudManagedTemplatePrefix ), diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts index 2a87c9cbca994f..3e1be0196231a4 100644 --- a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts @@ -83,7 +83,9 @@ export class KibanaMetricsAdapter implements InfraMetricsAdapter { series: panel.series.map((series) => { return { id: series.id, - label: series.label, + // In case of grouping by multiple fields, "series.label" is array. + // If infra will perform this type of grouping, the following code needs to be updated + label: [series.label].flat()[0], data: series.data.map((point) => ({ timestamp: point[0] as number, value: point[1] as number | null, diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 3660c3d3db0cbf..5ef9e05cf590b0 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -13,7 +13,7 @@ import { createKbnUrlStateStorage, withNotifyOnErrors, } from '../../../../../src/plugins/kibana_utils/public'; -import { useKibana } from '../../../../../src/plugins/kibana_react/public'; +import { useExecutionContext, useKibana } from '../../../../../src/plugins/kibana_react/public'; import { OnSaveProps } from '../../../../../src/plugins/saved_objects/public'; import { syncQueryStateWithUrl } from '../../../../../src/plugins/data/public'; import { LensAppProps, LensAppServices } from './types'; @@ -71,6 +71,7 @@ export function App({ getOriginatingAppName, spaces, http, + executionContext, // Temporarily required until the 'by value' paradigm is default. dashboardFeatureFlag, } = lensAppServices; @@ -111,6 +112,7 @@ export function App({ undefined ); const [isGoBackToVizEditorModalVisible, setIsGoBackToVizEditorModalVisible] = useState(false); + const savedObjectId = (initialInput as LensByReferenceInput)?.savedObjectId; useEffect(() => { if (currentDoc) { @@ -122,6 +124,12 @@ export function App({ setIndicateNoData(true); }, [setIndicateNoData]); + useExecutionContext(executionContext, { + type: 'application', + id: savedObjectId || 'new', + page: 'editor', + }); + useEffect(() => { if (indicateNoData) { setIndicateNoData(false); @@ -132,11 +140,9 @@ export function App({ () => Boolean( // Temporarily required until the 'by value' paradigm is default. - dashboardFeatureFlag.allowByValueEmbeddables && - isLinkedToOriginatingApp && - !(initialInput as LensByReferenceInput)?.savedObjectId + dashboardFeatureFlag.allowByValueEmbeddables && isLinkedToOriginatingApp && !savedObjectId ), - [dashboardFeatureFlag.allowByValueEmbeddables, isLinkedToOriginatingApp, initialInput] + [dashboardFeatureFlag.allowByValueEmbeddables, isLinkedToOriginatingApp, savedObjectId] ); useEffect(() => { diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index 28db5e9f4c43a3..6f2fd4e8026ad9 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -77,6 +77,7 @@ export async function getLensServices( usageCollection, savedObjectsTagging, attributeService, + executionContext: coreStart.executionContext, http: coreStart.http, chrome: coreStart.chrome, overlays: coreStart.overlays, diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts index bdd7bebd991e78..25fff038c4814e 100644 --- a/x-pack/plugins/lens/public/app_plugin/types.ts +++ b/x-pack/plugins/lens/public/app_plugin/types.ts @@ -12,6 +12,7 @@ import type { ApplicationStart, AppMountParameters, ChromeStart, + ExecutionContextStart, HttpStart, IUiSettingsClient, NotificationsStart, @@ -114,6 +115,7 @@ export interface HistoryLocationState { export interface LensAppServices { http: HttpStart; + executionContext: ExecutionContextStart; chrome: ChromeStart; overlays: OverlayStart; storage: IStorageWrapper; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index c25b8b72640776..72639f3582583a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -1604,7 +1604,7 @@ describe('IndexPattern Data Source suggestions', () => { const updatedContext = [ { ...context[0], - splitField: 'source', + splitFields: ['source'], splitMode: 'terms', termsParams: { size: 10, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts index 0e6fbf02a491ef..8e4017a583a910 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts @@ -181,10 +181,16 @@ function createNewTimeseriesLayerWithMetricAggregationFromVizEditor( ): IndexPatternLayer | undefined { const { timeFieldName, splitMode, splitFilters, metrics, timeInterval } = layer; const dateField = indexPattern.getFieldByName(timeFieldName!); - const splitField = layer.splitField ? indexPattern.getFieldByName(layer.splitField) : null; + + const splitFields = layer.splitFields + ? (layer.splitFields + .map((item) => indexPattern.getFieldByName(item)) + .filter(Boolean) as IndexPatternField[]) + : null; + // generate the layer for split by terms - if (splitMode === 'terms' && splitField) { - return getSplitByTermsLayer(indexPattern, splitField, dateField, layer); + if (splitMode === 'terms' && splitFields?.length) { + return getSplitByTermsLayer(indexPattern, splitFields, dateField, layer); // generate the layer for split by filters } else if (splitMode?.includes('filter') && splitFilters && splitFilters.length) { return getSplitByFiltersLayer(indexPattern, dateField, layer); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx index 78129cc8c12330..6f2a2acf3edf0c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx @@ -322,11 +322,13 @@ export const termsOperation: OperationDefinition { }) ); }); + + it('should preserve custom label when set by the user', () => { + const updateLayerSpy = jest.fn(); + const existingFields = getExistingFields(); + const operationSupportMatrix = getDefaultOperationSupportMatrix('col1', existingFields); + + layer.columns.col1 = { + label: 'MyCustomLabel', + customLabel: true, + dataType: 'string', + isBucketed: true, + operationType: 'terms', + params: { + orderBy: { type: 'alphabetical' }, + size: 3, + orderDirection: 'asc', + secondaryFields: ['geo.src'], + }, + sourceField: 'source', + } as TermsIndexPatternColumn; + let instance = mount( + + ); + // add a new field + act(() => { + instance.find('[data-test-subj="indexPattern-terms-add-field"]').first().simulate('click'); + }); + instance = instance.update(); + + act(() => { + instance.find(EuiComboBox).last().prop('onChange')!([ + { value: { type: 'field', field: 'bytes' }, label: 'bytes' }, + ]); + }); + + expect(updateLayerSpy).toHaveBeenCalledWith( + expect.objectContaining({ + columns: expect.objectContaining({ + col1: expect.objectContaining({ + label: 'MyCustomLabel', + }), + }), + }) + ); + }); }); describe('param editor', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index ab7ee8992f2fe8..5f51b531231704 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -1672,12 +1672,13 @@ export function computeLayerFromContext( export function getSplitByTermsLayer( indexPattern: IndexPattern, - splitField: IndexPatternField, + splitFields: IndexPatternField[], dateField: IndexPatternField | undefined, layer: VisualizeEditorLayersContext ): IndexPatternLayer { const { termsParams, metrics, timeInterval, splitWithDateHistogram } = layer; const copyMetricsArray = [...metrics]; + const computedLayer = computeLayerFromContext( metrics.length === 1, copyMetricsArray, @@ -1686,7 +1687,9 @@ export function getSplitByTermsLayer( layer.label ); + const [baseField, ...secondaryFields] = splitFields; const columnId = generateId(); + let termsLayer = insertNewColumn({ op: splitWithDateHistogram ? 'date_histogram' : 'terms', layer: insertNewColumn({ @@ -1701,10 +1704,22 @@ export function getSplitByTermsLayer( }, }), columnId, - field: splitField, + field: baseField, indexPattern, visualizationGroups: [], }); + + if (secondaryFields.length) { + termsLayer = updateColumnParam({ + layer: termsLayer, + columnId, + paramName: 'secondaryFields', + value: secondaryFields.map((i) => i.name), + }); + + termsLayer = updateDefaultLabels(termsLayer, indexPattern); + } + const termsColumnParams = termsParams as TermsIndexPatternColumn['params']; if (termsColumnParams) { for (const [param, value] of Object.entries(termsColumnParams)) { diff --git a/x-pack/plugins/lens/public/mocks/services_mock.tsx b/x-pack/plugins/lens/public/mocks/services_mock.tsx index 9fa6d61370a17c..6681811744da42 100644 --- a/x-pack/plugins/lens/public/mocks/services_mock.tsx +++ b/x-pack/plugins/lens/public/mocks/services_mock.tsx @@ -112,6 +112,7 @@ export function makeDefaultServices( chrome: core.chrome, overlays: core.overlays, uiSettings: core.uiSettings, + executionContext: core.executionContext, navigation: navigationStartMock, notifications: core.notifications, attributeService: makeAttributeService(), diff --git a/x-pack/plugins/lens/public/shared_components/toolbar_popover.scss b/x-pack/plugins/lens/public/shared_components/toolbar_popover.scss index a11e3373df4679..c06f13dfc2eb11 100644 --- a/x-pack/plugins/lens/public/shared_components/toolbar_popover.scss +++ b/x-pack/plugins/lens/public/shared_components/toolbar_popover.scss @@ -1,3 +1,3 @@ .lnsVisToolbar__popover { - width: 365px; + width: 404px; } diff --git a/x-pack/plugins/lens/public/xy_visualization/color_assignment.ts b/x-pack/plugins/lens/public/xy_visualization/color_assignment.ts index e1e2ba75b50c40..2c567254384219 100644 --- a/x-pack/plugins/lens/public/xy_visualization/color_assignment.ts +++ b/x-pack/plugins/lens/public/xy_visualization/color_assignment.ts @@ -59,6 +59,7 @@ export function getColorAssignments( } const splitAccessor = layer.splitAccessor; const column = data.tables[layer.layerId]?.columns.find(({ id }) => id === splitAccessor); + const columnFormatter = column && formatFactory(column.meta.params); const splits = !column || !data.tables[layer.layerId] ? [] @@ -66,7 +67,7 @@ export function getColorAssignments( data.tables[layer.layerId].rows.map((row) => { let value = row[splitAccessor]; if (value && !isPrimitive(value)) { - value = formatFactory(column.meta.params).convert(value); + value = columnFormatter?.convert(value) ?? value; } else { value = String(value); } diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx index ea0e336ff2f08a..fb8ad127a394ef 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx @@ -42,11 +42,13 @@ import type { ExpressionRenderDefinition, Datatable, DatatableRow, + DatatableColumn, } from 'src/plugins/expressions/public'; import { IconType } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { RenderMode } from 'src/plugins/expressions'; import { ThemeServiceStart } from 'kibana/public'; +import { FieldFormat } from 'src/plugins/field_formats/common'; import { EmptyPlaceholder } from '../../../../../src/plugins/charts/public'; import { KibanaThemeProvider } from '../../../../../src/plugins/kibana_react/public'; import type { ILensInterpreterRenderHandlers, LensFilterEvent, LensBrushEvent } from '../types'; @@ -599,6 +601,7 @@ export function XYChart({ : undefined, }, }; + return ( (); + for (const column of table.columns) { + formatterPerColumn.set(column, formatFactory(column.meta.params)); + } + // what if row values are not primitive? That is the case of, for instance, Ranges // remaps them to their serialized version with the formatHint metadata // In order to do it we need to make a copy of the table as the raw one is required for more features (filters, etc...) later on @@ -744,7 +752,7 @@ export function XYChart({ // pre-format values for ordinal x axes because there can only be a single x axis formatter on chart level (!isPrimitive(record) || (column.id === xAccessor && xScaleType === 'ordinal')) ) { - newRow[column.id] = formatFactory(column.meta.params).convert(record); + newRow[column.id] = formatterPerColumn.get(column)!.convert(record); } } return newRow; @@ -798,6 +806,8 @@ export function XYChart({ ); const formatter = table?.columns.find((column) => column.id === accessor)?.meta?.params; + const splitHint = table.columns.find((col) => col.id === splitAccessor)?.meta?.params; + const splitFormatter = formatFactory(splitHint); const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], @@ -857,8 +867,6 @@ export function XYChart({ }, }, name(d) { - const splitHint = table.columns.find((col) => col.id === splitAccessor)?.meta?.params; - // For multiple y series, the name of the operation is used on each, either: // * Key - Y name // * Formatted value - Y name @@ -871,7 +879,7 @@ export function XYChart({ splitAccessor && !layersAlreadyFormatted[splitAccessor] ) { - return formatFactory(splitHint).convert(key); + return splitFormatter.convert(key); } return splitAccessor && i === 0 ? key : columnToLabelMap[key] ?? ''; }) @@ -885,7 +893,7 @@ export function XYChart({ if (splitAccessor && layersAlreadyFormatted[splitAccessor]) { return d.seriesKeys[0]; } - return formatFactory(splitHint).convert(d.seriesKeys[0]); + return splitFormatter.convert(d.seriesKeys[0]); } // This handles both split and single-y cases: // * If split series without formatting, show the value literally diff --git a/x-pack/plugins/maps/common/execution_context.test.ts b/x-pack/plugins/maps/common/execution_context.test.ts new file mode 100644 index 00000000000000..25e3813a7e8f01 --- /dev/null +++ b/x-pack/plugins/maps/common/execution_context.test.ts @@ -0,0 +1,36 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { makeExecutionContext } from './execution_context'; + +describe('makeExecutionContext', () => { + test('returns basic fields if nothing is provided', () => { + const context = makeExecutionContext({}); + expect(context).toStrictEqual({ + name: 'maps', + type: 'application', + }); + }); + + test('merges in context', () => { + const context = makeExecutionContext({ id: '123' }); + expect(context).toStrictEqual({ + name: 'maps', + type: 'application', + id: '123', + }); + }); + + test('omits undefined values', () => { + const context = makeExecutionContext({ id: '123', description: undefined }); + expect(context).toStrictEqual({ + name: 'maps', + type: 'application', + id: '123', + }); + }); +}); diff --git a/x-pack/plugins/maps/common/execution_context.ts b/x-pack/plugins/maps/common/execution_context.ts index 23de29cfa8cd7d..4a11eb5d890295 100644 --- a/x-pack/plugins/maps/common/execution_context.ts +++ b/x-pack/plugins/maps/common/execution_context.ts @@ -5,14 +5,16 @@ * 2.0. */ +import { isUndefined, omitBy } from 'lodash'; import { APP_ID } from './constants'; -export function makeExecutionContext(id: string, url: string, description?: string) { - return { - name: APP_ID, - type: 'application', - id, - description: description || '', - url, - }; +export function makeExecutionContext(context: { id?: string; url?: string; description?: string }) { + return omitBy( + { + name: APP_ID, + type: 'application', + ...context, + }, + isUndefined + ); } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index e2f9959b25d31d..a26bd341613b2d 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -5,8 +5,14 @@ * 2.0. */ +import { coreMock } from '../../../../../../../src/core/public/mocks'; import { MapExtent, VectorSourceRequestMeta } from '../../../../common/descriptor_types'; -import { getHttp, getIndexPatternService, getSearchService } from '../../../kibana_services'; +import { + getExecutionContext, + getHttp, + getIndexPatternService, + getSearchService, +} from '../../../kibana_services'; import { ESGeoGridSource } from './es_geo_grid_source'; import { ES_GEO_FIELD_TYPE, @@ -129,6 +135,13 @@ describe('ESGeoGridSource', () => { }, }, }); + + const coreStartMock = coreMock.createStart(); + coreStartMock.executionContext.get.mockReturnValue({ + name: 'some-app', + }); + // @ts-expect-error + getExecutionContext.mockReturnValue(coreStartMock.executionContext); }); afterEach(() => { diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 54e4964b35f03f..d8197902c73ace 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -33,6 +33,7 @@ export const getUiSettings = () => coreStart.uiSettings; export const getIsDarkMode = () => getUiSettings().get('theme:darkMode', false); export const getIndexPatternSelectComponent = () => pluginsStart.data.ui.IndexPatternSelect; export const getHttp = () => coreStart.http; +export const getExecutionContext = () => coreStart.executionContext; export const getTimeFilter = () => pluginsStart.data.query.timefilter.timefilter; export const getToasts = () => coreStart.notifications.toasts; export const getSavedObjectsClient = () => coreStart.savedObjects.client; diff --git a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx index 571cba64a06c45..dab284b0b71e46 100644 --- a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx +++ b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx @@ -17,6 +17,7 @@ import { getMapsCapabilities, getToasts, getCoreChrome, + getExecutionContext, getNavigateToApp, getSavedObjectsClient, getSavedObjectsTagging, @@ -121,6 +122,12 @@ async function deleteMaps(items: object[]) { } export function MapsListView() { + getExecutionContext().set({ + type: 'application', + page: 'list', + id: '', + }); + const isReadOnly = !getMapsCapabilities().save; getCoreChrome().docTitle.change(getAppTitle()); diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 9aede248e1877d..a341246f748f3a 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -16,6 +16,7 @@ import { type Filter, FilterStateStore } from '@kbn/es-query'; import type { Query, TimeRange, DataView } from 'src/plugins/data/common'; import { getData, + getExecutionContext, getCoreChrome, getMapsCapabilities, getNavigation, @@ -115,6 +116,12 @@ export class MapApp extends React.Component { componentDidMount() { this._isMounted = true; + getExecutionContext().set({ + type: 'application', + page: 'editor', + id: this.props.savedMap.getSavedObjectId() || 'new', + }); + this._autoRefreshSubscription = getTimeFilter() .getAutoRefreshFetch$() .pipe( diff --git a/x-pack/plugins/maps/public/util.test.js b/x-pack/plugins/maps/public/util.test.js index d8861063fc637c..7fc88578b378ae 100644 --- a/x-pack/plugins/maps/public/util.test.js +++ b/x-pack/plugins/maps/public/util.test.js @@ -5,7 +5,7 @@ * 2.0. */ -import { getGlyphUrl } from './util'; +import { getGlyphUrl, makePublicExecutionContext } from './util'; const MOCK_EMS_SETTINGS = { isEMSEnabled: () => true, @@ -62,3 +62,55 @@ describe('getGlyphUrl', () => { }); }); }); + +describe('makePublicExecutionContext', () => { + let injectedContext = {}; + beforeAll(() => { + require('./kibana_services').getExecutionContext = () => ({ + get: () => injectedContext, + }); + }); + + test('creates basic context when no top level context is provided', () => { + const context = makePublicExecutionContext('test'); + expect(context).toStrictEqual({ + description: 'test', + name: 'maps', + type: 'application', + url: '/', + }); + }); + + test('merges with top level context if its from the same app', () => { + injectedContext = { + name: 'maps', + id: '1234', + }; + const context = makePublicExecutionContext('test'); + expect(context).toStrictEqual({ + description: 'test', + name: 'maps', + type: 'application', + url: '/', + id: '1234', + }); + }); + + test('nests inside top level context if its from a different app', () => { + injectedContext = { + name: 'other-app', + id: '1234', + }; + const context = makePublicExecutionContext('test'); + expect(context).toStrictEqual({ + name: 'other-app', + id: '1234', + child: { + description: 'test', + type: 'application', + name: 'maps', + url: '/', + }, + }); + }); +}); diff --git a/x-pack/plugins/maps/public/util.ts b/x-pack/plugins/maps/public/util.ts index 4adb8b35bfcea2..66244ea5f67685 100644 --- a/x-pack/plugins/maps/public/util.ts +++ b/x-pack/plugins/maps/public/util.ts @@ -8,7 +8,13 @@ import { EMSClient, FileLayer, TMSService } from '@elastic/ems-client'; import type { KibanaExecutionContext } from 'kibana/public'; import { FONTS_API_PATH } from '../common/constants'; -import { getHttp, getTilemap, getEMSSettings, getMapsEmsStart } from './kibana_services'; +import { + getHttp, + getTilemap, + getEMSSettings, + getMapsEmsStart, + getExecutionContext, +} from './kibana_services'; import { getLicenseId } from './licensed_features'; import { makeExecutionContext } from '../common/execution_context'; @@ -67,9 +73,21 @@ export function isRetina(): boolean { return window.devicePixelRatio === 2; } -export function makePublicExecutionContext( - id: string, - description?: string -): KibanaExecutionContext { - return makeExecutionContext(id, window.location.pathname, description); +export function makePublicExecutionContext(description: string): KibanaExecutionContext { + const topLevelContext = getExecutionContext().get(); + const context = makeExecutionContext({ + url: window.location.pathname, + description, + }); + + // Distinguish between running in maps app vs. embedded + return topLevelContext.name !== undefined && topLevelContext.name !== context.name + ? { + ...topLevelContext, + child: context, + } + : { + ...topLevelContext, + ...context, + }; } diff --git a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts index 193a3d74e2dca2..28effa5eabfba8 100644 --- a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts @@ -56,7 +56,10 @@ export async function getEsGridTile({ }; const tile = await core.executionContext.withContext( - makeExecutionContext('mvt:get_grid_tile', url), + makeExecutionContext({ + description: 'mvt:get_grid_tile', + url, + }), async () => { return await context.core.elasticsearch.client.asCurrentUser.transport.request( { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 2c8b6dd4b113d6..7e9bc01c5c317c 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -57,7 +57,10 @@ export async function getEsTile({ }; const tile = await core.executionContext.withContext( - makeExecutionContext('mvt:get_tile', url), + makeExecutionContext({ + description: 'mvt:get_tile', + url, + }), async () => { return await context.core.elasticsearch.client.asCurrentUser.transport.request( { diff --git a/x-pack/plugins/ml/public/application/components/model_snapshots/revert_model_snapshot_flyout/revert_model_snapshot_flyout.tsx b/x-pack/plugins/ml/public/application/components/model_snapshots/revert_model_snapshot_flyout/revert_model_snapshot_flyout.tsx index 498a27834d050f..9305927618872f 100644 --- a/x-pack/plugins/ml/public/application/components/model_snapshots/revert_model_snapshot_flyout/revert_model_snapshot_flyout.tsx +++ b/x-pack/plugins/ml/public/application/components/model_snapshots/revert_model_snapshot_flyout/revert_model_snapshot_flyout.tsx @@ -230,7 +230,7 @@ export const RevertModelSnapshotFlyout: FC = ({ fadeChart={true} overlayRanges={[ { - start: currentSnapshot.latest_record_time_stamp, + start: currentSnapshot.latest_record_time_stamp!, end: job.data_counts.latest_record_timestamp!, color: '#ff0000', }, @@ -253,7 +253,7 @@ export const RevertModelSnapshotFlyout: FC = ({ @@ -333,7 +333,7 @@ export const RevertModelSnapshotFlyout: FC = ({ ({ ...acc, [d.field]: d.value }), {}); const [openActionsPopoverId, setActionsPopover] = useState(null); const { - timelines, + cases, application: {}, - } = useKibana().services; + } = useKibana().services; const parseObservabilityAlert = useMemo( () => parseAlert(observabilityRuleTypeRegistry), @@ -158,10 +161,6 @@ function ObservabilityActions({ const alert = parseObservabilityAlert(dataFieldEs); const { prepend } = core.http.basePath; - const afterCaseSelection = useCallback(() => { - setActionsPopover(null); - }, []); - const closeActionsPopover = useCallback(() => { setActionsPopover(null); }, []); @@ -171,35 +170,59 @@ function ObservabilityActions({ }, []); const casePermissions = useGetUserCasesPermissions(); - const event = useMemo(() => { - return { - data, - _id: eventId, - ecs: ecsData, - }; - }, [data, eventId, ecsData]); - const ruleId = alert.fields['kibana.alert.rule.uuid'] ?? null; const linkToRule = ruleId ? prepend(paths.management.ruleDetails(ruleId)) : null; + const caseAttachments: CaseAttachments = useMemo(() => { + return ecsData?._id + ? [ + { + alertId: ecsData?._id ?? '', + index: ecsData?._index ?? '', + owner: observabilityFeatureId, + type: CommentType.alert, + rule: cases.helpers.getRuleIdFromEvent({ ecs: ecsData, data: data ?? [] }), + }, + ] + : []; + }, [ecsData, cases.helpers, data]); + + const createCaseFlyout = cases.hooks.getUseCasesAddToNewCaseFlyout({ + attachments: caseAttachments, + }); + + const selectCaseModal = cases.hooks.getUseCasesAddToExistingCaseModal({ + attachments: caseAttachments, + }); + + const handleAddToNewCaseClick = useCallback(() => { + createCaseFlyout.open(); + closeActionsPopover(); + }, [createCaseFlyout, closeActionsPopover]); + + const handleAddToExistingCaseClick = useCallback(() => { + selectCaseModal.open(); + closeActionsPopover(); + }, [closeActionsPopover, selectCaseModal]); + const actionsMenuItems = useMemo(() => { return [ ...(casePermissions?.crud ? [ - timelines.getAddToExistingCaseButton({ - event, - casePermissions, - appId: observabilityAppId, - owner: observabilityFeatureId, - onClose: afterCaseSelection, - }), - timelines.getAddToNewCaseButton({ - event, - casePermissions, - appId: observabilityAppId, - owner: observabilityFeatureId, - onClose: afterCaseSelection, - }), + + {ADD_TO_EXISTING_CASE} + , + + {ADD_TO_NEW_CASE} + , ] : []), @@ -215,7 +238,7 @@ function ObservabilityActions({ ] : []), ]; - }, [afterCaseSelection, casePermissions, timelines, event, linkToRule]); + }, [casePermissions?.crud, handleAddToExistingCaseClick, handleAddToNewCaseClick, linkToRule]); const actionsToolTip = actionsMenuItems.length <= 0 diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/translations.ts b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/translations.ts new file mode 100644 index 00000000000000..c72dc4c9437592 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_table_t_grid/translations.ts @@ -0,0 +1,22 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const ADD_TO_EXISTING_CASE = i18n.translate( + 'xpack.observability.detectionEngine.alerts.actions.addToCase', + { + defaultMessage: 'Add to existing case', + } +); + +export const ADD_TO_NEW_CASE = i18n.translate( + 'xpack.observability.detectionEngine.alerts.actions.addToNewCase', + { + defaultMessage: 'Add to new case', + } +); diff --git a/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx index 4d4ef5b8148438..ac5900ca3dc6ae 100644 --- a/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx +++ b/x-pack/plugins/observability/public/pages/overview/old_overview_page.tsx @@ -8,6 +8,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiHorizontalRule } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useMemo, useRef, useCallback } from 'react'; +import { observabilityFeatureId } from '../../../common'; +import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { useTrackPageview } from '../..'; import { EmptySections } from '../../components/app/empty_sections'; import { ObservabilityHeaderMenu } from '../../components/app/header'; @@ -28,6 +30,8 @@ import { DataSections } from './data_sections'; import { LoadingObservability } from './loading_observability'; import { AlertsTableTGrid } from '../alerts/containers/alerts_table_t_grid/alerts_table_t_grid'; import { SectionContainer } from '../../components/app/section'; +import { ObservabilityAppServices } from '../../application/types'; +import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions'; interface Props { routeParams: RouteParams<'/overview'>; } @@ -85,6 +89,10 @@ export function OverviewPage({ routeParams }: Props) { return refetch.current && refetch.current(); }, []); + const kibana = useKibana(); + const CasesContext = kibana.services.cases.getCasesContext(); + const userPermissions = useGetUserCasesPermissions(); + if (hasAnyData === undefined) { return ; } @@ -130,12 +138,18 @@ export function OverviewPage({ routeParams }: Props) { })} hasError={false} > - + + + diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts index 538fa3a008a1fd..69bdafd5dccddd 100644 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts @@ -5,30 +5,17 @@ * 2.0. */ -import { - getException, - getExceptionList, - expectedExportedExceptionList, -} from '../../objects/exception'; +import { getExceptionList, expectedExportedExceptionList } from '../../objects/exception'; import { getNewRule } from '../../objects/rule'; -import { RULE_STATUS } from '../../screens/create_new_rule'; - import { createCustomRule } from '../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange, waitForPageWithoutDateRange, } from '../../tasks/login'; -import { - addsExceptionFromRuleSettings, - goBackToAllRulesTable, - goToExceptionsTab, -} from '../../tasks/rule_details'; import { DETECTIONS_RULE_MANAGEMENT_URL, EXCEPTIONS_URL } from '../../urls/navigation'; -import { cleanKibana, reload } from '../../tasks/common'; +import { cleanKibana } from '../../tasks/common'; import { deleteExceptionListWithRuleReference, deleteExceptionListWithoutRuleReference, @@ -43,30 +30,47 @@ import { } from '../../screens/exceptions'; import { createExceptionList } from '../../tasks/api_calls/exceptions'; +const getExceptionList1 = () => ({ + ...getExceptionList(), + name: 'Test a new list 1', + list_id: 'exception_list_1', +}); +const getExceptionList2 = () => ({ + ...getExceptionList(), + name: 'Test list 2', + list_id: 'exception_list_2', +}); + describe('Exceptions Table', () => { before(() => { cleanKibana(); loginAndWaitForPageWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - createCustomRule(getNewRule()); - reload(); - goToRuleDetails(); - cy.get(RULE_STATUS).should('have.text', '—'); - - esArchiverLoad('auditbeat_for_exceptions'); - - // Add a detections exception list - goToExceptionsTab(); - addsExceptionFromRuleSettings(getException()); + // Create exception list associated with a rule + createExceptionList(getExceptionList2(), getExceptionList2().list_id).then((response) => + createCustomRule({ + ...getNewRule(), + exceptionLists: [ + { + id: response.body.id, + list_id: getExceptionList2().list_id, + type: getExceptionList2().type, + namespace_type: getExceptionList2().namespace_type, + }, + ], + }) + ); // Create exception list not used by any rules - createExceptionList(getExceptionList(), getExceptionList().list_id).as('exceptionListResponse'); + createExceptionList(getExceptionList1(), getExceptionList1().list_id).as( + 'exceptionListResponse' + ); - goBackToAllRulesTable(); - }); + waitForPageWithoutDateRange(EXCEPTIONS_URL); - after(() => { - esArchiverUnload('auditbeat_for_exceptions'); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '3'); }); it('Exports exception list', function () { @@ -87,60 +91,80 @@ describe('Exceptions Table', () => { waitForPageWithoutDateRange(EXCEPTIONS_URL); waitForExceptionsTableToBeLoaded(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 3 lists`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '3'); // Single word search searchForExceptionList('Endpoint'); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 1 list`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1'); cy.get(EXCEPTIONS_TABLE_LIST_NAME).should('have.text', 'Endpoint Security Exception List'); // Multi word search clearSearchSelection(); - searchForExceptionList('New Rule Test'); + searchForExceptionList('test'); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 2 lists`); - cy.get(EXCEPTIONS_TABLE_LIST_NAME).eq(0).should('have.text', 'Test exception list'); - cy.get(EXCEPTIONS_TABLE_LIST_NAME).eq(1).should('have.text', 'New Rule Test'); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '2'); + cy.get(EXCEPTIONS_TABLE_LIST_NAME).eq(1).should('have.text', 'Test list 2'); + cy.get(EXCEPTIONS_TABLE_LIST_NAME).eq(0).should('have.text', 'Test a new list 1'); // Exact phrase search clearSearchSelection(); - searchForExceptionList('"New Rule Test"'); + searchForExceptionList(`"${getExceptionList1().name}"`); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 1 list`); - cy.get(EXCEPTIONS_TABLE_LIST_NAME).should('have.text', 'New Rule Test'); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1'); + cy.get(EXCEPTIONS_TABLE_LIST_NAME).should('have.text', getExceptionList1().name); // Field search clearSearchSelection(); searchForExceptionList('list_id:endpoint_list'); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 1 list`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1'); cy.get(EXCEPTIONS_TABLE_LIST_NAME).should('have.text', 'Endpoint Security Exception List'); clearSearchSelection(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 3 lists`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '3'); }); it('Deletes exception list without rule reference', () => { waitForPageWithoutDateRange(EXCEPTIONS_URL); waitForExceptionsTableToBeLoaded(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 3 lists`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '3'); deleteExceptionListWithoutRuleReference(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 2 lists`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '2'); }); it('Deletes exception list with rule reference', () => { waitForPageWithoutDateRange(EXCEPTIONS_URL); waitForExceptionsTableToBeLoaded(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 2 lists`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '2'); deleteExceptionListWithRuleReference(); - cy.get(EXCEPTIONS_TABLE_SHOWING_LISTS).should('have.text', `Showing 1 list`); + // Using cy.contains because we do not care about the exact text, + // just checking number of lists shown + cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1'); }); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/exception.ts b/x-pack/plugins/security_solution/cypress/objects/exception.ts index 1a70bb10383203..fbb000f43fdd23 100644 --- a/x-pack/plugins/security_solution/cypress/objects/exception.ts +++ b/x-pack/plugins/security_solution/cypress/objects/exception.ts @@ -41,5 +41,5 @@ export const expectedExportedExceptionList = ( exceptionListResponse: Cypress.Response ): string => { const jsonrule = exceptionListResponse.body; - return `{"_version":"${jsonrule._version}","created_at":"${jsonrule.created_at}","created_by":"elastic","description":"${jsonrule.description}","id":"${jsonrule.id}","immutable":false,"list_id":"test_exception_list","name":"Test exception list","namespace_type":"single","os_types":[],"tags":[],"tie_breaker_id":"${jsonrule.tie_breaker_id}","type":"detection","updated_at":"${jsonrule.updated_at}","updated_by":"elastic","version":1}\n{"exported_exception_list_count":1,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0}\n`; + return `{"_version":"${jsonrule._version}","created_at":"${jsonrule.created_at}","created_by":"elastic","description":"${jsonrule.description}","id":"${jsonrule.id}","immutable":false,"list_id":"${jsonrule.list_id}","name":"${jsonrule.name}","namespace_type":"single","os_types":[],"tags":[],"tie_breaker_id":"${jsonrule.tie_breaker_id}","type":"${jsonrule.type}","updated_at":"${jsonrule.updated_at}","updated_by":"elastic","version":1}\n{"exported_exception_list_count":1,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0}\n`; }; diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index 2f81c160f28017..65e61c48ec64d4 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -59,6 +59,7 @@ export interface CustomRule { timeline: CompleteTimeline; maxSignals: number; buildingBlockType?: string; + exceptionLists?: Array<{ id: string; list_id: string; type: string; namespace_type: string }>; } export interface ThresholdRule extends CustomRule { diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts index 13ba3af59be9a0..405c1181403958 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts @@ -24,6 +24,7 @@ export const createCustomRule = (rule: CustomRule, ruleId = 'rule_testing', inte query: rule.customQuery, language: 'kuery', enabled: false, + exceptions_list: rule.exceptionLists ?? [], }, headers: { 'kbn-xsrf': 'cypress-creds' }, failOnStatusCode: false, diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index a9fd9a5d9d44f8..5e3fc4e81f9dc3 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -13,7 +13,7 @@ import type { Filter } from '@kbn/es-query'; import { inputsModel, inputsSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; import { ControlColumnProps, RowRenderer, TimelineId } from '../../../../common/types/timeline'; -import { APP_UI_ID } from '../../../../common/constants'; +import { APP_ID, APP_UI_ID } from '../../../../common/constants'; import { timelineSelectors, timelineActions } from '../../../timelines/store/timeline'; import type { SubsetTimelineModel, TimelineModel } from '../../../timelines/store/timeline/model'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; @@ -27,7 +27,7 @@ import { TGridCellAction } from '../../../../../timelines/common/types'; import { DetailsPanel } from '../../../timelines/components/side_panel'; import { CellValueElementProps } from '../../../timelines/components/timeline/cell_rendering'; import { FIELDS_WITHOUT_CELL_ACTIONS } from '../../lib/cell_actions/constants'; -import { useKibana } from '../../lib/kibana'; +import { useGetUserCasesPermissions, useKibana } from '../../lib/kibana'; import { GraphOverlay } from '../../../timelines/components/graph_overlay'; import { CreateFieldEditorActions, @@ -109,7 +109,7 @@ const StatefulEventsViewerComponent: React.FC = ({ unit, }) => { const dispatch = useDispatch(); - const { timelines: timelinesUi } = useKibana().services; + const { timelines: timelinesUi, cases: casesUi } = useKibana().services; const { browserFields, dataViewId, @@ -179,63 +179,68 @@ const StatefulEventsViewerComponent: React.FC = ({ const createFieldComponent = useCreateFieldButton(scopeId, id, editorActionsRef); + const casesPermissions = useGetUserCasesPermissions(); + const CasesContext = casesUi.getCasesContext(); + return ( <> - - - {timelinesUi.getTGrid<'embedded'>({ - additionalFilters, - appId: APP_UI_ID, - browserFields, - bulkActions, - columns, - dataProviders, - dataViewId, - defaultCellActions, - deletedEventIds, - disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS, - docValueFields, - end, - entityType, - filters: globalFilters, - filterStatus: currentFilter, - globalFullScreen, - graphEventId, - graphOverlay, - hasAlertsCrud, - id, - indexNames: selectedPatterns, - indexPattern, - isLive, - isLoadingIndexPattern, - itemsPerPage, - itemsPerPageOptions, - kqlMode, - leadingControlColumns, - onRuleChange, - query, - renderCellValue, - rowRenderers, - runtimeMappings, - setQuery, - sort, - start, - tGridEventRenderedViewEnabled, - trailingControlColumns, - type: 'embedded', - unit, - createFieldComponent, - })} - - - + + + + {timelinesUi.getTGrid<'embedded'>({ + additionalFilters, + appId: APP_UI_ID, + browserFields, + bulkActions, + columns, + dataProviders, + dataViewId, + defaultCellActions, + deletedEventIds, + disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS, + docValueFields, + end, + entityType, + filters: globalFilters, + filterStatus: currentFilter, + globalFullScreen, + graphEventId, + graphOverlay, + hasAlertsCrud, + id, + indexNames: selectedPatterns, + indexPattern, + isLive, + isLoadingIndexPattern, + itemsPerPage, + itemsPerPageOptions, + kqlMode, + leadingControlColumns, + onRuleChange, + query, + renderCellValue, + rowRenderers, + runtimeMappings, + setQuery, + sort, + start, + tGridEventRenderedViewEnabled, + trailingControlColumns, + type: 'embedded', + unit, + createFieldComponent, + })} + + + + ); }; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts index aacc1dc9516934..b76b5ee99843e8 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts @@ -18,6 +18,7 @@ import { createWithKibanaMock, } from '../kibana_react.mock'; import { APP_UI_ID } from '../../../../../common/constants'; +import { mockCasesContract } from '../../../../../../cases/public/mocks'; const mockStartServicesMock = createStartServicesMock(); export const KibanaServices = { get: jest.fn(), getKibanaVersion: jest.fn(() => '8.0.0') }; @@ -28,6 +29,7 @@ export const useKibana = jest.fn().mockReturnValue({ get: jest.fn(), set: jest.fn(), }, + cases: mockCasesContract(), data: { ...mockStartServicesMock.data, search: { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx index 3c9d2115f7ef28..d5fc54c5cbac73 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx @@ -12,6 +12,7 @@ import { TestProviders } from '../../../../common/mock'; import React from 'react'; import { Ecs } from '../../../../../common/ecs'; import { mockTimelines } from '../../../../common/mock/mock_timelines_plugin'; +import { mockCasesContract } from '../../../../../../cases/public/mocks'; const ecsRowData: Ecs = { _id: '1', @@ -51,6 +52,7 @@ jest.mock('../../../../common/lib/kibana', () => ({ application: { capabilities: { siem: { crud_alerts: true, read_alerts: true } }, }, + cases: mockCasesContract(), }, }), useGetUserCasesPermissions: jest.fn().mockReturnValue({ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index b5e630de50f79d..d472b9bf3f1915 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -33,7 +33,6 @@ import { useExceptionFlyout } from './use_add_exception_flyout'; import { useExceptionActions } from './use_add_exception_actions'; import { useEventFilterModal } from './use_event_filter_modal'; import { Status } from '../../../../../common/detection_engine/schemas/common/schemas'; -import { useKibana } from '../../../../common/lib/kibana'; import { ATTACH_ALERT_TO_CASE_FOR_ROW } from '../../../../timelines/components/timeline/body/translations'; import { useEventFilterAction } from './use_event_filter_action'; import { useAddToCaseActions } from './use_add_to_case_actions'; @@ -65,16 +64,15 @@ const AlertContextMenuComponent: React.FC { + const onMenuItemClick = useCallback(() => { setPopover(false); }, []); const ruleId = get(0, ecsRowData?.kibana?.alert?.rule?.uuid); const ruleName = get(0, ecsRowData?.kibana?.alert?.rule?.name); - const { timelines: timelinesUi } = useKibana().services; - const { addToCaseActionProps, addToCaseActionItems } = useAddToCaseActions({ + const { addToCaseActionItems } = useAddToCaseActions({ ecsData: ecsRowData, - afterCaseSelection: afterItemSelection, + onMenuItemClick, timelineId, ariaLabel: ATTACH_ALERT_TO_CASE_FOR_ROW({ ariaRowindex, columnValues }), }); @@ -186,7 +184,6 @@ const AlertContextMenuComponent: React.FC - {addToCaseActionProps && timelinesUi.getAddToCaseAction(addToCaseActionProps)} {items.length > 0 && (
diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx index cc0ef8d4e8b797..2ca4525c7e1ab5 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx @@ -5,16 +5,19 @@ * 2.0. */ -import { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; +import { EuiContextMenuItem } from '@elastic/eui'; +import { CommentType } from '../../../../../../cases/common'; +import { CaseAttachments } from '../../../../../../cases/public'; import { useGetUserCasesPermissions, useKibana } from '../../../../common/lib/kibana'; import type { TimelineNonEcsData } from '../../../../../common/search_strategy'; import { TimelineId } from '../../../../../common/types'; -import { APP_ID, APP_UI_ID } from '../../../../../common/constants'; -import { useInsertTimeline } from '../../../../cases/components/use_insert_timeline'; +import { APP_ID } from '../../../../../common/constants'; import { Ecs } from '../../../../../common/ecs'; +import { ADD_TO_EXISTING_CASE, ADD_TO_NEW_CASE } from '../translations'; export interface UseAddToCaseActions { - afterCaseSelection: () => void; + onMenuItemClick: () => void; ariaLabel?: string; ecsData?: Ecs; nonEcsData?: TimelineNonEcsData[]; @@ -22,51 +25,92 @@ export interface UseAddToCaseActions { } export const useAddToCaseActions = ({ - afterCaseSelection, + onMenuItemClick, ariaLabel, ecsData, nonEcsData, timelineId, }: UseAddToCaseActions) => { - const { timelines: timelinesUi } = useKibana().services; + const { cases: casesUi } = useKibana().services; const casePermissions = useGetUserCasesPermissions(); - const insertTimelineHook = useInsertTimeline; + const hasWritePermissions = casePermissions?.crud ?? false; - const addToCaseActionProps = useMemo( - () => - ecsData?._id - ? { - ariaLabel, - event: { data: nonEcsData ?? [], ecs: ecsData, _id: ecsData?._id }, - useInsertTimeline: insertTimelineHook, - casePermissions, - appId: APP_UI_ID, + const caseAttachments: CaseAttachments = useMemo(() => { + return ecsData?._id + ? [ + { + alertId: ecsData?._id ?? '', + index: ecsData?._index ?? '', owner: APP_ID, - onClose: afterCaseSelection, - } - : null, - [ecsData, ariaLabel, nonEcsData, insertTimelineHook, casePermissions, afterCaseSelection] - ); - const hasWritePermissions = casePermissions?.crud ?? false; - const addToCaseActionItems = useMemo( - () => + type: CommentType.alert, + rule: casesUi.helpers.getRuleIdFromEvent({ ecs: ecsData, data: nonEcsData ?? [] }), + }, + ] + : []; + }, [casesUi.helpers, ecsData, nonEcsData]); + + const createCaseFlyout = casesUi.hooks.getUseCasesAddToNewCaseFlyout({ + attachments: caseAttachments, + onClose: onMenuItemClick, + }); + + const selectCaseModal = casesUi.hooks.getUseCasesAddToExistingCaseModal({ + attachments: caseAttachments, + onClose: onMenuItemClick, + }); + + const handleAddToNewCaseClick = useCallback(() => { + // TODO rename this, this is really `closePopover()` + onMenuItemClick(); + createCaseFlyout.open(); + }, [onMenuItemClick, createCaseFlyout]); + + const handleAddToExistingCaseClick = useCallback(() => { + // TODO rename this, this is really `closePopover()` + onMenuItemClick(); + selectCaseModal.open(); + }, [onMenuItemClick, selectCaseModal]); + + const addToCaseActionItems = useMemo(() => { + if ( [ TimelineId.detectionsPage, TimelineId.detectionsRulesDetailsPage, TimelineId.active, ].includes(timelineId as TimelineId) && - hasWritePermissions && - addToCaseActionProps - ? [ - timelinesUi.getAddToExistingCaseButton(addToCaseActionProps), - timelinesUi.getAddToNewCaseButton(addToCaseActionProps), - ] - : [], - [addToCaseActionProps, hasWritePermissions, timelineId, timelinesUi] - ); + hasWritePermissions + ) { + return [ + // add to existing case menu item + + {ADD_TO_EXISTING_CASE} + , + // add to new case menu item + + {ADD_TO_NEW_CASE} + , + ]; + } + return []; + }, [ + ariaLabel, + handleAddToExistingCaseClick, + handleAddToNewCaseClick, + hasWritePermissions, + timelineId, + ]); return { addToCaseActionItems, - addToCaseActionProps, }; }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/translations.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/translations.ts index 590b5759ecae45..bdddd8ab462076 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/translations.ts @@ -285,3 +285,17 @@ export const TRIGGERED = i18n.translate( defaultMessage: 'Triggered', } ); + +export const ADD_TO_EXISTING_CASE = i18n.translate( + 'xpack.securitySolution.detectionEngine.alerts.actions.addToCase', + { + defaultMessage: 'Add to existing case', + } +); + +export const ADD_TO_NEW_CASE = i18n.translate( + 'xpack.securitySolution.detectionEngine.alerts.actions.addToNewCase', + { + defaultMessage: 'Add to new case', + } +); diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx index 0c525a2d77706a..a15a717f6f42a2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx @@ -17,6 +17,7 @@ import { TestProviders } from '../../../common/mock'; import { mockTimelines } from '../../../common/mock/mock_timelines_plugin'; import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; import { useKibana } from '../../../common/lib/kibana'; +import { mockCasesContract } from '../../../../../cases/public/mocks'; jest.mock('../user_info', () => ({ useUserData: jest.fn().mockReturnValue([{ canUserCRUD: true, hasIndexWrite: true }]), @@ -82,6 +83,7 @@ describe('take action dropdown', () => { services: { ...mockStartServicesMock, timelines: { ...mockTimelines }, + cases: mockCasesContract(), application: { capabilities: { siem: { crud_alerts: true, read_alerts: true } }, }, diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx index 8ad76c70247bf8..d9dfcd0fee7dae 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx @@ -137,7 +137,7 @@ export const TakeActionDropdown = React.memo( disabled: !isEndpointEvent, }); - const afterCaseSelection = useCallback(() => { + const onMenuItemClick = useCallback(() => { closePopoverHandler(); }, [closePopoverHandler]); @@ -175,7 +175,7 @@ export const TakeActionDropdown = React.memo( const { addToCaseActionItems } = useAddToCaseActions({ ecsData, nonEcsData: detailsData?.map((d) => ({ field: d.field, value: d.values })) ?? [], - afterCaseSelection, + onMenuItemClick, timelineId, }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index 4b6cbb6f7e16dd..4891c75744e385 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -24,7 +24,7 @@ import { createStore, State } from '../../../common/store'; import { mockHistory, Router } from '../../../common/mock/router'; import { mockTimelines } from '../../../common/mock/mock_timelines_plugin'; import { mockBrowserFields } from '../../../common/containers/source/mock'; -import { mockCasesContext } from '../../../common/mock/mock_cases_context'; +import { mockCasesContext } from '../../../../../cases/public/mocks/mock_cases_context'; // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar and QueryBar diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/footer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/footer.test.tsx index 71d6f6253010d7..4a0b7d0fe0501e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/footer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/footer.test.tsx @@ -15,6 +15,7 @@ import { mockAlertDetailsData } from '../../../../common/components/event_detail import type { TimelineEventsDetailsItem } from '../../../../../common/search_strategy'; import { KibanaServices, useKibana } from '../../../../common/lib/kibana'; import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { mockCasesContract } from '../../../../../../cases/public/mocks'; const ecsData: Ecs = { _id: '1', @@ -114,6 +115,7 @@ describe('event details footer component', () => { }, query: jest.fn(), }, + cases: mockCasesContract(), }, }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx index b6e6aa40876ccf..7a94dcef31cf7b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx @@ -12,6 +12,7 @@ import { TestProviders, mockTimelineModel, mockTimelineData } from '../../../../ import { Actions } from '.'; import { mockTimelines } from '../../../../../common/mock/mock_timelines_plugin'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; +import { mockCasesContract } from '../../../../../../../cases/public/mocks'; jest.mock('../../../../../detections/components/user_info', () => ({ useUserData: jest.fn().mockReturnValue([{ canUserCRUD: true, hasIndexWrite: true }]), @@ -43,6 +44,7 @@ jest.mock('../../../../../common/lib/kibana', () => ({ siem: { crud_alerts: true, read_alerts: true }, }, }, + cases: mockCasesContract(), uiSettings: { get: jest.fn(), }, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx index b9e04060881d4f..890175ac8daf9a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx @@ -20,6 +20,7 @@ import { getDefaultControlColumn } from '../control_columns'; import { testLeadingControlColumn } from '../../../../../common/mock/mock_timeline_control_columns'; import { mockTimelines } from '../../../../../common/mock/mock_timelines_plugin'; import { getActionsColumnWidth } from '../../../../../../../timelines/public'; +import { mockCasesContract } from '../../../../../../../cases/public/mocks'; jest.mock('../../../../../common/hooks/use_experimental_features'); const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; @@ -40,6 +41,7 @@ jest.mock('../../../../../common/lib/kibana', () => ({ siem: { crud_alerts: true, read_alerts: true }, }, }, + cases: mockCasesContract(), }, }), useToasts: jest.fn().mockReturnValue({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx index 66a140987475c5..f616b4afc2af5f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.test.tsx @@ -24,12 +24,12 @@ import { useMountAppended } from '../../../../common/utils/use_mount_appended'; import { timelineActions } from '../../../store/timeline'; import { ColumnHeaderOptions, TimelineTabs } from '../../../../../common/types/timeline'; import { defaultRowRenderers } from './renderers'; -import { mockCasesContext } from '../../../../common/mock/mock_cases_context'; jest.mock('../../../../common/lib/kibana/hooks'); jest.mock('../../../../common/hooks/use_app_toasts'); jest.mock('../../../../common/lib/kibana', () => { const originalModule = jest.requireActual('../../../../common/lib/kibana'); + const mockCasesContract = jest.requireActual('../../../../../../cases/public/mocks'); return { ...originalModule, useKibana: jest.fn().mockReturnValue({ @@ -41,9 +41,7 @@ jest.mock('../../../../common/lib/kibana', () => { siem: { crud_alerts: true, read_alerts: true }, }, }, - cases: { - getCasesContext: () => mockCasesContext, - }, + cases: mockCasesContract.mockCasesContract(), data: { search: jest.fn(), query: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx index 43622b7e453652..943abc88cf2b05 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx @@ -23,7 +23,7 @@ import { useTimelineEventsDetails } from '../../../containers/details/index'; import { useSourcererDataView } from '../../../../common/containers/sourcerer'; import { mockSourcererScope } from '../../../../common/containers/sourcerer/mocks'; import { useDraggableKeyboardWrapper as mockUseDraggableKeyboardWrapper } from '../../../../../../timelines/public/components'; -import { mockCasesContext } from '../../../../common/mock/mock_cases_context'; +import { mockCasesContext } from '../../../../../../cases/public/mocks/mock_cases_context'; jest.mock('../../../containers/index', () => ({ useTimelineEvents: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx index ffe50f935b9fec..954f54fdba7770 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx @@ -24,7 +24,7 @@ import { mockSourcererScope } from '../../../../common/containers/sourcerer/mock import { PinnedTabContentComponent, Props as PinnedTabContentComponentProps } from '.'; import { Direction } from '../../../../../common/search_strategy'; import { useDraggableKeyboardWrapper as mockUseDraggableKeyboardWrapper } from '../../../../../../timelines/public/components'; -import { mockCasesContext } from '../../../../common/mock/mock_cases_context'; +import { mockCasesContext } from '../../../../../../cases/public/mocks/mock_cases_context'; jest.mock('../../../containers/index', () => ({ useTimelineEvents: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx index 019bedacbffe88..c16afa945cc08d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx @@ -26,7 +26,7 @@ import { useSourcererDataView } from '../../../../common/containers/sourcerer'; import { mockSourcererScope } from '../../../../common/containers/sourcerer/mocks'; import { Direction } from '../../../../../common/search_strategy'; import * as helpers from '../helpers'; -import { mockCasesContext } from '../../../../common/mock/mock_cases_context'; +import { mockCasesContext } from '../../../../../../cases/public/mocks/mock_cases_context'; jest.mock('../../../containers/index', () => ({ useTimelineEvents: jest.fn(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts index f8270c53b07ae2..99230627cb6b82 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts @@ -176,7 +176,13 @@ export const searchAfterAndBulkCreate = async ({ buildRuleMessage(`enrichedEvents.hits.hits: ${enrichedEvents.hits.hits.length}`) ); - sendAlertTelemetryEvents(logger, eventsTelemetry, enrichedEvents, buildRuleMessage); + sendAlertTelemetryEvents( + logger, + eventsTelemetry, + enrichedEvents, + createdItems, + buildRuleMessage + ); } if (!hasSortId) { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts index 991378983e1b28..36bb90936620bc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { selectEvents } from './send_telemetry_events'; +import { selectEvents, enrichEndpointAlertsSignalID } from './send_telemetry_events'; describe('sendAlertTelemetry', () => { it('selectEvents', () => { @@ -33,6 +33,9 @@ describe('sendAlertTelemetry', () => { data_stream: { dataset: 'endpoint.events', }, + event: { + id: 'foo', + }, }, }, { @@ -47,6 +50,9 @@ describe('sendAlertTelemetry', () => { dataset: 'endpoint.alerts', other: 'x', }, + event: { + id: 'bar', + }, }, }, { @@ -58,13 +64,52 @@ describe('sendAlertTelemetry', () => { '@timestamp': 'x', key3: 'hello', data_stream: {}, + event: { + id: 'baz', + }, + }, + }, + { + _index: 'y', + _type: 'y', + _id: 'y', + _score: 0, + _source: { + '@timestamp': 'y', + key3: 'hello', + data_stream: { + dataset: 'endpoint.alerts', + other: 'y', + }, + event: { + id: 'not-in-map', + }, + }, + }, + { + _index: 'z', + _type: 'z', + _id: 'z', + _score: 0, + _source: { + '@timestamp': 'z', + key3: 'no-event-id', + data_stream: { + dataset: 'endpoint.alerts', + other: 'z', + }, }, }, ], }, }; - - const sources = selectEvents(filteredEvents); + const joinMap = new Map([ + ['foo', '1234'], + ['bar', 'abcd'], + ['baz', '4567'], + ]); + const subsetEvents = selectEvents(filteredEvents); + const sources = enrichEndpointAlertsSignalID(subsetEvents, joinMap); expect(sources).toStrictEqual([ { '@timestamp': 'x', @@ -73,6 +118,31 @@ describe('sendAlertTelemetry', () => { dataset: 'endpoint.alerts', other: 'x', }, + event: { + id: 'bar', + }, + signal_id: 'abcd', + }, + { + '@timestamp': 'y', + key3: 'hello', + data_stream: { + dataset: 'endpoint.alerts', + other: 'y', + }, + event: { + id: 'not-in-map', + }, + signal_id: undefined, + }, + { + '@timestamp': 'z', + key3: 'no-event-id', + data_stream: { + dataset: 'endpoint.alerts', + other: 'z', + }, + signal_id: undefined, }, ]); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts index 5904f943183c39..fc3aed36939cde 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts @@ -11,14 +11,17 @@ import { BuildRuleMessage } from './rule_messages'; import { SignalSearchResponse, SignalSource } from './types'; import { Logger } from '../../../../../../../src/core/server'; -export interface SearchResultWithSource { +interface SearchResultSource { _source: SignalSource; } +type CreatedSignalId = string; +type AlertId = string; + export function selectEvents(filteredEvents: SignalSearchResponse): TelemetryEvent[] { // @ts-expect-error @elastic/elasticsearch _source is optional const sources: TelemetryEvent[] = filteredEvents.hits.hits.map(function ( - obj: SearchResultWithSource + obj: SearchResultSource ): TelemetryEvent { return obj._source; }); @@ -27,20 +30,49 @@ export function selectEvents(filteredEvents: SignalSearchResponse): TelemetryEve return sources.filter((obj: TelemetryEvent) => obj.data_stream?.dataset === 'endpoint.alerts'); } +export function enrichEndpointAlertsSignalID( + events: TelemetryEvent[], + signalIdMap: Map +): TelemetryEvent[] { + return events.map(function (obj: TelemetryEvent): TelemetryEvent { + obj.signal_id = undefined; + if (obj?.event?.id !== undefined) { + obj.signal_id = signalIdMap.get(obj.event.id); + } + return obj; + }); +} + export function sendAlertTelemetryEvents( logger: Logger, eventsTelemetry: ITelemetryEventsSender | undefined, filteredEvents: SignalSearchResponse, + createdEvents: SignalSource[], buildRuleMessage: BuildRuleMessage ) { if (eventsTelemetry === undefined) { return; } - const sources = selectEvents(filteredEvents); + let selectedEvents = selectEvents(filteredEvents); + if (selectedEvents.length > 0) { + // Create map of ancenstor_id -> alert_id + let signalIdMap = new Map(); + /* eslint-disable no-param-reassign */ + signalIdMap = createdEvents.reduce((signalMap, obj) => { + const ancestorId = obj['kibana.alert.original_event.id']?.toString(); + const alertId = obj._id?.toString(); + if (ancestorId !== null && ancestorId !== undefined && alertId !== undefined) { + signalMap = signalIdMap.set(ancestorId, alertId); + } + + return signalMap; + }, new Map()); + selectedEvents = enrichEndpointAlertsSignalID(selectedEvents, signalIdMap); + } try { - eventsTelemetry.queueTelemetryEvents(sources); + eventsTelemetry.queueTelemetryEvents(selectedEvents); } catch (exc) { logger.error(buildRuleMessage(`[-] queing telemetry events failed ${exc}`)); } diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts index 452717f1efb4f7..bd41bc454e8760 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts @@ -108,6 +108,7 @@ const allowlistBaseEventFields: AllowlistFields = { export const allowlistEventFields: AllowlistFields = { _id: true, '@timestamp': true, + signal_id: true, agent: true, Endpoint: true, /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts b/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts index 70852aa3093c67..d055f3843d479a 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts @@ -35,6 +35,7 @@ describe('TelemetryEventsSender', () => { { event: { kind: 'alert', + id: 'test', }, dns: { question: { @@ -108,6 +109,7 @@ describe('TelemetryEventsSender', () => { { event: { kind: 'alert', + id: 'test', }, dns: { question: { diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/types.ts b/x-pack/plugins/security_solution/server/lib/telemetry/types.ts index 35b701552b6ba4..35b531ae6941c3 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/types.ts @@ -58,6 +58,10 @@ export interface TelemetryEvent { }; }; license?: ESLicense; + event?: { + id?: string; + kind?: string; + }; } // EP Policy Response diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json new file mode 100644 index 00000000000000..96327533d4e291 --- /dev/null +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -0,0 +1,25710 @@ +{ + "formats": { + "number": { + "currency": { + "style": "currency" + }, + "percent": { + "style": "percent" + } + }, + "date": { + "short": { + "month": "numeric", + "day": "numeric", + "year": "2-digit" + }, + "medium": { + "month": "short", + "day": "numeric", + "year": "numeric" + }, + "long": { + "month": "long", + "day": "numeric", + "year": "numeric" + }, + "full": { + "weekday": "long", + "month": "long", + "day": "numeric", + "year": "numeric" + } + }, + "time": { + "short": { + "hour": "numeric", + "minute": "numeric" + }, + "medium": { + "hour": "numeric", + "minute": "numeric", + "second": "numeric" + }, + "long": { + "hour": "numeric", + "minute": "numeric", + "second": "numeric", + "timeZoneName": "short" + }, + "full": { + "hour": "numeric", + "minute": "numeric", + "second": "numeric", + "timeZoneName": "short" + } + }, + "relative": { + "years": { + "units": "year" + }, + "months": { + "units": "month" + }, + "days": { + "units": "day" + }, + "hours": { + "units": "hour" + }, + "minutes": { + "units": "minute" + }, + "seconds": { + "units": "second" + } + } + }, + "messages": { + "xpack.lens.formula.absFunction.markdown": "\nCalcule une valeur absolue. Une valeur négative est multipliée par -1, une valeur positive reste identique.\n\nExemple : calculer la distance moyenne par rapport au niveau de la mer \"abs(average(altitude))\"\n ", + "xpack.lens.formula.addFunction.markdown": "\nAjoute jusqu'à deux nombres.\nFonctionne également avec le symbole \"+\".\n\nExemple : calculer la somme de deux champs\n\n\"sum(price) + sum(tax)\"\n\nExemple : compenser le compte par une valeur statique\n\n\"add(count(), 5)\"\n ", + "xpack.lens.formula.cbrtFunction.markdown": "\nÉtablit la racine carrée de la valeur.\n\nExemple : calculer la longueur du côté à partir du volume\n`cbrt(last_value(volume))`\n ", + "xpack.lens.formula.ceilFunction.markdown": "\nArrondit le plafond de la valeur au chiffre supérieur.\n\nExemple : arrondir le prix au dollar supérieur\n`ceil(sum(price))`\n ", + "xpack.lens.formula.clampFunction.markdown": "\nÉtablit une limite minimale et maximale pour la valeur.\n\nExemple : s'assurer de repérer les valeurs aberrantes\n```\nclamp(\n average(bytes),\n percentile(bytes, percentile=5),\n percentile(bytes, percentile=95)\n)\n```\n", + "xpack.lens.formula.cubeFunction.markdown": "\nCalcule le cube d'un nombre.\n\nExemple : calculer le volume à partir de la longueur du côté\n`cube(last_value(length))`\n ", + "xpack.lens.formula.divideFunction.markdown": "\nDivise le premier nombre par le deuxième.\nFonctionne également avec le symbole \"/\".\n\nExemple : calculer la marge bénéficiaire\n\"sum(profit) / sum(revenue)\"\n\nExemple : \"divide(sum(bytes), 2)\"\n ", + "xpack.lens.formula.expFunction.markdown": "\nÉlève *e* à la puissance n.\n\nExemple : calculer la fonction exponentielle naturelle\n\n`exp(last_value(duration))`\n ", + "xpack.lens.formula.fixFunction.markdown": "\nPour les valeurs positives, part du bas. Pour les valeurs négatives, part du haut.\n\nExemple : arrondir à zéro\n\"fix(sum(profit))\"\n ", + "xpack.lens.formula.floorFunction.markdown": "\nArrondit à la valeur entière inférieure la plus proche.\n\nExemple : arrondir un prix au chiffre inférieur\n\"floor(sum(price))\"\n ", + "xpack.lens.formula.logFunction.markdown": "\nÉtablit un logarithme avec base optionnelle. La base naturelle *e* est utilisée par défaut.\n\nExemple : calculer le nombre de bits nécessaire au stockage de valeurs\n```\nlog(sum(bytes))\nlog(sum(bytes), 2)\n```\n ", + "xpack.lens.formula.modFunction.markdown": "\nÉtablit le reste après division de la fonction par un nombre.\n\nExemple : calculer les trois derniers chiffres d'une valeur\n\"mod(sum(price), 1000)\"\n ", + "xpack.lens.formula.multiplyFunction.markdown": "\nMultiplie deux nombres.\nFonctionne également avec le symbole \"*\".\n\nExemple : calculer le prix après application du taux d'imposition courant\n`sum(bytes) * last_value(tax_rate)`\n\nExemple : calculer le prix après application du taux d'imposition constant\n\"multiply(sum(price), 1.2)\"\n ", + "xpack.lens.formula.powFunction.markdown": "\nÉlève la valeur à une puissance spécifique. Le deuxième argument est obligatoire.\n\nExemple : calculer le volume en fonction de la longueur du côté\n\"pow(last_value(length), 3)\"\n ", + "xpack.lens.formula.roundFunction.markdown": "\nArrondit à un nombre donné de décimales, 0 étant la valeur par défaut.\n\nExemples : arrondir au centième\n```\nround(sum(bytes))\nround(sum(bytes), 2)\n```\n ", + "xpack.lens.formula.sqrtFunction.markdown": "\nÉtablit la racine carrée d'une valeur positive uniquement.\n\nExemple : calculer la longueur du côté en fonction de la surface\n`sqrt(last_value(area))`\n ", + "xpack.lens.formula.squareFunction.markdown": "\nÉlève la valeur à la puissance 2.\n\nExemple : calculer l’aire en fonction de la longueur du côté\n`square(last_value(length))`\n ", + "xpack.lens.formula.subtractFunction.markdown": "\nSoustrait le premier nombre du deuxième.\nFonctionne également avec le symbole \"-\".\n\nExemple : calculer la plage d'un champ\n\"subtract(max(bytes), min(bytes))\"\n ", + "xpack.lens.formulaDocumentation.filterRatioDescription.markdown": "### Rapport de filtre :\n\nUtilisez \"kql=''\" pour filtrer un ensemble de documents et le comparer à d'autres documents du même regroupement.\nPar exemple, pour consulter l'évolution du taux d'erreur au fil du temps :\n\n```\ncount(kql='response.status_code > 400') / count()\n```\n ", + "xpack.lens.formulaDocumentation.percentOfTotalDescription.markdown": "### Pourcentage du total\n\nLes formules peuvent calculer \"overall_sum\" pour tous les regroupements,\nce qui permet de convertir chaque regroupement en un pourcentage du total :\n\n```\nsum(products.base_price) / overall_sum(sum(products.base_price))\n```\n ", + "xpack.lens.formulaDocumentation.weekOverWeekDescription.markdown": "### Semaine après semaine :\n\nUtilisez \"shift='1w'\" pour obtenir la valeur de chaque regroupement\nde la semaine précédente. Le décalage ne doit pas être utilisé avec la fonction *Valeurs les plus élevées*.\n\n```\npercentile(system.network.in.bytes, percentile=99) /\npercentile(system.network.in.bytes, percentile=99, shift='1w')\n```\n ", + "xpack.lens.indexPattern.cardinality.documentation.markdown": "\nCalcule le nombre de valeurs uniques d'un champ donné. Fonctionne pour les nombres, les chaînes, les dates et les valeurs booléennes.\n\nExemple : calculer le nombre de produits différents :\n`unique_count(product.name)`\n\nExemple : calculer le nombre de produits différents du groupe \"clothes\" :\n\"unique_count(product.name, kql='product.group=clothes')\"\n ", + "xpack.lens.indexPattern.count.documentation.markdown": "\nCalcule le nombre de documents.\n\nExemple : calculer le nombre de documents :\n\"count()\"\n\nExemple : calculer le nombre de documents correspondant à un filtre spécifique :\n\"count(kql='price > 500')\"\n ", + "xpack.lens.indexPattern.counterRate.documentation.markdown": "\nCalcule le taux d'un compteur toujours croissant. Cette fonction renvoie uniquement des résultats utiles inhérents aux champs d'indicateurs de compteur qui contiennent une mesure quelconque à croissance régulière.\nSi la valeur diminue, elle est interprétée comme une mesure de réinitialisation de compteur. Pour obtenir des résultats plus précis, \"counter_rate\" doit être calculé d’après la valeur \"max\" du champ.\n\nCe calcul est réalisé séparément pour des séries distinctes définies par des filtres ou des dimensions de valeurs supérieures.\nIl utilise l'intervalle en cours utilisé dans la formule.\n\nExemple : visualiser le taux d'octets reçus au fil du temps par un serveur Memcached :\n`counter_rate(max(memcached.stats.read.bytes))`\n ", + "xpack.lens.indexPattern.cumulativeSum.documentation.markdown": "\nCalcule la somme cumulée d'un indicateur au fil du temps, en ajoutant toutes les valeurs précédentes d'une série à chaque valeur. Pour utiliser cette fonction, vous devez également configurer une dimension de l'histogramme de dates.\n\nCe calcul est réalisé séparément pour des séries distinctes définies par des filtres ou des dimensions de valeurs supérieures.\n\nExemple : visualiser les octets reçus cumulés au fil du temps :\n`cumulative_sum(sum(bytes))`\n ", + "xpack.lens.indexPattern.differences.documentation.markdown": "\nCalcule la différence par rapport à la dernière valeur d'un indicateur au fil du temps. Pour utiliser cette fonction, vous devez également configurer une dimension de l'histogramme de dates.\nLes données doivent être séquentielles pour les différences. Si vos données sont vides lorsque vous utilisez des différences, essayez d'augmenter l'intervalle de l'histogramme de dates.\n\nCe calcul est réalisé séparément pour des séries distinctes définies par des filtres ou des dimensions de valeurs supérieures.\n\nExemple : visualiser la modification des octets reçus au fil du temps :\n`differences(sum(bytes))`\n ", + "xpack.lens.indexPattern.lastValue.documentation.markdown": "\nRenvoie la valeur d'un champ du dernier document, triée par le champ d'heure par défaut du modèle d'indexation.\n\nCette fonction permet de récupérer le dernier état d'une entité.\n\nExemple : obtenir le statut actuel du serveur A :\n`last_value(server.status, kql='server.name=\"A\"')`\n ", + "xpack.lens.indexPattern.metric.documentation.markdown": "\nRenvoie l'indicateur {metric} d'un champ. Cette fonction fonctionne uniquement pour les champs numériques.\n\nExemple : obtenir l'indicateur {metric} d'un prix :\n\"{metric}(price)\"\n\nExemple : obtenir l'indicateur {metric} d'un prix pour des commandes du Royaume-Uni :\n\"{metric}(price, kql='location:UK')\"\n ", + "xpack.lens.indexPattern.movingAverage.documentation.markdown": "\nCalcule la moyenne mobile d'un indicateur au fil du temps, en prenant la moyenne des n dernières valeurs pour calculer la valeur actuelle. Pour utiliser cette fonction, vous devez également configurer une dimension de l'histogramme de dates.\nLa valeur de fenêtre par défaut est {defaultValue}.\n\nCe calcul est réalisé séparément pour des séries distinctes définies par des filtres ou des dimensions de valeurs supérieures.\n\nPrend un paramètre nommé \"window\" qui spécifie le nombre de dernières valeurs à inclure dans le calcul de la moyenne de la valeur actuelle.\n\nExemple : lisser une ligne de mesures :\n`moving_average(sum(bytes), window=5)`\n ", + "xpack.lens.indexPattern.overall_average.documentation.markdown": "\nCalcule la moyenne d'un indicateur pour tous les points de données d'une série dans le graphique actuel. Une série est définie par une dimension à l'aide d'un histogramme de dates ou d'une fonction d'intervalle.\nD'autres dimensions permettant de répartir les données telles que les valeurs supérieures ou les filtres sont traitées en tant que séries distinctes.\n\nSi le graphique actuel n'utilise aucun histogramme de dates ou aucune fonction d'intervalle, \"overall_average\" calcule la moyenne pour toutes les dimensions, quelle que soit la fonction utilisée.\n\nExemple : écart par rapport à la moyenne :\n\"sum(bytes) - overall_average(sum(bytes))\"\n ", + "xpack.lens.indexPattern.overall_max.documentation.markdown": "\nCalcule la valeur maximale d'un indicateur pour tous les points de données d'une série dans le graphique actuel. Une série est définie par une dimension à l'aide d'un histogramme de dates ou d'une fonction d'intervalle.\nD'autres dimensions permettant de répartir les données telles que les valeurs supérieures ou les filtres sont traitées en tant que séries distinctes.\n\nSi le graphique actuel n'utilise aucun histogramme de dates ou aucune fonction d'intervalle, \"overall_max\" calcule la valeur maximale pour toutes les dimensions, quelle que soit la fonction utilisée.\n\nExemple : pourcentage de plage\n\"(sum(bytes) - overall_min(sum(bytes))) / (overall_max(sum(bytes)) - overall_min(sum(bytes)))\"\n ", + "xpack.lens.indexPattern.overall_min.documentation.markdown": "\nCalcule la valeur minimale d'un indicateur pour tous les points de données d'une série dans le graphique actuel. Une série est définie par une dimension à l'aide d'un histogramme de dates ou d'une fonction d'intervalle.\nD'autres dimensions permettant de répartir les données telles que les valeurs supérieures ou les filtres sont traitées en tant que séries distinctes.\n\nSi le graphique actuel n'utilise aucun histogramme de dates ou aucune fonction d'intervalle, \"overall_min\" calcule la valeur minimale pour toutes les dimensions, quelle que soit la fonction utilisée.\n\nExemple : pourcentage de plage\n\"(sum(bytes) - overall_min(sum(bytes)) / (overall_max(sum(bytes)) - overall_min(sum(bytes)))\"\n ", + "xpack.lens.indexPattern.overall_sum.documentation.markdown": "\nCalcule la somme d'un indicateur pour tous les points de données d'une série dans le graphique actuel. Une série est définie par une dimension à l'aide d'un histogramme de dates ou d'une fonction d'intervalle.\nD'autres dimensions permettant de répartir les données telles que les valeurs supérieures ou les filtres sont traitées en tant que séries distinctes.\n\nSi le graphique actuel n'utilise aucun histogramme de dates ou aucune fonction d'intervalle, \"overall_sum\" calcule la somme pour toutes les dimensions, quelle que soit la fonction utilisée.\n\nExemple : pourcentage de total\n\"sum(bytes) / overall_sum(sum(bytes))\"\n ", + "xpack.lens.indexPattern.percentile.documentation.markdown": "\nRenvoie le centile spécifié des valeurs d'un champ. Il s'agit de la valeur de n pour cent des valeurs présentes dans les documents.\n\nExemple : obtenir le nombre d'octets supérieurs à 95 % des valeurs :\n`percentile(bytes, percentile=95)`\n ", + "xpack.lens.app.addToLibrary": "Enregistrer dans la bibliothèque", + "xpack.lens.app.cancel": "Annuler", + "xpack.lens.app.cancelButtonAriaLabel": "Retour à la dernière application sans enregistrer les modifications", + "xpack.lens.app.docLoadingError": "Erreur lors du chargement du document enregistré", + "xpack.lens.app.downloadButtonAriaLabel": "Télécharger les données en fichier CSV", + "xpack.lens.app.downloadButtonFormulasWarning": "Votre fichier CSV contient des caractères que les applications de feuilles de calcul pourraient considérer comme des formules.", + "xpack.lens.app.downloadCSV": "Télécharger en tant que CSV", + "xpack.lens.app.save": "Enregistrer", + "xpack.lens.app.saveAndReturn": "Enregistrer et revenir", + "xpack.lens.app.saveAndReturnButtonAriaLabel": "Enregistrer la visualisation Lens en cours et revenir à l'application précédente", + "xpack.lens.app.saveAs": "Enregistrer sous", + "xpack.lens.app.saveButtonAriaLabel": "Enregistrer la visualisation Lens en cours", + "xpack.lens.app.saveModalType": "Visualisation Lens", + "xpack.lens.app.saveVisualization.successNotificationText": "'{visTitle}' enregistré", + "xpack.lens.app.unsavedFilename": "non enregistré", + "xpack.lens.app.unsavedWorkMessage": "Quitter Lens avec un travail non enregistré ?", + "xpack.lens.app.unsavedWorkTitle": "Modifications non enregistrées", + "xpack.lens.app.updatePanel": "Mettre à jour le panneau sur {originatingAppName}", + "xpack.lens.app404": "404 Page introuvable", + "xpack.lens.breadcrumbsByValue": "Modifier la visualisation", + "xpack.lens.breadcrumbsCreate": "Créer", + "xpack.lens.breadcrumbsTitle": "Visualiser la bibliothèque", + "xpack.lens.chartSwitch.dataLossDescription": "La sélection de ce type de visualisation entraînera une perte partielle des sélections de configuration actuellement appliquées.", + "xpack.lens.chartSwitch.dataLossLabel": "Avertissement", + "xpack.lens.chartSwitch.experimentalLabel": "Expérimental", + "xpack.lens.chartSwitch.noResults": "Résultats introuvables pour {term}.", + "xpack.lens.chartTitle.unsaved": "Visualisation non enregistrée", + "xpack.lens.chartWarnings.number": "{warningsCount} {warningsCount, plural, one {avertissement} other {avertissements}}", + "xpack.lens.configPanel.addLayerButton": "Ajouter un calque", + "xpack.lens.configPanel.color.tooltip.auto": "Lens choisit automatiquement des couleurs à votre place sauf si vous spécifiez une couleur personnalisée.", + "xpack.lens.configPanel.color.tooltip.custom": "Effacez la couleur personnalisée pour revenir au mode \"Auto\".", + "xpack.lens.configPanel.color.tooltip.disabled": "Les séries individuelles n'acceptent pas les couleurs personnalisées lorsque le calque inclut l'option \"Répartir par\".", + "xpack.lens.configPanel.selectVisualization": "Sélectionner une visualisation", + "xpack.lens.configPanel.visualizationType": "Type de visualisation", + "xpack.lens.configure.configurePanelTitle": "{groupLabel}", + "xpack.lens.configure.editConfig": "Modifier la configuration {label}", + "xpack.lens.configure.emptyConfig": "Ajouter ou glisser-déposer un champ", + "xpack.lens.configure.invalidConfigTooltip": "Configuration non valide.", + "xpack.lens.configure.invalidConfigTooltipClick": "Cliquez pour en savoir plus.", + "xpack.lens.customBucketContainer.dragToReorder": "Faire glisser pour réorganiser", + "xpack.lens.dataPanelWrapper.switchDatasource": "Basculer vers la source de données", + "xpack.lens.datatable.addLayer": "Ajouter un calque de visualisation", + "xpack.lens.datatable.breakdownColumns": "Colonnes", + "xpack.lens.datatable.breakdownColumns.description": "Divisez les colonnes d'indicateurs par champ. Il est recommandé de conserver un faible nombre de colonnes pour éviter le défilement horizontal.", + "xpack.lens.datatable.breakdownRows": "Lignes", + "xpack.lens.datatable.breakdownRows.description": "Divisez le tableau par champ. Cette opération est recommandée pour les répartitions à cardinalité élevée.", + "xpack.lens.datatable.conjunctionSign": " & ", + "xpack.lens.datatable.expressionHelpLabel": "Outil de rendu de tableaux de données", + "xpack.lens.datatable.groupLabel": "Valeur tabulaire et unique", + "xpack.lens.datatable.label": "Tableau", + "xpack.lens.datatable.metrics": "Indicateurs", + "xpack.lens.datatable.suggestionLabel": "En tant que tableau", + "xpack.lens.datatable.titleLabel": "Titre", + "xpack.lens.datatable.visualizationName": "Tableau de données", + "xpack.lens.datatable.visualizationOf": "Tableau {operations}", + "xpack.lens.datatypes.boolean": "booléen", + "xpack.lens.datatypes.date": "date", + "xpack.lens.datatypes.geoPoint": "geo_point", + "xpack.lens.datatypes.geoShape": "geo_shape", + "xpack.lens.datatypes.histogram": "histogramme", + "xpack.lens.datatypes.ipAddress": "IP", + "xpack.lens.datatypes.number": "numéro", + "xpack.lens.datatypes.record": "enregistrement", + "xpack.lens.datatypes.string": "chaîne", + "xpack.lens.deleteLayerAriaLabel": "Supprimer le calque {index}", + "xpack.lens.dimensionContainer.close": "Fermer", + "xpack.lens.dimensionContainer.closeConfiguration": "Fermer la configuration", + "xpack.lens.discover.visualizeFieldLegend": "Visualiser le champ", + "xpack.lens.dragDrop.altOption": "Alt/Option", + "xpack.lens.dragDrop.announce.cancelled": "Mouvement annulé. {label} revenu à sa position initiale", + "xpack.lens.dragDrop.announce.cancelledItem": "Mouvement annulé. {label} revenu au groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.duplicated": "{label} dupliqué dans le groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.duplicateIncompatible": "Copie de {label} convertie en {nextLabel} et ajoutée au groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.moveCompatible": "{label} déplacé dans le groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.moveIncompatible": "{label} converti en {nextLabel} et déplacé dans le groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.reordered": "{label} réorganisé dans le groupe {groupLabel} de la position {prevPosition} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.replaceDuplicateIncompatible": "Copie de {label} convertie en {nextLabel} et {dropLabel} remplacé dans le groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.replaceIncompatible": "{label} converti en {nextLabel} et {dropLabel} remplacé dans le groupe {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.swapCompatible": "{label} déplacé dans {dropGroupLabel} à la position {dropPosition} et {dropLabel} dans {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.dropped.swapIncompatible": "{label} converti en {nextLabel} dans le groupe {groupLabel} à la position {position} et permuté avec {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition}", + "xpack.lens.dragDrop.announce.droppedDefault": "{label} ajouté dans le groupe {dropGroupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.droppedNoPosition": "{label} ajouté à {dropLabel}", + "xpack.lens.dragDrop.announce.duplicate.short": " Maintenez la touche Alt ou Option enfoncée pour dupliquer.", + "xpack.lens.dragDrop.announce.duplicated.replace": "{dropLabel} remplacé par {label} dans {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.duplicated.replaceDuplicateCompatible": "{dropLabel} remplacé par une copie de {label} dans {groupLabel} à la position {position}", + "xpack.lens.dragDrop.announce.lifted": "{label} levé", + "xpack.lens.dragDrop.announce.selectedTarget.default": "Ajoutez {label} au groupe {dropGroupLabel} à la position {position}. Appuyer sur la barre d'espace ou sur Entrée pour ajouter", + "xpack.lens.dragDrop.announce.selectedTarget.defaultNoPosition": "Ajoutez {label} à {dropLabel}. Appuyer sur la barre d'espace ou sur Entrée pour ajouter", + "xpack.lens.dragDrop.announce.selectedTarget.duplicated": "Dupliquez {label} dans le groupe {dropGroupLabel} à la position {position}. Maintenir la touche Alt ou Option enfoncée et appuyer sur la barre d'espace ou sur Entrée pour dupliquer", + "xpack.lens.dragDrop.announce.selectedTarget.duplicatedInGroup": "Dupliquez {label} dans le groupe {dropGroupLabel} à la position {position}. Appuyer sur la barre d'espace ou sur Entrée pour dupliquer", + "xpack.lens.dragDrop.announce.selectedTarget.duplicateIncompatible": "Convertissez la copie de {label} en {nextLabel} et ajoutez-la au groupe {groupLabel} à la position {position}. Maintenir la touche Alt ou Option enfoncée et appuyer sur la barre d'espace ou sur Entrée pour dupliquer", + "xpack.lens.dragDrop.announce.selectedTarget.moveCompatible": "Déplacez {label} dans le groupe {dropGroupLabel} à la position {dropPosition}. Appuyer sur la barre d'espace ou sur Entrée pour déplacer", + "xpack.lens.dragDrop.announce.selectedTarget.moveCompatibleMain": "Vous faites glisser {label} de {groupLabel} à la position {position} vers la position {dropPosition} dans le groupe {dropGroupLabel}. Appuyez sur la barre d'espace ou sur Entrée pour déplacer.{duplicateCopy}{swapCopy}", + "xpack.lens.dragDrop.announce.selectedTarget.moveIncompatible": "Convertissez {label} en {nextLabel} et déplacez-le dans le groupe {dropGroupLabel} à la position {dropPosition}. Appuyer sur la barre d'espace ou sur Entrée pour déplacer", + "xpack.lens.dragDrop.announce.selectedTarget.moveIncompatibleMain": "Vous faites glisser {label} de {groupLabel} à la position {position} vers la position {dropPosition} dans le groupe {dropGroupLabel}. Appuyez sur la barre d'espace ou sur Entrée pour convertir {label} en {nextLabel} et déplacer.{duplicateCopy}{swapCopy}", + "xpack.lens.dragDrop.announce.selectedTarget.noSelected": "Aucune cible sélectionnée. Utiliser les touches fléchées pour sélectionner une cible", + "xpack.lens.dragDrop.announce.selectedTarget.reordered": "Réorganisez {label} dans le groupe {groupLabel} de la position {prevPosition} à la position {position}. Appuyer sur la barre d'espace ou sur Entrée pour réorganiser", + "xpack.lens.dragDrop.announce.selectedTarget.reorderedBack": "{label} revenu à sa position initiale {prevPosition}", + "xpack.lens.dragDrop.announce.selectedTarget.replace": "Remplacez {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition} avec {label}. Appuyez sur la barre d'espace ou sur Entrée pour remplacer.", + "xpack.lens.dragDrop.announce.selectedTarget.replaceDuplicateCompatible": "Dupliquez {label} et remplacez {dropLabel} dans {groupLabel} à la position {position}. Maintenir la touche Alt ou Option enfoncée et appuyer sur la barre d'espace ou sur Entrée pour dupliquer et remplacer", + "xpack.lens.dragDrop.announce.selectedTarget.replaceDuplicateIncompatible": "Convertissez la copie de {label} en {nextLabel} et remplacez {dropLabel} dans le groupe {groupLabel} à la position {position}. Maintenir la touche Alt ou Option enfoncée et appuyer sur la barre d'espace ou sur Entrée pour dupliquer et remplacer", + "xpack.lens.dragDrop.announce.selectedTarget.replaceIncompatible": "Convertissez {label} en {nextLabel} et remplacez {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition}. Appuyer sur la barre d'espace ou sur Entrée pour remplacer", + "xpack.lens.dragDrop.announce.selectedTarget.replaceIncompatibleMain": "Vous faites glisser {label} à partir de {groupLabel} à la position {position} sur {dropLabel} à partir du groupe {dropGroupLabel} à la position {dropPosition}. Appuyer sur la barre d'espace ou sur Entrée pour convertir {label} en {nextLabel} et remplacer {dropLabel}.{duplicateCopy}{swapCopy}", + "xpack.lens.dragDrop.announce.selectedTarget.replaceMain": "Vous faites glisser {label} à partir de {groupLabel} à la position {position} sur {dropLabel} à partir du groupe {dropGroupLabel} à la position {dropPosition}. Appuyer sur la barre d'espace ou sur Entrée pour remplacer {dropLabel} par {label}.{duplicateCopy}{swapCopy}", + "xpack.lens.dragDrop.announce.selectedTarget.swapCompatible": "Permutez {label} dans le groupe {groupLabel} à la position {position} avec {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition}. Maintenir la touche Maj enfoncée tout en appuyant sur la barre d'espace ou sur Entrée pour permuter", + "xpack.lens.dragDrop.announce.selectedTarget.swapIncompatible": "Convertir {label} en {nextLabel} dans le groupe {groupLabel} à la position {position} et permutez avec {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition}. Maintenir la touche Maj enfoncée tout en appuyant sur la barre d'espace ou sur Entrée pour permuter", + "xpack.lens.dragDrop.announce.swap.short": " Maintenez la touche Maj enfoncée pour permuter.", + "xpack.lens.dragDrop.duplicate": "Dupliquer", + "xpack.lens.dragDrop.keyboardInstructions": "Appuyez sur la barre d'espace ou sur Entrée pour commencer à faire glisser. Lors du glissement, utilisez les touches fléchées gauche/droite pour vous déplacer entre les cibles de dépôt. Appuyez à nouveau sur la barre d'espace ou sur Entrée pour terminer.", + "xpack.lens.dragDrop.keyboardInstructionsReorder": "Appuyez sur la barre d'espace ou sur Entrée pour commencer à faire glisser. Lors du glissement, utilisez les touches fléchées haut/bas pour réorganiser les éléments dans le groupe et les touches gauche/droite pour choisir les cibles de dépôt à l'extérieur du groupe. Appuyez à nouveau sur la barre d'espace ou sur Entrée pour terminer.", + "xpack.lens.dragDrop.shift": "Déplacer", + "xpack.lens.dragDrop.swap": "Permuter", + "xpack.lens.dynamicColoring.customPalette.deleteButtonAriaLabel": "Supprimer", + "xpack.lens.editorFrame.buildExpressionError": "Une erreur inattendue s'est produite lors de la préparation du graphique", + "xpack.lens.editorFrame.colorIndicatorLabel": "Couleur de cette dimension : {hex}", + "xpack.lens.editorFrame.configurationFailureMoreErrors": " +{errors} {errors, plural, one {erreur} other {erreurs}}", + "xpack.lens.editorFrame.dataFailure": "Une erreur s'est produite lors du chargement des données.", + "xpack.lens.editorFrame.emptyWorkspace": "Déposer quelques champs ici pour commencer", + "xpack.lens.editorFrame.emptyWorkspaceHeading": "Lens est un nouvel outil permettant de créer des visualisations", + "xpack.lens.editorFrame.emptyWorkspaceSimple": "Déposer le champ ici", + "xpack.lens.editorFrame.expandRenderingErrorButton": "Afficher les détails de l'erreur", + "xpack.lens.editorFrame.expressionFailure": "Une erreur s'est produite dans l'expression", + "xpack.lens.editorFrame.expressionFailureMessage": "Erreur de requête : {type}, {reason}", + "xpack.lens.editorFrame.expressionFailureMessageWithContext": "Erreur de requête : {type}, {reason} dans {context}", + "xpack.lens.editorFrame.expressionMissingDatasource": "Impossible de trouver la source de données pour la visualisation", + "xpack.lens.editorFrame.expressionMissingVisualizationType": "Type de visualisation non trouvé.", + "xpack.lens.editorFrame.goToForums": "Formuler des requêtes et donner un retour", + "xpack.lens.editorFrame.invisibleIndicatorLabel": "Cette dimension n'est pas visible actuellement dans le graphique", + "xpack.lens.editorFrame.networkErrorMessage": "Erreur réseau, réessayez plus tard ou contactez votre administrateur.", + "xpack.lens.editorFrame.noColorIndicatorLabel": "Cette dimension n'a pas de couleur individuelle", + "xpack.lens.editorFrame.paletteColorIndicatorLabel": "Cette dimension utilise une palette", + "xpack.lens.editorFrame.previewErrorLabel": "L'aperçu du rendu a échoué", + "xpack.lens.editorFrame.suggestionPanelTitle": "Suggestions", + "xpack.lens.editorFrame.workspaceLabel": "Espace de travail", + "xpack.lens.embeddable.failure": "Impossible d'afficher la visualisation", + "xpack.lens.embeddable.fixErrors": "Effectuez des modifications dans l'éditeur Lens pour corriger l'erreur", + "xpack.lens.embeddable.moreErrors": "Effectuez des modifications dans l'éditeur Lens pour afficher plus d'erreurs", + "xpack.lens.embeddableDisplayName": "lens", + "xpack.lens.fieldFormats.longSuffix.d": "par jour", + "xpack.lens.fieldFormats.longSuffix.h": "par heure", + "xpack.lens.fieldFormats.longSuffix.m": "par minute", + "xpack.lens.fieldFormats.longSuffix.s": "par seconde", + "xpack.lens.fieldFormats.suffix.d": "/d", + "xpack.lens.fieldFormats.suffix.h": "/h", + "xpack.lens.fieldFormats.suffix.m": "/m", + "xpack.lens.fieldFormats.suffix.s": "/s", + "xpack.lens.fieldFormats.suffix.title": "Suffixe", + "xpack.lens.filterBy.removeLabel": "Supprimer le filtre", + "xpack.lens.fittingFunctionsDescription.carry": "Remplit les blancs avec la dernière valeur", + "xpack.lens.fittingFunctionsDescription.linear": "Remplit les blancs avec une ligne", + "xpack.lens.fittingFunctionsDescription.lookahead": "Remplit les blancs avec la valeur suivante", + "xpack.lens.fittingFunctionsDescription.none": "Ne remplit pas les blancs", + "xpack.lens.fittingFunctionsDescription.zero": "Remplit les blancs avec des zéros", + "xpack.lens.fittingFunctionsTitle.carry": "Dernier", + "xpack.lens.fittingFunctionsTitle.linear": "Linéaire", + "xpack.lens.fittingFunctionsTitle.lookahead": "Suivant", + "xpack.lens.fittingFunctionsTitle.none": "Masquer", + "xpack.lens.fittingFunctionsTitle.zero": "Zéro", + "xpack.lens.formula.base": "base", + "xpack.lens.formula.decimals": "décimales", + "xpack.lens.formula.disableWordWrapLabel": "Désactiver le renvoi à la ligne des mots", + "xpack.lens.formula.editorHelpInlineHideLabel": "Masquer la référence des fonctions", + "xpack.lens.formula.editorHelpInlineHideToolTip": "Masquer la référence des fonctions", + "xpack.lens.formula.editorHelpInlineShowToolTip": "Afficher la référence des fonctions", + "xpack.lens.formula.editorHelpOverlayToolTip": "Référence des fonctions", + "xpack.lens.formula.fullScreenEnterLabel": "Développer", + "xpack.lens.formula.fullScreenExitLabel": "Réduire", + "xpack.lens.formula.kqlExtraArguments": "[kql]?: string, [lucene]?: string", + "xpack.lens.formula.left": "gauche", + "xpack.lens.formula.max": "max", + "xpack.lens.formula.min": "min", + "xpack.lens.formula.number": "numéro", + "xpack.lens.formula.optionalArgument": "Facultatif. La valeur par défaut est {defaultValue}", + "xpack.lens.formula.requiredArgument": "Requis", + "xpack.lens.formula.right": "droite", + "xpack.lens.formula.shiftExtraArguments": "[shift]?: string", + "xpack.lens.formula.string": "chaîne", + "xpack.lens.formula.value": "valeur", + "xpack.lens.formulaCommonFormulaDocumentation": "Les formules les plus courantes divisent deux valeurs pour produire un pourcentage. Pour obtenir un affichage correct, définissez \"Format de valeur\" sur \"pourcent\".", + "xpack.lens.formulaDocumentation.columnCalculationSection": "Calculs de colonnes", + "xpack.lens.formulaDocumentation.columnCalculationSectionDescription": "Ces fonctions sont exécutées pour chaque ligne, mais elles sont fournies avec la colonne entière comme contexte. Elles sont également appelées fonctions de fenêtre.", + "xpack.lens.formulaDocumentation.elasticsearchSection": "Elasticsearch", + "xpack.lens.formulaDocumentation.elasticsearchSectionDescription": "Ces fonctions seront exécutées sur les documents bruts pour chaque ligne du tableau résultant, en agrégeant tous les documents correspondant aux dimensions de répartition en une seule valeur.", + "xpack.lens.formulaDocumentation.filterRatio": "Rapport de filtre", + "xpack.lens.formulaDocumentation.header": "Référence de formule", + "xpack.lens.formulaDocumentation.mathSection": "Mathématique", + "xpack.lens.formulaDocumentation.mathSectionDescription": "Ces fonctions seront exécutées pour chaque ligne du tableau résultant en utilisant des valeurs uniques de la même ligne calculées à l'aide d'autres fonctions.", + "xpack.lens.formulaDocumentation.percentOfTotal": "Pourcentage du total", + "xpack.lens.formulaDocumentation.weekOverWeek": "Semaine après semaine", + "xpack.lens.formulaDocumentationHeading": "Fonctionnement", + "xpack.lens.formulaEnableWordWrapLabel": "Activer le renvoi à la ligne des mots", + "xpack.lens.formulaErrorCount": "{count} {count, plural, one {erreur} other {erreurs}}", + "xpack.lens.formulaExampleMarkdown": "Exemples", + "xpack.lens.formulaFrequentlyUsedHeading": "Formules courantes", + "xpack.lens.formulaPlaceholderText": "Saisissez une formule en combinant des fonctions avec la fonction mathématique, telle que :", + "xpack.lens.formulaSearchPlaceholder": "Rechercher des fonctions", + "xpack.lens.formulaWarningCount": "{count} {count, plural, one {avertissement} other {avertissements}}", + "xpack.lens.functions.counterRate.args.byHelpText": "Colonne selon laquelle le calcul du taux de compteur sera divisé", + "xpack.lens.functions.counterRate.args.inputColumnIdHelpText": "Colonne pour laquelle le taux de compteur sera calculé", + "xpack.lens.functions.counterRate.args.outputColumnIdHelpText": "Colonne dans laquelle le taux de compteur résultant sera stocké", + "xpack.lens.functions.counterRate.args.outputColumnNameHelpText": "Nom de la colonne dans laquelle le taux de compteur résultant sera stocké", + "xpack.lens.functions.counterRate.help": "Calcule le taux de compteur d'une colonne dans un tableau de données", + "xpack.lens.functions.lastValue.missingSortField": "Ce modèle d'indexation ne contient aucun champ de date", + "xpack.lens.functions.mergeTables.help": "Aide pour fusionner n'importe quel nombre de tableaux Kibana en un tableau unique et l'exposer via un adaptateur d'inspecteur", + "xpack.lens.functions.renameColumns.help": "Aide pour renommer les colonnes d'un tableau de données", + "xpack.lens.functions.renameColumns.idMap.help": "Un objet encodé JSON dans lequel les clés sont les anciens ID de colonne et les valeurs sont les nouveaux ID correspondants. Tous les autres ID de colonne sont conservés.", + "xpack.lens.functions.timeScale.dateColumnMissingMessage": "L'ID de colonne de date {columnId} n'existe pas.", + "xpack.lens.functions.timeScale.timeInfoMissingMessage": "Impossible de récupérer les informations d'histogramme des dates", + "xpack.lens.geoFieldWorkspace.dropMessage": "Déposer le champ ici pour l'ouvrir dans Maps", + "xpack.lens.geoFieldWorkspace.dropZoneLabel": "zone de dépôt pour ouvrir dans Maps", + "xpack.lens.heatmap.addLayer": "Ajouter un calque de visualisation", + "xpack.lens.heatmap.cellValueLabel": "Valeur de cellule", + "xpack.lens.heatmap.groupLabel": "Carte thermique", + "xpack.lens.heatmap.heatmapLabel": "Carte thermique", + "xpack.lens.heatmap.horizontalAxisLabel": "Axe horizontal", + "xpack.lens.heatmap.verticalAxisLabel": "Axe vertical", + "xpack.lens.heatmapChart.legendVisibility.hide": "Masquer", + "xpack.lens.heatmapChart.legendVisibility.show": "Afficher", + "xpack.lens.heatmapVisualization.arrayValuesWarningMessage": "{label} contient des valeurs de tableau. Le rendu de votre visualisation peut ne pas se présenter comme attendu.", + "xpack.lens.heatmapVisualization.heatmapGroupLabel": "Carte thermique", + "xpack.lens.heatmapVisualization.heatmapLabel": "Carte thermique", + "xpack.lens.heatmapVisualization.missingXAccessorLongMessage": "La configuration de l'axe horizontal est manquante.", + "xpack.lens.heatmapVisualization.missingXAccessorShortMessage": "Axe horizontal manquant.", + "xpack.lens.indexPattern.advancedSettings": "Ajouter des options avancées", + "xpack.lens.indexPattern.allFieldsLabel": "Tous les champs", + "xpack.lens.indexPattern.allFieldsLabelHelp": "Les champs disponibles ont des données dans les 500 premiers documents correspondant à vos filtres. Pour afficher tous les filtres, développez les champs vides. Certains types de champ ne peuvent pas être visualisés dans Lens, y compris les champ de texte intégral et champs géographiques.", + "xpack.lens.indexPattern.availableFieldsLabel": "Champs disponibles", + "xpack.lens.indexPattern.avg": "Moyenne", + "xpack.lens.indexPattern.avg.description": "Agrégation d'indicateurs à valeur unique qui calcule la moyenne des valeurs numériques extraites des documents agrégés", + "xpack.lens.indexPattern.avgOf": "Moyenne de {name}", + "xpack.lens.indexPattern.bytesFormatLabel": "Octets (1024)", + "xpack.lens.indexPattern.calculations.dateHistogramErrorMessage": "{name} requiert un histogramme des dates pour fonctionner. Ajoutez un histogramme des dates ou sélectionnez une autre fonction.", + "xpack.lens.indexPattern.calculations.layerDataType": "{name} est désactivé pour ce type de calque.", + "xpack.lens.indexPattern.cardinality": "Compte unique", + "xpack.lens.indexPattern.cardinality.signature": "champ : chaîne", + "xpack.lens.indexPattern.cardinalityOf": "Compte unique de {name}", + "xpack.lens.indexPattern.chooseField": "Sélectionner un champ", + "xpack.lens.indexPattern.chooseFieldLabel": "Pour utiliser cette fonction, sélectionnez un champ.", + "xpack.lens.indexPattern.chooseSubFunction": "Choisir une sous-fonction", + "xpack.lens.indexPattern.columnFormatLabel": "Format de valeur", + "xpack.lens.indexPattern.columnLabel": "Afficher le nom", + "xpack.lens.indexPattern.count": "Compte", + "xpack.lens.indexPattern.counterRate": "Taux de compteur", + "xpack.lens.indexPattern.counterRate.signature": "indicateur : nombre", + "xpack.lens.indexPattern.CounterRateOf": "Taux de compteur de {name}", + "xpack.lens.indexPattern.countOf": "Nombre d'enregistrements", + "xpack.lens.indexPattern.cumulative_sum.signature": "indicateur : nombre", + "xpack.lens.indexPattern.cumulativeSum": "Somme cumulée", + "xpack.lens.indexPattern.cumulativeSumOf": "Somme cumulée de {name}", + "xpack.lens.indexPattern.dateHistogram": "Histogramme des dates", + "xpack.lens.indexPattern.dateHistogram.autoAdvancedExplanation": "L'intervalle suit cette logique :", + "xpack.lens.indexPattern.dateHistogram.autoBasicExplanation": "L'histogramme des dates automatique divise un champ de données en groupes par intervalle.", + "xpack.lens.indexPattern.dateHistogram.autoBoundHeader": "Intervalle cible mesuré", + "xpack.lens.indexPattern.dateHistogram.autoHelpText": "Fonctionnement", + "xpack.lens.indexPattern.dateHistogram.autoInterval": "Personnaliser l'intervalle de temps", + "xpack.lens.indexPattern.dateHistogram.autoIntervalHeader": "Intervalle utilisé", + "xpack.lens.indexPattern.dateHistogram.autoLongerExplanation": "Pour choisir l'intervalle, Lens divise la plage temporelle spécifiée par le paramètre {targetBarSetting}. Lens calcule le meilleur intervalle pour vos données. Par exemple 30m, 1h et 12. Le nombre maximal de barres est défini par la valeur {maxBarSetting}.", + "xpack.lens.indexPattern.dateHistogram.days": "jours", + "xpack.lens.indexPattern.dateHistogram.hours": "heures", + "xpack.lens.indexPattern.dateHistogram.milliseconds": "millisecondes", + "xpack.lens.indexPattern.dateHistogram.minimumInterval": "Intervalle minimal", + "xpack.lens.indexPattern.dateHistogram.minutes": "minutes", + "xpack.lens.indexPattern.dateHistogram.month": "mois", + "xpack.lens.indexPattern.dateHistogram.moreThanYear": "Plus d'un an", + "xpack.lens.indexPattern.dateHistogram.restrictedInterval": "Intervalle fixé à {intervalValue} en raison de restrictions d'agrégation.", + "xpack.lens.indexPattern.dateHistogram.seconds": "secondes", + "xpack.lens.indexPattern.dateHistogram.titleHelp": "Fonctionnement de l'histogramme des dates automatique", + "xpack.lens.indexPattern.dateHistogram.upTo": "Jusqu'à", + "xpack.lens.indexPattern.dateHistogram.week": "semaine", + "xpack.lens.indexPattern.dateHistogram.year": "an", + "xpack.lens.indexPattern.decimalPlacesLabel": "Décimales", + "xpack.lens.indexPattern.defaultFormatLabel": "Par défaut", + "xpack.lens.indexPattern.derivative": "Différences", + "xpack.lens.indexPattern.derivativeOf": "Différences de {name}", + "xpack.lens.indexPattern.differences.signature": "indicateur : nombre", + "xpack.lens.indexPattern.editFieldLabel": "Modifier le champ de modèle d'indexation", + "xpack.lens.indexPattern.emptyDimensionButton": "Dimension vide", + "xpack.lens.indexPattern.emptyFieldsLabel": "Champs vides", + "xpack.lens.indexPattern.emptyFieldsLabelHelp": "Les champs vides ne contenaient aucune valeur dans les 500 premiers documents basés sur vos filtres.", + "xpack.lens.indexPattern.existenceErrorAriaLabel": "La récupération de l'existence a échoué", + "xpack.lens.indexPattern.existenceErrorLabel": "Impossible de charger les informations de champ", + "xpack.lens.indexPattern.existenceTimeoutAriaLabel": "La récupération de l'existence a expiré", + "xpack.lens.indexPattern.existenceTimeoutLabel": "Les informations de champ ont pris trop de temps", + "xpack.lens.indexPattern.fieldDistributionLabel": "Distribution", + "xpack.lens.indexPattern.fieldItem.visualizeGeoFieldLinkText": "Visualiser dans Maps", + "xpack.lens.indexPattern.fieldItemTooltip": "Effectuez un glisser-déposer pour visualiser.", + "xpack.lens.indexPattern.fieldNoOperation": "Le champ {field} ne peut pas être utilisé sans opération", + "xpack.lens.indexPattern.fieldNotFound": "Champ {invalidField} introuvable", + "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "Chaîne vide", + "xpack.lens.indexPattern.fieldPlaceholder": "Champ", + "xpack.lens.indexPattern.fieldStatsButtonAriaLabel": "Prévisualiser {fieldName} : {fieldType}", + "xpack.lens.indexPattern.fieldStatsButtonEmptyLabel": "Ce champ ne comporte aucune donnée mais vous pouvez toujours effectuer un glisser-déposer pour visualiser.", + "xpack.lens.indexPattern.fieldStatsButtonLabel": "Cliquez pour obtenir un aperçu du champ, ou effectuez un glisser-déposer pour visualiser.", + "xpack.lens.indexPattern.fieldStatsCountLabel": "Compte", + "xpack.lens.indexPattern.fieldStatsDisplayToggle": "Basculer soit", + "xpack.lens.indexPattern.fieldStatsLimited": "Le résumé des informations n'est pas disponible pour les champs de type de gamme.", + "xpack.lens.indexPattern.fieldStatsNoData": "Ce champ est vide car il n'existe pas dans les 500 documents échantillonnés. L'ajout de ce champ à la configuration peut générer un graphique vide.", + "xpack.lens.indexPattern.fieldTimeDistributionLabel": "Répartition du temps", + "xpack.lens.indexPattern.fieldTopValuesLabel": "Valeurs les plus élevées", + "xpack.lens.indexPattern.fieldWrongType": "Le champ {invalidField} a un type incorrect", + "xpack.lens.indexPattern.filterBy.clickToEdit": "Cliquer pour modifier", + "xpack.lens.indexPattern.filterBy.emptyFilterQuery": "(vide)", + "xpack.lens.indexPattern.filterBy.label": "Filtrer par", + "xpack.lens.indexPattern.filters": "Filtres", + "xpack.lens.indexPattern.filters.addaFilter": "Ajouter un filtre", + "xpack.lens.indexPattern.filters.clickToEdit": "Cliquer pour modifier", + "xpack.lens.indexPattern.filters.isInvalid": "Cette requête n'est pas valide", + "xpack.lens.indexPattern.filters.label.placeholder": "Tous les enregistrements", + "xpack.lens.indexPattern.filters.queryPlaceholderKql": "{example}", + "xpack.lens.indexPattern.filters.queryPlaceholderLucene": "{example}", + "xpack.lens.indexPattern.filters.removeFilter": "Retirer un filtre", + "xpack.lens.indexPattern.formulaExpressionNotHandled": "L'opération {operation} dans la formule ne comprend pas les paramètres suivants : {params}", + "xpack.lens.indexPattern.formulaExpressionParseError": "La formule {expression} ne peut pas être analysée", + "xpack.lens.indexPattern.formulaExpressionWrongType": "Les paramètres de l'opération {operation} dans la formule ont un type incorrect : {params}", + "xpack.lens.indexPattern.formulaFieldNotFound": "{variablesLength, plural, one {Champ} other {Champs}} {variablesList} introuvable(s)", + "xpack.lens.indexPattern.formulaFieldNotRequired": "L'opération {operation} n'accepte aucun champ comme argument", + "xpack.lens.indexPattern.formulaFieldValue": "champ", + "xpack.lens.indexPattern.formulaLabel": "Formule", + "xpack.lens.indexPattern.formulaMathMissingArgument": "L'opération {operation} dans la formule ne comprend pas les arguments {count} : {params}", + "xpack.lens.indexPattern.formulaMetricValue": "indicateur", + "xpack.lens.indexPattern.formulaNoFieldForOperation": "aucun champ", + "xpack.lens.indexPattern.formulaNoOperation": "aucune opération", + "xpack.lens.indexPattern.formulaOperationDoubleQueryError": "Utilisez uniquement kql= ou lucene=, mais pas les deux", + "xpack.lens.indexPattern.formulaOperationDuplicateParams": "Les paramètres de l'opération {operation} ont été déclarés plusieurs fois : {params}", + "xpack.lens.indexPattern.formulaOperationQueryError": "Des guillemets simples sont requis pour {language}='' à {rawQuery}", + "xpack.lens.indexPattern.formulaOperationTooManyFirstArguments": "L'opération {operation} dans la formule requiert un {type} {supported, plural, one {unique} other {pris en charge}}, trouvé : {text}", + "xpack.lens.indexPattern.formulaOperationValue": "opération", + "xpack.lens.indexPattern.formulaOperationwrongArgument": "L'opération {operation} dans la formule ne prend pas en charge les paramètres {type}, trouvé : {text}", + "xpack.lens.indexPattern.formulaOperationWrongFirstArgument": "Le premier argument pour {operation} doit être un nom {type}. Trouvé {argument}", + "xpack.lens.indexPattern.formulaParameterNotRequired": "L'opération {operation} n'accepte aucun paramètre", + "xpack.lens.indexPattern.formulaPartLabel": "Partie de {label}", + "xpack.lens.indexPattern.formulaWarning": "Formule actuellement appliquée", + "xpack.lens.indexPattern.formulaWarningText": "Pour écraser votre formule, sélectionnez une fonction rapide", + "xpack.lens.indexPattern.formulaWithTooManyArguments": "L'opération {operation} a trop d'arguments", + "xpack.lens.indexPattern.functionsLabel": "Sélectionner une fonction", + "xpack.lens.indexPattern.groupByDropdown": "Regrouper par", + "xpack.lens.indexPattern.incompleteOperation": "(incomplet)", + "xpack.lens.indexPattern.intervals": "Intervalles", + "xpack.lens.indexPattern.invalidFieldLabel": "Champ non valide. Vérifiez votre modèle d'indexation ou choisissez un autre champ.", + "xpack.lens.indexPattern.invalidInterval": "Valeur d'intervalle non valide", + "xpack.lens.indexPattern.invalidOperationLabel": "Ce champ ne fonctionne pas avec la fonction sélectionnée.", + "xpack.lens.indexPattern.invalidReferenceConfiguration": "La dimension \"{dimensionLabel}\" n'est pas configurée correctement", + "xpack.lens.indexPattern.invalidTimeShift": "Décalage non valide. Entrez un entier positif suivi par l'une des unités suivantes : s, m, h, d, w, M, y. Par exemple, 3h pour 3 heures", + "xpack.lens.indexPattern.lastValue": "Dernière valeur", + "xpack.lens.indexPattern.lastValue.disabled": "Cette fonction requiert la présence d'un champ de date dans votre index", + "xpack.lens.indexPattern.lastValue.invalidTypeSortField": "Le champ {invalidField} n'est pas un champ de date et ne peut pas être utilisé pour le tri", + "xpack.lens.indexPattern.lastValue.signature": "champ : chaîne", + "xpack.lens.indexPattern.lastValue.sortField": "Trier par le champ de date", + "xpack.lens.indexPattern.lastValue.sortFieldNotFound": "Champ {invalidField} introuvable", + "xpack.lens.indexPattern.lastValue.sortFieldPlaceholder": "Champ de tri", + "xpack.lens.indexPattern.lastValueOf": "Dernière valeur de {name}", + "xpack.lens.indexPattern.layerErrorWrapper": "Erreur de {position} pour le calque : {wrappedMessage}", + "xpack.lens.indexPattern.max": "Maximum", + "xpack.lens.indexPattern.max.description": "Agrégation d'indicateurs à valeur unique qui renvoie la valeur maximale des valeurs numériques extraites des documents agrégés.", + "xpack.lens.indexPattern.maxOf": "Maximum de {name}", + "xpack.lens.indexPattern.median": "Médiane", + "xpack.lens.indexPattern.median.description": "Agrégation d'indicateurs à valeur unique qui calcule la valeur médiane des valeurs numériques extraites des documents agrégés.", + "xpack.lens.indexPattern.medianOf": "Médiane de {name}", + "xpack.lens.indexPattern.metaFieldsLabel": "Champs méta", + "xpack.lens.indexPattern.metric.signature": "champ : chaîne", + "xpack.lens.indexPattern.min": "Minimum", + "xpack.lens.indexPattern.min.description": "Agrégation d'indicateurs à valeur unique qui renvoie la valeur minimale des valeurs numériques extraites des documents agrégés.", + "xpack.lens.indexPattern.minOf": "Minimum de {name}", + "xpack.lens.indexPattern.missingFieldLabel": "Champ manquant", + "xpack.lens.indexPattern.missingReferenceError": "\"{dimensionLabel}\" n'est pas entièrement configuré", + "xpack.lens.indexPattern.moveToWorkspace": "Ajouter {field} à l'espace de travail", + "xpack.lens.indexPattern.moveToWorkspaceDisabled": "Ce champ ne peut pas être ajouté automatiquement à l'espace de travail. Vous pouvez toujours l'utiliser directement dans le panneau de configuration.", + "xpack.lens.indexPattern.moving_average.signature": "indicateur : nombre, [window] : nombre", + "xpack.lens.indexPattern.movingAverage": "Moyenne mobile", + "xpack.lens.indexPattern.movingAverage.basicExplanation": "La moyenne mobile fait glisser une fenêtre sur les données et affiche la valeur moyenne. La moyenne mobile est prise en charge uniquement par les histogrammes des dates.", + "xpack.lens.indexPattern.movingAverage.helpText": "Fonctionnement", + "xpack.lens.indexPattern.movingAverage.limitations": "La première valeur de moyenne mobile commence au deuxième élément.", + "xpack.lens.indexPattern.movingAverage.longerExplanation": "Pour calculer la moyenne mobile, Lens utilise la moyenne de la fenêtre et applique une politique d'omission pour les blancs. Pour les valeurs manquantes, le groupe est ignoré, et le calcul est effectué sur la valeur suivante.", + "xpack.lens.indexPattern.movingAverage.tableExplanation": "Par exemple, avec les données [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], vous pouvez calculer une moyenne mobile simple avec une taille de fenêtre de 5 :", + "xpack.lens.indexPattern.movingAverage.titleHelp": "Fonctionnement de la moyenne mobile", + "xpack.lens.indexPattern.movingAverage.window": "Taille de fenêtre", + "xpack.lens.indexPattern.movingAverage.windowInitialPartial": "La fenêtre est partielle jusqu'à ce qu'elle atteigne le nombre demandé d'éléments. Par exemple, avec une taille de fenêtre de 5 :", + "xpack.lens.indexPattern.movingAverage.windowLimitations": "La fenêtre n'inclut pas la valeur actuelle.", + "xpack.lens.indexPattern.movingAverageOf": "Moyenne mobile de {name}", + "xpack.lens.indexPattern.multipleDateHistogramsError": "\"{dimensionLabel}\" n'est pas le seul histogramme des dates. Lorsque vous utilisez des décalages, veillez à n'utiliser qu'un seul histogramme des dates.", + "xpack.lens.indexPattern.numberFormatLabel": "Numéro", + "xpack.lens.indexPattern.ofDocumentsLabel": "documents", + "xpack.lens.indexPattern.operationsNotFound": "{operationLength, plural, one {Opération} other {Opérations}} {operationsList} non trouvée(s)", + "xpack.lens.indexPattern.otherDocsLabel": "Autre", + "xpack.lens.indexPattern.overall_metric": "indicateur : nombre", + "xpack.lens.indexPattern.overallAverageOf": "Moyenne générale de {name}", + "xpack.lens.indexPattern.overallMax": "Max général", + "xpack.lens.indexPattern.overallMaxOf": "Max général de {name}", + "xpack.lens.indexPattern.overallMin": "Min général", + "xpack.lens.indexPattern.overallMinOf": "Min général de {name}", + "xpack.lens.indexPattern.overallSum": "Somme générale", + "xpack.lens.indexPattern.overallSumOf": "Somme générale de {name}", + "xpack.lens.indexPattern.percentageOfLabel": "{percentage} % de", + "xpack.lens.indexPattern.percentFormatLabel": "Pour cent", + "xpack.lens.indexPattern.percentile": "Centile", + "xpack.lens.indexPattern.percentile.errorMessage": "Le centile doit être un entier compris entre 1 et 99", + "xpack.lens.indexPattern.percentile.percentileValue": "Centile", + "xpack.lens.indexPattern.percentile.signature": "champ : chaîne, [percentile] : nombre", + "xpack.lens.indexPattern.percentileOf": "{percentile, selectordinal, one {#er} two {#e} few {#e} other {#e}} centile de {name}", + "xpack.lens.indexPattern.pinnedTopValuesLabel": "Filtres de {field}", + "xpack.lens.indexPattern.quickFunctionsLabel": "Fonctions rapides", + "xpack.lens.indexPattern.range.isInvalid": "Cette plage n'est pas valide", + "xpack.lens.indexPattern.ranges.addRange": "Ajouter une plage", + "xpack.lens.indexPattern.ranges.customIntervalsToggle": "Créer des plages personnalisées", + "xpack.lens.indexPattern.ranges.customRangeLabelPlaceholder": "Étiquette personnalisée", + "xpack.lens.indexPattern.ranges.customRanges": "Plages", + "xpack.lens.indexPattern.ranges.customRangesRemoval": "Retirer les plages personnalisées", + "xpack.lens.indexPattern.ranges.decreaseButtonLabel": "Diminuer la granularité", + "xpack.lens.indexPattern.ranges.deleteRange": "Supprimer la plage", + "xpack.lens.indexPattern.ranges.granularity": "Granularité des intervalles", + "xpack.lens.indexPattern.ranges.granularityHelpText": "Fonctionnement", + "xpack.lens.indexPattern.ranges.granularityPopoverAdvancedExplanation": "Les intervalles sont incrémentés par 10, 5 ou 2. Par exemple, un intervalle peut être 100 ou 0,2 .", + "xpack.lens.indexPattern.ranges.granularityPopoverBasicExplanation": "La granularité des intervalles divise le champ en intervalles régulièrement espacés sur la base des valeurs minimales et maximales du champ.", + "xpack.lens.indexPattern.ranges.granularityPopoverExplanation": "La taille de l'intervalle est une valeur de \"gentillesse\". Lorsque la granularité du curseur change, l'intervalle reste le même lorsque l'intervalle de \"gentillesse\" est le même. La granularité minimale est 1, et la valeur maximale est {setting}. Pour modifier la granularité maximale, accédez aux Paramètres avancés.", + "xpack.lens.indexPattern.ranges.granularityPopoverTitle": "Fonctionnement de la granularité des intervalles", + "xpack.lens.indexPattern.ranges.increaseButtonLabel": "Augmenter la granularité", + "xpack.lens.indexPattern.ranges.lessThanOrEqualAppend": "≤", + "xpack.lens.indexPattern.ranges.lessThanOrEqualTooltip": "Inférieur ou égal à", + "xpack.lens.indexPattern.ranges.lessThanPrepend": "<", + "xpack.lens.indexPattern.ranges.lessThanTooltip": "Inférieur à", + "xpack.lens.indexPattern.records": "Enregistrements", + "xpack.lens.indexPattern.referenceFunctionPlaceholder": "Sous-fonction", + "xpack.lens.indexPattern.removeColumnAriaLabel": "Ajouter ou glisser-déposer un champ dans {groupLabel}", + "xpack.lens.indexPattern.removeColumnLabel": "Retirer la configuration de \"{groupLabel}\"", + "xpack.lens.indexPattern.removeFieldLabel": "Retirer le champ du modèle d'indexation", + "xpack.lens.indexPattern.sortField.invalid": "Champ non valide. Vérifiez votre modèle d'indexation ou choisissez un autre champ.", + "xpack.lens.indexpattern.suggestions.nestingChangeLabel": "{innerOperation} pour chaque {outerOperation}", + "xpack.lens.indexpattern.suggestions.overallLabel": "{operation} générale", + "xpack.lens.indexpattern.suggestions.overTimeLabel": "Sur la durée", + "xpack.lens.indexPattern.sum": "Somme", + "xpack.lens.indexPattern.sum.description": "Agrégation d'indicateurs à valeur unique qui récapitule les valeurs numériques extraites des documents agrégés.", + "xpack.lens.indexPattern.sumOf": "Somme de {name}", + "xpack.lens.indexPattern.terms": "Valeurs les plus élevées", + "xpack.lens.indexPattern.terms.advancedSettings": "Avancé", + "xpack.lens.indexPattern.terms.missingBucketDescription": "Inclure les documents sans ce champ", + "xpack.lens.indexPattern.terms.missingLabel": "(valeur manquante)", + "xpack.lens.indexPattern.terms.orderAlphabetical": "Alphabétique", + "xpack.lens.indexPattern.terms.orderAscending": "Croissant", + "xpack.lens.indexPattern.terms.orderBy": "Classer par", + "xpack.lens.indexPattern.terms.orderByHelp": "Spécifie la dimension selon laquelle les valeurs les plus élevées sont classées.", + "xpack.lens.indexPattern.terms.orderDescending": "Décroissant", + "xpack.lens.indexPattern.terms.orderDirection": "Sens de classement", + "xpack.lens.indexPattern.terms.otherBucketDescription": "Regrouper les autres valeurs sous \"Autre\"", + "xpack.lens.indexPattern.terms.otherLabel": "Autre", + "xpack.lens.indexPattern.terms.size": "Nombre de valeurs", + "xpack.lens.indexPattern.termsOf": "Valeurs les plus élevées de {name}", + "xpack.lens.indexPattern.termsWithMultipleShifts": "Dans un seul calque, il est impossible de combiner des indicateurs avec des décalages temporels différents et des valeurs dynamiques les plus élevées. Utilisez la même valeur de décalage pour tous les indicateurs, ou utilisez des filtres à la place des valeurs les plus élevées.", + "xpack.lens.indexPattern.termsWithMultipleShiftsFixActionLabel": "Utiliser des filtres", + "xpack.lens.indexPattern.timeScale.enableTimeScale": "Normaliser par unité", + "xpack.lens.indexPattern.timeScale.label": "Normaliser par unité", + "xpack.lens.indexPattern.timeScale.tooltip": "Normalisez les valeurs pour qu'elles soient toujours affichées en tant que taux par unité de temps spécifiée, indépendamment de l'intervalle de dates sous-jacent.", + "xpack.lens.indexPattern.timeShift.12hours": "Il y a 12 heures (12h)", + "xpack.lens.indexPattern.timeShift.3hours": "Il y a 3 heures (3h)", + "xpack.lens.indexPattern.timeShift.3months": "Il y a 3 mois (3M)", + "xpack.lens.indexPattern.timeShift.6hours": "Il y a 6 heures (6h)", + "xpack.lens.indexPattern.timeShift.6months": "Il y a 6 mois (6M)", + "xpack.lens.indexPattern.timeShift.day": "Il y a 1 jour (1d)", + "xpack.lens.indexPattern.timeShift.help": "Entrer le nombre et l'unité du décalage temporel", + "xpack.lens.indexPattern.timeShift.hour": "Il y a 1 heure (1h)", + "xpack.lens.indexPattern.timeShift.label": "Décalage temporel", + "xpack.lens.indexPattern.timeShift.month": "Il y a 1 mois (1M)", + "xpack.lens.indexPattern.timeShift.noMultipleHelp": "Le décalage temporel doit être un multiple de l'intervalle de l'histogramme des dates. Ajustez le décalage ou l'intervalle de l'histogramme des dates", + "xpack.lens.indexPattern.timeShift.tooSmallHelp": "Le décalage temporel doit être supérieur à l'intervalle de l'histogramme des dates. Augmentez le décalage ou spécifiez un intervalle plus petit dans l'histogramme des dates", + "xpack.lens.indexPattern.timeShift.week": "Il y a 1 semaine (1w)", + "xpack.lens.indexPattern.timeShift.year": "Il y a 1 an (1y)", + "xpack.lens.indexPattern.timeShiftMultipleWarning": "{label} utilise un décalage temporel de {columnTimeShift} qui n'est pas un multiple de l'intervalle de l'histogramme des dates de {interval}. Pour éviter une non-correspondance des données, utilisez un multiple de {interval} comme décalage.", + "xpack.lens.indexPattern.timeShiftPlaceholder": "Saisissez des valeurs personnalisées (par ex. 8w)", + "xpack.lens.indexPattern.timeShiftSmallWarning": "{label} utilise un décalage temporel de {columnTimeShift} qui est inférieur à l'intervalle de l'histogramme des dates de {interval}. Pour éviter une non-correspondance des données, utilisez un multiple de {interval} comme décalage.", + "xpack.lens.indexPattern.uniqueLabel": "{label} [{num}]", + "xpack.lens.indexPattern.useAsTopLevelAgg": "Regrouper d'abord en fonction de ce champ", + "xpack.lens.indexPatterns.actionsPopoverLabel": "Paramètres du modèle d'indexation", + "xpack.lens.indexPatterns.addFieldButton": "Ajouter un champ au modèle d'indexation", + "xpack.lens.indexPatterns.clearFiltersLabel": "Effacer le nom et saisissez les filtres", + "xpack.lens.indexPatterns.fieldFiltersLabel": "Filtrer par type", + "xpack.lens.indexPatterns.fieldSearchLiveRegion": "{availableFields} {availableFields, plural, one {champ} other {champs}} disponible(s). {emptyFields} {emptyFields, plural, one {champ} other {champs}} vide(s). {metaFields} {metaFields, plural, one {champ} other {champs}} méta.", + "xpack.lens.indexPatterns.filterByNameLabel": "Rechercher les noms des champs", + "xpack.lens.indexPatterns.manageFieldButton": "Gérer les champs du modèle d'indexation", + "xpack.lens.indexPatterns.noAvailableDataLabel": "Aucun champ disponible ne contient de données.", + "xpack.lens.indexPatterns.noDataLabel": "Aucun champ.", + "xpack.lens.indexPatterns.noEmptyDataLabel": "Aucun champ vide.", + "xpack.lens.indexPatterns.noFields.extendTimeBullet": "Extension de la plage temporelle", + "xpack.lens.indexPatterns.noFields.fieldTypeFilterBullet": "Utilisation de différents filtres de champ", + "xpack.lens.indexPatterns.noFields.globalFiltersBullet": "Modification des filtres globaux", + "xpack.lens.indexPatterns.noFields.tryText": "Essayer :", + "xpack.lens.indexPatterns.noFieldsLabel": "Aucun champ n'existe dans ce modèle d'indexation.", + "xpack.lens.indexPatterns.noFilteredFieldsLabel": "Aucun champ ne correspond aux filtres sélectionnés.", + "xpack.lens.indexPatterns.noMetaDataLabel": "Aucun champ méta.", + "xpack.lens.indexPatternSuggestion.removeLayerLabel": "Afficher uniquement {indexPatternTitle}", + "xpack.lens.indexPatternSuggestion.removeLayerPositionLabel": "Afficher uniquement le calque {layerNumber}", + "xpack.lens.labelInput.label": "Étiquette", + "xpack.lens.layerPanel.layerVisualizationType": "Type de visualisation du calque", + "xpack.lens.lensSavedObjectLabel": "Visualisation Lens", + "xpack.lens.metric.addLayer": "Ajouter un calque de visualisation", + "xpack.lens.metric.groupLabel": "Valeur tabulaire et unique", + "xpack.lens.metric.label": "Indicateur", + "xpack.lens.pageTitle": "Lens", + "xpack.lens.paletteHeatmapGradient.customize": "Modifier", + "xpack.lens.paletteHeatmapGradient.customizeLong": "Modifier la palette", + "xpack.lens.paletteHeatmapGradient.label": "Couleur", + "xpack.lens.palettePicker.label": "Palette de couleurs", + "xpack.lens.paletteTableGradient.customize": "Modifier", + "xpack.lens.paletteTableGradient.label": "Couleur", + "xpack.lens.pie.addLayer": "Ajouter un calque de visualisation", + "xpack.lens.pie.arrayValues": "{label} contient des valeurs de tableau. Le rendu de votre visualisation peut ne pas se présenter comme attendu.", + "xpack.lens.pie.donutLabel": "Graphique en anneau", + "xpack.lens.pie.groupLabel": "Proportion", + "xpack.lens.pie.groupsizeLabel": "Taille par", + "xpack.lens.pie.pielabel": "Camembert", + "xpack.lens.pie.sliceGroupLabel": "Section par", + "xpack.lens.pie.suggestionLabel": "Comme {chartName}", + "xpack.lens.pie.treemapGroupLabel": "Regrouper par", + "xpack.lens.pie.treemaplabel": "Compartimentage", + "xpack.lens.pie.treemapSuggestionLabel": "Comme compartimentage", + "xpack.lens.pieChart.categoriesInLegendLabel": "Masquer les étiquettes", + "xpack.lens.pieChart.fitInsideOnlyLabel": "À l'intérieur uniquement", + "xpack.lens.pieChart.hiddenNumbersLabel": "Masquer dans le graphique", + "xpack.lens.pieChart.labelPositionLabel": "Position", + "xpack.lens.pieChart.legendVisibility.auto": "Auto", + "xpack.lens.pieChart.legendVisibility.hide": "Masquer", + "xpack.lens.pieChart.legendVisibility.show": "Afficher", + "xpack.lens.pieChart.nestedLegendLabel": "Imbriqué", + "xpack.lens.pieChart.numberLabels": "Valeurs", + "xpack.lens.pieChart.percentDecimalsLabel": "Nombre maximal de décimales pour les pourcentages", + "xpack.lens.pieChart.showCategoriesLabel": "Intérieur ou extérieur", + "xpack.lens.pieChart.showFormatterValuesLabel": "Afficher la valeur", + "xpack.lens.pieChart.showPercentValuesLabel": "Afficher le pourcentage", + "xpack.lens.pieChart.showTreemapCategoriesLabel": "Afficher les étiquettes", + "xpack.lens.pieChart.valuesLabel": "Étiquettes", + "xpack.lens.resetLayerAriaLabel": "Réinitialiser le calque {index}", + "xpack.lens.resetVisualizationAriaLabel": "Réinitialiser la visualisation", + "xpack.lens.searchTitle": "Lens : créer des visualisations", + "xpack.lens.section.configPanelLabel": "Panneau de configuration", + "xpack.lens.section.dataPanelLabel": "Panneau de données", + "xpack.lens.section.workspaceLabel": "Espace de travail de visualisation", + "xpack.lens.shared.chartValueLabelVisibilityLabel": "Étiquettes", + "xpack.lens.shared.curveLabel": "Options visuelles", + "xpack.lens.shared.legend.filterForValueButtonAriaLabel": "Filtre pour la valeur", + "xpack.lens.shared.legend.filterOptionsLegend": "{legendDataLabel}, options de filtre", + "xpack.lens.shared.legend.filterOutValueButtonAriaLabel": "Filtrer la valeur", + "xpack.lens.shared.legendAlignmentLabel": "Alignement", + "xpack.lens.shared.legendInsideAlignmentLabel": "Alignement", + "xpack.lens.shared.legendInsideColumnsLabel": "Nombre de colonnes", + "xpack.lens.shared.legendInsideLocationAlignmentLabel": "Alignement", + "xpack.lens.shared.legendInsideTooltip": "Requiert que la légende soit placée dans la visualisation", + "xpack.lens.shared.legendIsTruncated": "Requiert que le texte soit tronqué", + "xpack.lens.shared.legendLabel": "Légende", + "xpack.lens.shared.legendLocationBottomLeft": "En bas à gauche", + "xpack.lens.shared.legendLocationBottomRight": "En bas à droite", + "xpack.lens.shared.legendLocationLabel": "Emplacement", + "xpack.lens.shared.legendLocationTopLeft": "En haut à gauche", + "xpack.lens.shared.legendLocationTopRight": "En haut à droite", + "xpack.lens.shared.legendPositionBottom": "Bas", + "xpack.lens.shared.legendPositionLeft": "Gauche", + "xpack.lens.shared.legendPositionRight": "Droite", + "xpack.lens.shared.legendPositionTop": "Haut", + "xpack.lens.shared.legendVisibilityLabel": "Affichage", + "xpack.lens.shared.legendVisibleTooltip": "Requiert que la légende soit affichée", + "xpack.lens.shared.maxLinesLabel": "Nombre maximal de lignes", + "xpack.lens.shared.nestedLegendLabel": "Imbriqué", + "xpack.lens.shared.truncateLegend": "Tronquer le texte", + "xpack.lens.shared.valueInLegendLabel": "Afficher la valeur", + "xpack.lens.sugegstion.refreshSuggestionLabel": "Actualiser", + "xpack.lens.suggestion.refreshSuggestionTooltip": "Actualisez les suggestions en fonction de la visualisation sélectionnée.", + "xpack.lens.suggestions.currentVisLabel": "Visualisation en cours", + "xpack.lens.table.actionsLabel": "Afficher les actions", + "xpack.lens.table.alignment.center": "Centre", + "xpack.lens.table.alignment.label": "Alignement du texte", + "xpack.lens.table.alignment.left": "Gauche", + "xpack.lens.table.alignment.right": "Droite", + "xpack.lens.table.columnFilter.filterForValueText": "Filtre pour la colonne", + "xpack.lens.table.columnFilter.filterOutValueText": "Filtrer la colonne", + "xpack.lens.table.columnVisibilityLabel": "Masquer la colonne", + "xpack.lens.table.defaultAriaLabel": "Visualisation du tableau de données", + "xpack.lens.table.dynamicColoring.cell": "Cellule", + "xpack.lens.table.dynamicColoring.customPalette.colorStopsHelpPercentage": "Les types de valeurs en pourcentage sont relatifs à la plage complète des valeurs de données disponibles.", + "xpack.lens.table.dynamicColoring.label": "Couleur par valeur", + "xpack.lens.table.dynamicColoring.none": "Aucune", + "xpack.lens.table.dynamicColoring.rangeType.label": "Type de valeur", + "xpack.lens.table.dynamicColoring.rangeType.number": "Numéro", + "xpack.lens.table.dynamicColoring.rangeType.percent": "Pour cent", + "xpack.lens.table.dynamicColoring.text": "Texte", + "xpack.lens.table.hide.hideLabel": "Masquer", + "xpack.lens.table.palettePanelContainer.back": "Retour", + "xpack.lens.table.palettePanelTitle": "Modifier la couleur", + "xpack.lens.table.resize.reset": "Réinitialiser la largeur", + "xpack.lens.table.sort.ascLabel": "Trier dans l'ordre croissant", + "xpack.lens.table.sort.descLabel": "Trier dans l'ordre décroissant", + "xpack.lens.table.summaryRow.average": "Moyenne", + "xpack.lens.table.summaryRow.count": "Compte de valeurs", + "xpack.lens.table.summaryRow.customlabel": "Étiquette de résumé", + "xpack.lens.table.summaryRow.label": "Ligne de résumé", + "xpack.lens.table.summaryRow.maximum": "Maximum", + "xpack.lens.table.summaryRow.minimum": "Minimum", + "xpack.lens.table.summaryRow.none": "Aucune", + "xpack.lens.table.summaryRow.sum": "Somme", + "xpack.lens.table.tableCellFilter.filterForValueAriaLabel": "Filtre pour la valeur : {cellContent}", + "xpack.lens.table.tableCellFilter.filterForValueText": "Filtre pour la valeur", + "xpack.lens.table.tableCellFilter.filterOutValueAriaLabel": "Filtrer la valeur : {cellContent}", + "xpack.lens.table.tableCellFilter.filterOutValueText": "Filtrer la valeur", + "xpack.lens.timeScale.removeLabel": "Retirer la normalisation par unité de temps", + "xpack.lens.timeShift.removeLabel": "Retirer le décalage temporel", + "xpack.lens.visTypeAlias.description": "Créez des visualisations avec notre éditeur de glisser-déposer. Basculez entre les différents types de visualisation à tout moment.", + "xpack.lens.visTypeAlias.note": "Recommandé pour la plupart des utilisateurs.", + "xpack.lens.visTypeAlias.title": "Lens", + "xpack.lens.visTypeAlias.type": "Lens", + "xpack.lens.visualizeGeoFieldMessage": "Lens ne peut pas visualiser les champs {fieldType}", + "xpack.lens.xyChart.addDataLayerLabel": "Ajouter un calque de visualisation", + "xpack.lens.xyChart.addLayer": "Ajouter un calque", + "xpack.lens.xyChart.addLayerTooltip": "Utilisez plusieurs calques pour combiner les types de visualisation ou pour visualiser différents modèles d'indexation.", + "xpack.lens.xyChart.axisExtent.custom": "Personnalisé", + "xpack.lens.xyChart.axisExtent.dataBounds": "Limites de données", + "xpack.lens.xyChart.axisExtent.disabledDataBoundsMessage": "Seuls les graphiques linéaires peuvent être adaptés aux limites de données", + "xpack.lens.xyChart.axisExtent.full": "Plein", + "xpack.lens.xyChart.axisExtent.label": "Limites", + "xpack.lens.xyChart.axisOrientation.angled": "En angle", + "xpack.lens.xyChart.axisOrientation.horizontal": "Horizontal", + "xpack.lens.xyChart.axisOrientation.label": "Orientation", + "xpack.lens.xyChart.axisOrientation.vertical": "Vertical", + "xpack.lens.xyChart.axisSide.auto": "Auto", + "xpack.lens.xyChart.axisSide.bottom": "Bas", + "xpack.lens.xyChart.axisSide.label": "Côté de l'axe", + "xpack.lens.xyChart.axisSide.left": "Gauche", + "xpack.lens.xyChart.axisSide.right": "Droite", + "xpack.lens.xyChart.axisSide.top": "Haut", + "xpack.lens.xyChart.axisTitlesSettings.help": "Afficher les titres des axes X et Y", + "xpack.lens.xyChart.bottomAxisDisabledHelpText": "Ce paramètre s'applique uniquement lorsque l'axe du bas est activé.", + "xpack.lens.xyChart.bottomAxisLabel": "Axe du bas", + "xpack.lens.xyChart.boundaryError": "La limite inférieure doit être plus grande que la limite supérieure", + "xpack.lens.xyChart.curveStyleLabel": "Courbes", + "xpack.lens.xyChart.curveType.help": "Définir de quelle façon le type de courbe est rendu pour un graphique linéaire", + "xpack.lens.xyChart.emptyXLabel": "(vide)", + "xpack.lens.xyChart.extentMode.help": "Mode d'extension", + "xpack.lens.xyChart.fillOpacity.help": "Définir l'opacité du remplissage du graphique en aires", + "xpack.lens.xyChart.fillOpacityLabel": "Opacité de remplissage", + "xpack.lens.xyChart.fittingFunction.help": "Définir le mode de traitement des valeurs manquantes", + "xpack.lens.xyChart.floatingColumns.help": "Spécifie le nombre de colonnes lorsque la légende est affichée à l'intérieur du graphique.", + "xpack.lens.xyChart.Gridlines": "Quadrillage", + "xpack.lens.xyChart.gridlinesSettings.help": "Afficher le quadrillage des axes X et Y", + "xpack.lens.xyChart.help": "Graphique X/Y", + "xpack.lens.xyChart.hideEndzones.help": "Masquer les marqueurs de zone de fin pour les données partielles", + "xpack.lens.xyChart.horizontalAlignment.help": "Spécifie l'alignement horizontal de la légende lorsqu'elle est affichée à l'intérieur du graphique.", + "xpack.lens.xyChart.horizontalAxisLabel": "Axe horizontal", + "xpack.lens.xyChart.inclusiveZero": "Les limites doivent inclure zéro.", + "xpack.lens.xyChart.isInside.help": "Spécifie si une légende se trouve à l'intérieur d'un graphique", + "xpack.lens.xyChart.isVisible.help": "Spécifie si la légende est visible ou non.", + "xpack.lens.xyChart.labelsOrientation.help": "Définit la rotation des étiquettes des axes", + "xpack.lens.xyChart.leftAxisDisabledHelpText": "Ce paramètre s'applique uniquement lorsque l'axe de gauche est activé.", + "xpack.lens.xyChart.leftAxisLabel": "Axe de gauche", + "xpack.lens.xyChart.legend.help": "Configurez la légende du graphique.", + "xpack.lens.xyChart.legendLocation.inside": "Intérieur", + "xpack.lens.xyChart.legendLocation.outside": "Extérieur", + "xpack.lens.xyChart.legendVisibility.auto": "Auto", + "xpack.lens.xyChart.legendVisibility.hide": "Masquer", + "xpack.lens.xyChart.legendVisibility.show": "Afficher", + "xpack.lens.xyChart.lowerBoundLabel": "Limite inférieure", + "xpack.lens.xyChart.maxLines.help": "Spécifie le nombre de lignes par élément de légende.", + "xpack.lens.xyChart.missingValuesLabel": "Valeurs manquantes", + "xpack.lens.xyChart.missingValuesLabelHelpText": "Par défaut, Lens masque les blancs dans les données. Pour remplir le blanc, effectuez une sélection.", + "xpack.lens.xyChart.nestUnderRoot": "Ensemble de données entier", + "xpack.lens.xyChart.position.help": "Spécifie la position de la légende.", + "xpack.lens.xyChart.renderer.help": "Outil de rendu de graphique X/Y", + "xpack.lens.xyChart.rightAxisDisabledHelpText": "Ce paramètre s'applique uniquement lorsque l'axe de droite est activé.", + "xpack.lens.xyChart.rightAxisLabel": "Axe de droite", + "xpack.lens.xyChart.seriesColor.auto": "Auto", + "xpack.lens.xyChart.seriesColor.label": "Couleur de la série", + "xpack.lens.xyChart.shouldTruncate.help": "Spécifie si les éléments de légende seront tronqués ou non", + "xpack.lens.xyChart.showEnzones": "Afficher les marqueurs de données partielles", + "xpack.lens.xyChart.showSingleSeries.help": "Spécifie si une légende comportant une seule entrée doit être affichée", + "xpack.lens.xyChart.splitSeries": "Répartir par", + "xpack.lens.xyChart.tickLabels": "Étiquettes de graduation", + "xpack.lens.xyChart.tickLabelsSettings.help": "Afficher les étiquettes de graduation des axes X et Y", + "xpack.lens.xyChart.title.help": "Titre de l'axe", + "xpack.lens.xyChart.topAxisDisabledHelpText": "Ce paramètre s'applique uniquement lorsque l'axe du haut est activé.", + "xpack.lens.xyChart.topAxisLabel": "Axe du haut", + "xpack.lens.xyChart.upperBoundLabel": "Limite supérieure", + "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "Ce paramètre ne peut pas être modifié dans les histogrammes.", + "xpack.lens.xyChart.valuesInLegend.help": "Afficher les valeurs dans la légende", + "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "Ce paramètre ne peut pas être modifié dans les graphiques en aires à pourcentages.", + "xpack.lens.xyChart.valuesStackedDisabledHelpText": "Ce paramètre ne peut pas être modifié dans les graphiques empilés ou les graphiques à barres à pourcentages", + "xpack.lens.xyChart.verticalAlignment.help": "Spécifie l'alignement vertical de la légende lorsqu'elle est affichée à l'intérieur du graphique.", + "xpack.lens.xyChart.verticalAxisLabel": "Axe vertical", + "xpack.lens.xyChart.xAxisGridlines.help": "Spécifie si le quadrillage de l'axe X est visible ou non.", + "xpack.lens.xyChart.xAxisLabelsOrientation.help": "Spécifie l'orientation des étiquettes de l'axe X.", + "xpack.lens.xyChart.xAxisTickLabels.help": "Spécifie si les étiquettes de graduation de l'axe X sont visibles ou non.", + "xpack.lens.xyChart.xAxisTitle.help": "Spécifie si le titre de l'axe X est visible ou non.", + "xpack.lens.xyChart.xTitle.help": "Titre de l'axe X", + "xpack.lens.xyChart.yLeftAxisgridlines.help": "Spécifie si le quadrillage de l'axe Y de gauche est visible ou non.", + "xpack.lens.xyChart.yLeftAxisLabelsOrientation.help": "Spécifie l'orientation des étiquettes de l'axe Y de gauche.", + "xpack.lens.xyChart.yLeftAxisTickLabels.help": "Spécifie si les étiquettes de graduation de l'axe Y de gauche sont visibles ou non.", + "xpack.lens.xyChart.yLeftAxisTitle.help": "Spécifie si le titre de l'axe Y de gauche est visible ou non.", + "xpack.lens.xyChart.yLeftExtent.help": "Portée de l'axe Y de gauche", + "xpack.lens.xyChart.yLeftTitle.help": "Titre de l'axe Y de gauche", + "xpack.lens.xyChart.yRightAxisgridlines.help": "Spécifie si le quadrillage de l'axe Y de droite est visible ou non.", + "xpack.lens.xyChart.yRightAxisLabelsOrientation.help": "Spécifie l'orientation des étiquettes de l'axe Y de droite.", + "xpack.lens.xyChart.yRightAxisTickLabels.help": "Spécifie si les étiquettes de graduation de l'axe Y de droite sont visibles ou non.", + "xpack.lens.xyChart.yRightAxisTitle.help": "Spécifie si le titre de l'axe Y de droite est visible ou non.", + "xpack.lens.xyChart.yRightExtent.help": "Portée de l'axe Y de droite", + "xpack.lens.xyChart.yRightTitle.help": "Titre de l'axe Y de droite", + "xpack.lens.xySuggestions.asPercentageTitle": "Pourcentage", + "xpack.lens.xySuggestions.barChartTitle": "Graphique à barres", + "xpack.lens.xySuggestions.dateSuggestion": "{yTitle} sur {xTitle}", + "xpack.lens.xySuggestions.emptyAxisTitle": "(vide)", + "xpack.lens.xySuggestions.flipTitle": "Retourner", + "xpack.lens.xySuggestions.lineChartTitle": "Graphique linéaire", + "xpack.lens.xySuggestions.nonDateSuggestion": "{yTitle} de {xTitle}", + "xpack.lens.xySuggestions.stackedChartTitle": "Empilé", + "xpack.lens.xySuggestions.unstackedChartTitle": "Non empilé", + "xpack.lens.xySuggestions.yAxixConjunctionSign": " & ", + "xpack.lens.xyVisualization.areaLabel": "Zone", + "xpack.lens.xyVisualization.arrayValues": "{label} contient des valeurs de tableau. Le rendu de votre visualisation peut ne pas se présenter comme attendu.", + "xpack.lens.xyVisualization.barGroupLabel": "Barre", + "xpack.lens.xyVisualization.barHorizontalFullLabel": "Horizontal à barres", + "xpack.lens.xyVisualization.barHorizontalLabel": "H. Barres", + "xpack.lens.xyVisualization.barLabel": "Vertical à barres", + "xpack.lens.xyVisualization.dataFailureSplitLong": "{layers, plural, one {Le calque} other {Les calques}} {layersList} {layers, plural, one {requiert} other {requièrent}} un champ pour {axis}.", + "xpack.lens.xyVisualization.dataFailureSplitShort": "{axis} manquant.", + "xpack.lens.xyVisualization.dataFailureYLong": "{layers, plural, one {Le calque} other {Les calques}} {layersList} {layers, plural, one {requiert} other {requièrent}} un champ pour {axis}.", + "xpack.lens.xyVisualization.dataFailureYShort": "{axis} manquant.", + "xpack.lens.xyVisualization.dataTypeFailureXLong": "Non-correspondance des types de données pour {axis}. Impossible de mélanger les types d'intervalle date et nombre.", + "xpack.lens.xyVisualization.dataTypeFailureXOrdinalLong": "Non-correspondance de type de données pour {axis}, utilisez une autre fonction.", + "xpack.lens.xyVisualization.dataTypeFailureXShort": "Type de données incorrect pour {axis}.", + "xpack.lens.xyVisualization.dataTypeFailureYLong": "La dimension {label} fournie pour {axis} possède un type de données incorrect. Nombre attendu mais possède {dataType}", + "xpack.lens.xyVisualization.dataTypeFailureYShort": "Type de données incorrect pour {axis}.", + "xpack.lens.xyVisualization.lineGroupLabel": "Linéaire et en aires", + "xpack.lens.xyVisualization.lineLabel": "Ligne", + "xpack.lens.xyVisualization.mixedBarHorizontalLabel": "Horizontal à barres mixte", + "xpack.lens.xyVisualization.mixedLabel": "XY mixte", + "xpack.lens.xyVisualization.stackedAreaLabel": "En aires empilées", + "xpack.lens.xyVisualization.stackedBarHorizontalFullLabel": "Horizontal à barres empilées", + "xpack.lens.xyVisualization.stackedBarHorizontalLabel": "H. À barres empilées", + "xpack.lens.xyVisualization.stackedBarLabel": "Vertical à barres empilées", + "xpack.lens.xyVisualization.stackedPercentageAreaLabel": "En aires à pourcentages", + "xpack.lens.xyVisualization.stackedPercentageBarHorizontalFullLabel": "Horizontal à barres à pourcentages", + "xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel": "H. À barres à pourcentages", + "xpack.lens.xyVisualization.stackedPercentageBarLabel": "Vertical à barres à pourcentages", + "xpack.lens.xyVisualization.xyLabel": "XY", + "advancedSettings.advancedSettingsLabel": "Paramètres avancés", + "advancedSettings.badge.readOnly.text": "Lecture seule", + "advancedSettings.badge.readOnly.tooltip": "Impossible d’enregistrer les paramètres avancés", + "advancedSettings.callOutCautionDescription": "Soyez prudent, ces paramètres sont destinés aux utilisateurs très avancés uniquement. Toute modification est susceptible d’entraîner des dommages importants à Kibana. Certains de ces paramètres peuvent être non documentés, non pris en charge ou expérimentaux. Lorsqu’un champ dispose d’une valeur par défaut, le laisser vide entraîne l’application de cette valeur par défaut, ce qui peut ne pas être acceptable compte tenu d’autres directives de configuration. Toute suppression d'un paramètre personnalisé de la configuration de Kibana est définitive.", + "advancedSettings.callOutCautionTitle": "Attention : toute action est susceptible de provoquer des dommages.", + "advancedSettings.categoryNames.dashboardLabel": "Tableau de bord", + "advancedSettings.categoryNames.discoverLabel": "Discover", + "advancedSettings.categoryNames.generalLabel": "Général", + "advancedSettings.categoryNames.machineLearningLabel": "Machine Learning", + "advancedSettings.categoryNames.notificationsLabel": "Notifications", + "advancedSettings.categoryNames.observabilityLabel": "Observabilité", + "advancedSettings.categoryNames.reportingLabel": "Reporting", + "advancedSettings.categoryNames.searchLabel": "Recherche", + "advancedSettings.categoryNames.securitySolutionLabel": "Solution de sécurité", + "advancedSettings.categoryNames.timelionLabel": "Timelion", + "advancedSettings.categoryNames.visualizationsLabel": "Visualisations", + "advancedSettings.categorySearchLabel": "Catégorie", + "advancedSettings.featureCatalogueTitle": "Personnalisez votre expérience Kibana : modifiez le format de date, activez le mode sombre, et bien plus encore.", + "advancedSettings.field.changeImageLinkAriaLabel": "Modifier {ariaName}", + "advancedSettings.field.changeImageLinkText": "Modifier l'image", + "advancedSettings.field.codeEditorSyntaxErrorMessage": "Syntaxe JSON non valide", + "advancedSettings.field.customSettingAriaLabel": "Paramètre personnalisé", + "advancedSettings.field.customSettingTooltip": "Paramètre personnalisé", + "advancedSettings.field.defaultValueText": "Valeur par défaut : {value}", + "advancedSettings.field.defaultValueTypeJsonText": "Valeur par défaut : {value}", + "advancedSettings.field.deprecationClickAreaLabel": "Cliquez ici pour afficher la documentation de déclassement pour {settingName}.", + "advancedSettings.field.helpText": "Ce paramètre est défini par le serveur Kibana et ne peut pas être modifié.", + "advancedSettings.field.imageChangeErrorMessage": "Impossible d’enregistrer l'image", + "advancedSettings.field.invalidIconLabel": "Non valide", + "advancedSettings.field.offLabel": "Off", + "advancedSettings.field.onLabel": "On", + "advancedSettings.field.resetToDefaultLinkAriaLabel": "Réinitialiser {ariaName} à la valeur par défaut", + "advancedSettings.field.resetToDefaultLinkText": "Réinitialiser à la valeur par défaut", + "advancedSettings.field.settingIsUnsaved": "Le paramètre n'est actuellement pas enregistré.", + "advancedSettings.field.unsavedIconLabel": "Non enregistré", + "advancedSettings.form.cancelButtonLabel": "Annuler les modifications", + "advancedSettings.form.clearNoSearchResultText": "(effacer la recherche)", + "advancedSettings.form.clearSearchResultText": "(effacer la recherche)", + "advancedSettings.form.countOfSettingsChanged": "{unsavedCount} {unsavedCount, plural, one {paramètre non enregistré} other {paramètres non enregistrés} }{hiddenCount, plural, =0 {} other {, # masqués} }", + "advancedSettings.form.noSearchResultText": "Aucun paramètre trouvé pour {queryText}. {clearSearch}", + "advancedSettings.form.requiresPageReloadToastButtonLabel": "Actualiser la page", + "advancedSettings.form.requiresPageReloadToastDescription": "Un ou plusieurs paramètres nécessitent d’actualiser la page pour pouvoir prendre effet.", + "advancedSettings.form.saveButtonLabel": "Enregistrer les modifications", + "advancedSettings.form.saveButtonTooltipWithInvalidChanges": "Corrigez les paramètres non valides avant d'enregistrer.", + "advancedSettings.form.saveErrorMessage": "Enregistrement impossible", + "advancedSettings.form.searchResultText": "Les termes de la recherche masquent {settingsCount} paramètres {clearSearch}", + "advancedSettings.pageTitle": "Paramètres", + "advancedSettings.searchBar.unableToParseQueryErrorMessage": "Impossible d'analyser la requête", + "advancedSettings.searchBarAriaLabel": "Rechercher dans les paramètres avancés", + "advancedSettings.voiceAnnouncement.ariaLabel": "Informations de résultat des paramètres avancés", + "advancedSettings.voiceAnnouncement.noSearchResultScreenReaderMessage": "Il existe {optionLenght, plural, one {# option} other {# options}} dans {sectionLenght, plural, one {# section} other {# sections}}.", + "advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "Vous avez recherché {query}. Il existe {optionLenght, plural, one {# option} other {# options}} dans {sectionLenght, plural, one {# section} other {# sections}}.", + "alerts.documentationTitle": "Afficher la documentation", + "alerts.noPermissionsMessage": "Pour consulter les alertes, vous devez disposer de privilèges pour la fonctionnalité Alertes dans l'espace Kibana. Pour en savoir plus, contactez votre administrateur Kibana.", + "alerts.noPermissionsTitle": "Privilèges de fonctionnalité Kibana requis", + "autocomplete.fieldRequiredError": "Ce champ ne peut pas être vide.", + "autocomplete.invalidDateError": "Date non valide", + "autocomplete.invalidNumberError": "Nombre non valide", + "autocomplete.loadingDescription": "Chargement...", + "autocomplete.selectField": "Veuillez d'abord sélectionner un champ...", + "bfetch.disableBfetchCompression": "Désactiver la compression par lots", + "bfetch.disableBfetchCompressionDesc": "Vous pouvez désactiver la compression par lots. Cela permet de déboguer des requêtes individuelles, mais augmente la taille des réponses.", + "charts.advancedSettings.visualization.colorMappingText": "Mappe des valeurs à des couleurs spécifiques dans les graphiques avec la palette Compatibilité.", + "charts.advancedSettings.visualization.colorMappingTextDeprecation": "Ce paramètre est déclassé et ne sera plus pris en charge à partir de la version 8.0.", + "charts.advancedSettings.visualization.colorMappingTitle": "Mapping des couleurs", + "charts.colormaps.bluesText": "Bleus", + "charts.colormaps.greensText": "Verts", + "charts.colormaps.greenToRedText": "Vert à rouge", + "charts.colormaps.greysText": "Gris", + "charts.colormaps.redsText": "Rouges", + "charts.colormaps.yellowToRedText": "Jaune à rouge", + "charts.colorPicker.clearColor": "Réinitialiser la couleur", + "charts.colorPicker.setColor.screenReaderDescription": "Définir la couleur pour la valeur {legendDataLabel}", + "charts.countText": "Décompte", + "charts.functions.palette.args.colorHelpText": "Les couleurs de la palette. Accepte un nom de couleur {html}, {hex}, {hsl}, {hsla}, {rgb} ou {rgba}.", + "charts.functions.palette.args.gradientHelpText": "Concevoir une palette de dégradés lorsque c'est possible ?", + "charts.functions.palette.args.reverseHelpText": "Inverser la palette ?", + "charts.functions.palette.args.stopHelpText": "La couleur à laquelle s’arrête la palette. Si utilisé, doit être associé à chaque couleur.", + "charts.functions.paletteHelpText": "Crée une palette de couleurs.", + "charts.functions.systemPalette.args.nameHelpText": "Nom de la palette dans la liste des palettes", + "charts.functions.systemPaletteHelpText": "Crée une palette de couleurs dynamique.", + "charts.legend.toggleLegendButtonAriaLabel": "Afficher/Masquer la légende", + "charts.legend.toggleLegendButtonTitle": "Afficher/Masquer la légende", + "charts.palettes.complimentaryLabel": "Gratuite", + "charts.palettes.coolLabel": "Froide", + "charts.palettes.customLabel": "Personnalisée", + "charts.palettes.defaultPaletteLabel": "Par défaut", + "charts.palettes.grayLabel": "Gris", + "charts.palettes.kibanaPaletteLabel": "Compatibilité", + "charts.palettes.negativeLabel": "Négative", + "charts.palettes.positiveLabel": "Positive", + "charts.palettes.statusLabel": "Statut", + "charts.palettes.temperatureLabel": "Température", + "charts.palettes.warmLabel": "Chaude", + "charts.partialData.bucketTooltipText": "La plage temporelle sélectionnée n'inclut pas ce compartiment en entier. Il se peut qu'elle contienne des données partielles.", + "console.autocomplete.addMethodMetaText": "méthode", + "console.consoleDisplayName": "Console", + "console.consoleMenu.copyAsCurlFailedMessage": "Impossible de copier la requête en tant que cURL", + "console.consoleMenu.copyAsCurlMessage": "Requête copiée en tant que cURL", + "console.devToolsDescription": "Plutôt que l’interface cURL, utilisez une interface JSON pour exploiter vos données dans la console.", + "console.devToolsTitle": "Interagir avec l'API Elasticsearch", + "console.exampleOutputTextarea": "Outils de développement de la console - Exemple d’éditeur", + "console.helpPage.keyboardCommands.autoIndentDescription": "Appliquer un retrait automatique à la requête en cours", + "console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription": "Fermer le menu de saisie semi-automatique", + "console.helpPage.keyboardCommands.collapseAllScopesDescription": "Réduire tout sauf l’élément actif. Ajouter un décalage pour développer.", + "console.helpPage.keyboardCommands.collapseExpandCurrentScopeDescription": "Réduire/développer l’élément actif", + "console.helpPage.keyboardCommands.jumpToPreviousNextRequestDescription": "Aller au début ou à la fin de la requête précédente/suivante", + "console.helpPage.keyboardCommands.openAutoCompleteDescription": "Ouvrir la saisie semi-automatique (même sans saisie)", + "console.helpPage.keyboardCommands.openDocumentationDescription": "Ouvrir la documentation pour la requête en cours", + "console.helpPage.keyboardCommands.selectCurrentlySelectedInAutoCompleteMenuDescription": "Sélectionner le terme en surbrillance ou le premier terme du menu de saisie semi-automatique", + "console.helpPage.keyboardCommands.submitRequestDescription": "Envoyer la requête", + "console.helpPage.keyboardCommands.switchFocusToAutoCompleteMenuDescription": "Permet d’accéder au menu de saisie semi-automatique. Utilisez les flèches pour sélectionner un terme.", + "console.helpPage.keyboardCommandsTitle": "Commandes du clavier", + "console.helpPage.pageTitle": "Aide", + "console.helpPage.requestFormatDescription": "Vous pouvez saisir une ou plusieurs requêtes dans l'éditeur blanc. La console prend en charge les requêtes dans un format compact :", + "console.helpPage.requestFormatTitle": "Format de la requête", + "console.historyPage.applyHistoryButtonLabel": "Appliquer", + "console.historyPage.clearHistoryButtonLabel": "Effacer", + "console.historyPage.closehistoryButtonLabel": "Fermer", + "console.historyPage.itemOfRequestListAriaLabel": "Requête : {historyItem}", + "console.historyPage.noHistoryTextMessage": "Aucun historique disponible", + "console.historyPage.pageTitle": "Historique", + "console.historyPage.requestListAriaLabel": "Historique des requêtes envoyées", + "console.inputTextarea": "Outils de développement de la console", + "console.loadingError.buttonLabel": "Recharger la console", + "console.loadingError.message": "Essayez de recharger pour obtenir les données les plus récentes.", + "console.loadingError.title": "Impossible de charger la console", + "console.notification.error.couldNotSaveRequestTitle": "Impossible d'enregistrer la requête dans l'historique de la console.", + "console.notification.error.historyQuotaReachedMessage": "L'historique des requêtes est arrivé à saturation. Effacez l'historique de la console pour pouvoir enregistrer de nouvelles requêtes.", + "console.notification.error.noRequestSelectedTitle": "Aucune requête sélectionnée. Sélectionnez une requête en positionnant le curseur dessus.", + "console.notification.error.unknownErrorTitle": "Erreur de requête inconnue", + "console.outputTextarea": "Outils de développement de la console - Sortie", + "console.pageHeading": "Console", + "console.requestInProgressBadgeText": "Requête en cours", + "console.requestOptions.autoIndentButtonLabel": "Retrait automatique", + "console.requestOptions.copyAsUrlButtonLabel": "Copier en tant que cURL", + "console.requestOptions.openDocumentationButtonLabel": "Ouvrir la documentation", + "console.requestOptionsButtonAriaLabel": "Options de requête", + "console.requestTimeElapasedBadgeTooltipContent": "Temps écoulé", + "console.sendRequestButtonTooltip": "Cliquer pour envoyer la requête", + "console.settingsPage.autocompleteLabel": "Saisie semi-automatique", + "console.settingsPage.cancelButtonLabel": "Annuler", + "console.settingsPage.fieldsLabelText": "Champs", + "console.settingsPage.fontSizeLabel": "Taille de la police", + "console.settingsPage.indicesAndAliasesLabelText": "Index et alias", + "console.settingsPage.jsonSyntaxLabel": "Syntaxe JSON", + "console.settingsPage.pageTitle": "Paramètres de la console", + "console.settingsPage.refreshButtonLabel": "Actualiser les suggestions de saisie semi-automatique", + "console.settingsPage.refreshingDataDescription": "La console actualise les suggestions de saisie semi-automatique en interrogeant Elasticsearch. L’actualisation automatique peut être un problème en cas de cluster volumineux ou de réseau limité.", + "console.settingsPage.refreshingDataLabel": "Actualisation des suggestions de saisie semi-automatique", + "console.settingsPage.saveButtonLabel": "Enregistrer", + "console.settingsPage.templatesLabelText": "Modèles", + "console.settingsPage.tripleQuotesMessage": "Utiliser des guillemets triples dans le volet de sortie", + "console.settingsPage.wrapLongLinesLabelText": "Renvoyer automatiquement à la ligne", + "console.topNav.helpTabDescription": "Aide", + "console.topNav.helpTabLabel": "Aide", + "console.topNav.historyTabDescription": "Historique", + "console.topNav.historyTabLabel": "Historique", + "console.topNav.settingsTabDescription": "Paramètres", + "console.topNav.settingsTabLabel": "Paramètres", + "console.welcomePage.closeButtonLabel": "Rejeter", + "console.welcomePage.pageTitle": "Bienvenue dans la console", + "console.welcomePage.quickIntroDescription": "L'interface utilisateur de la console est divisée en deux volets : un volet éditeur (à gauche) et un volet de réponse (à droite). L'éditeur permet de saisir des requêtes et de les envoyer à Elasticsearch, tandis que le volet de réponse affiche les résultats.", + "console.welcomePage.quickIntroTitle": "Introduction rapide à l'interface utilisateur", + "console.welcomePage.quickTips.cUrlFormatForRequestsDescription": "Vous pouvez coller des requêtes au format cURL ; elles seront automatiquement traduites dans la syntaxe de la console.", + "console.welcomePage.quickTips.keyboardShortcutsDescription": "N’hésitez pas à jeter un œil aux raccourcis clavier sous le bouton Aide. Vous pourriez y trouver des choses utiles.", + "console.welcomePage.quickTips.resizeEditorDescription": "Vous pouvez redimensionner les volets de l'éditeur et de réponse en faisant glisser le séparateur situé entre les deux.", + "console.welcomePage.quickTips.submitRequestDescription": "Utilisez l’icône de triangle vert pour envoyer vos requêtes à ES.", + "console.welcomePage.quickTips.useWrenchMenuDescription": "Cliquez sur l’icône en forme de clé pour découvrir d'autres éléments utiles.", + "console.welcomePage.quickTipsTitle": "Quelques brèves astuces, pendant que j'ai toute votre attention :", + "console.welcomePage.supportedRequestFormatDescription": "Lors de la saisie d'une requête, la console fera des suggestions que vous pourrez accepter en appuyant sur Entrée/Tab. Ces suggestions sont faites en fonction de la structure de la requête, des index et des types.", + "console.welcomePage.supportedRequestFormatTitle": "La console prend en charge les requêtes dans un format compact, tel que le format cURL :", + "core.application.appContainer.loadingAriaLabel": "Chargement de l'application", + "core.application.appNotFound.pageDescription": "Aucune application détectée pour cette URL. Revenez en arrière ou sélectionnez une application dans le menu.", + "core.application.appNotFound.title": "Application introuvable", + "core.application.appRenderError.defaultTitle": "Erreur d'application", + "core.chrome.browserDeprecationLink": "la matrice de prise en charge sur notre site web", + "core.chrome.browserDeprecationWarning": "La prise en charge d'Internet Explorer sera abandonnée dans les futures versions de ce logiciel. Veuillez consulter le site {link}.", + "core.chrome.legacyBrowserWarning": "Votre navigateur ne satisfait pas aux exigences de sécurité de Kibana.", + "core.euiAccordion.isLoading": "Chargement", + "core.euiBasicTable.selectAllRows": "Sélectionner toutes les lignes", + "core.euiBasicTable.selectThisRow": "Sélectionner cette ligne", + "core.euiBasicTable.tableAutoCaptionWithoutPagination": "Ce tableau contient {itemCount} lignes.", + "core.euiBasicTable.tableAutoCaptionWithPagination": "Ce tableau contient {itemCount} lignes sur {totalItemCount} lignes au total ; page {page} sur {pageCount}.", + "core.euiBasicTable.tableCaptionWithPagination": "{tableCaption} ; page {page} sur {pageCount}.", + "core.euiBasicTable.tablePagination": "Pagination pour le tableau précédent : {tableCaption}", + "core.euiBasicTable.tableSimpleAutoCaptionWithPagination": "Ce tableau contient {itemCount} lignes ; page {page} sur {pageCount}.", + "core.euiBottomBar.customScreenReaderAnnouncement": "Il y a un nouveau repère de région nommé {landmarkHeading} avec des commandes de niveau de page à la fin du document.", + "core.euiBottomBar.screenReaderAnnouncement": "Il y a un nouveau repère de région avec des commandes de niveau de page à la fin du document.", + "core.euiBottomBar.screenReaderHeading": "Commandes de niveau de page", + "core.euiBreadcrumbs.collapsedBadge.ariaLabel": "Voir le fil d’Ariane réduit", + "core.euiBreadcrumbs.nav.ariaLabel": "Fil d’Ariane", + "core.euiCardSelect.select": "Sélectionner", + "core.euiCardSelect.selected": "Sélectionné", + "core.euiCardSelect.unavailable": "Indisponible", + "core.euiCodeBlock.copyButton": "Copier", + "core.euiCodeBlock.fullscreenCollapse": "Réduire", + "core.euiCodeBlock.fullscreenExpand": "Développer", + "core.euiCollapsedItemActions.allActions": "Toutes les actions", + "core.euiColorPicker.alphaLabel": "Valeur (opacité) du canal Alpha", + "core.euiColorPicker.closeLabel": "Appuyez sur la flèche du bas pour ouvrir la fenêtre contextuelle des options de couleur.", + "core.euiColorPicker.colorErrorMessage": "Valeur de couleur non valide", + "core.euiColorPicker.colorLabel": "Valeur de couleur", + "core.euiColorPicker.openLabel": "Appuyez sur Échap pour fermer la fenêtre contextuelle.", + "core.euiColorPicker.popoverLabel": "Boîte de dialogue de sélection de couleur", + "core.euiColorPicker.transparent": "Transparent", + "core.euiColorPickerSwatch.ariaLabel": "Sélection de la couleur {color}", + "core.euiColorStops.screenReaderAnnouncement": "{label} : {readOnly} {disabled} Sélecteur d'arrêt de couleur. Chaque arrêt consiste en un nombre et en une valeur de couleur correspondante. Utilisez les flèches haut et bas pour sélectionner les arrêts. Appuyez sur Entrée pour créer un nouvel arrêt.", + "core.euiColorStopThumb.buttonAriaLabel": "Appuyez sur Entrée pour modifier cet arrêt. Appuyez sur Échap pour revenir au groupe.", + "core.euiColorStopThumb.buttonTitle": "Cliquez pour modifier, faites glisser pour repositionner.", + "core.euiColorStopThumb.removeLabel": "Supprimer cet arrêt", + "core.euiColorStopThumb.screenReaderAnnouncement": "La fenêtre contextuelle qui vient de s’ouvrir contient un formulaire de modification d'arrêt de couleur. Appuyez sur Tab pour parcourir les commandes du formulaire ou sur Échap pour fermer la fenêtre.", + "core.euiColorStopThumb.stopErrorMessage": "Valeur hors limites", + "core.euiColorStopThumb.stopLabel": "Valeur d'arrêt", + "core.euiColumnActions.hideColumn": "Masquer la colonne", + "core.euiColumnActions.moveLeft": "Déplacer vers la gauche", + "core.euiColumnActions.moveRight": "Déplacer vers la droite", + "core.euiColumnActions.sort": "Trier {schemaLabel}", + "core.euiColumnSelector.button": "Colonnes", + "core.euiColumnSelector.buttonActivePlural": "{numberOfHiddenFields} colonnes masquées", + "core.euiColumnSelector.buttonActiveSingular": "{numberOfHiddenFields} colonne masquée", + "core.euiColumnSelector.hideAll": "Tout masquer", + "core.euiColumnSelector.search": "Recherche", + "core.euiColumnSelector.searchcolumns": "Rechercher dans les colonnes", + "core.euiColumnSelector.selectAll": "Afficher tout", + "core.euiColumnSorting.button": "Trier les champs", + "core.euiColumnSorting.clearAll": "Annuler le tri", + "core.euiColumnSorting.emptySorting": "Aucun champ n'est trié actuellement.", + "core.euiColumnSorting.pickFields": "Sélectionner les champs de tri", + "core.euiColumnSorting.sortFieldAriaLabel": "Trier par :", + "core.euiColumnSortingDraggable.defaultSortAsc": "A-Z", + "core.euiColumnSortingDraggable.defaultSortDesc": "Z-A", + "core.euiComboBoxOptionsList.allOptionsSelected": "Vous avez sélectionné toutes les options disponibles.", + "core.euiComboBoxOptionsList.alreadyAdded": "{label} a déjà été ajouté.", + "core.euiComboBoxOptionsList.createCustomOption": "Ajouter {searchValue} en tant qu'option personnalisée", + "core.euiComboBoxOptionsList.delimiterMessage": "Ajouter chaque élément en séparant par {delimiter}", + "core.euiComboBoxOptionsList.loadingOptions": "Options de chargement", + "core.euiComboBoxOptionsList.noAvailableOptions": "Aucune option n’est disponible.", + "core.euiComboBoxOptionsList.noMatchingOptions": "{searchValue} ne correspond à aucune option.", + "core.euiComboBoxPill.removeSelection": "Supprimer {children} de la sélection de ce groupe", + "core.euiCommonlyUsedTimeRanges.legend": "Couramment utilisées", + "core.euiControlBar.customScreenReaderAnnouncement": "Il y a un nouveau repère de région nommé {landmarkHeading} avec des commandes de niveau de page à la fin du document.", + "core.euiControlBar.screenReaderAnnouncement": "Il y a un nouveau repère de région avec des commandes de niveau de page à la fin du document.", + "core.euiControlBar.screenReaderHeading": "Commandes de niveau de page", + "core.euiDataGrid.ariaLabel": "{label} ; page {page} sur {pageCount}.", + "core.euiDataGrid.ariaLabelledBy": "Page {page} sur {pageCount}.", + "core.euiDataGrid.screenReaderNotice": "Cette cellule contient du contenu interactif.", + "core.euiDataGridHeaderCell.headerActions": "Actions d'en-tête", + "core.euiDataGridSchema.booleanSortTextAsc": "Faux-Vrai", + "core.euiDataGridSchema.booleanSortTextDesc": "Vrai-Faux", + "core.euiDataGridSchema.currencySortTextAsc": "Bas-Haut", + "core.euiDataGridSchema.currencySortTextDesc": "Haut-Bas", + "core.euiDataGridSchema.dateSortTextAsc": "Ancien-Nouveau", + "core.euiDataGridSchema.dateSortTextDesc": "Nouveau-Ancien", + "core.euiDataGridSchema.jsonSortTextAsc": "Petit-Grand", + "core.euiDataGridSchema.jsonSortTextDesc": "Grand-Petit", + "core.euiDataGridSchema.numberSortTextAsc": "Bas-Haut", + "core.euiDataGridSchema.numberSortTextDesc": "Haut-Bas", + "core.euiDatePopoverButton.invalidTitle": "Date non valide : {title}", + "core.euiDatePopoverButton.outdatedTitle": "Mise à jour requise : {title}", + "core.euiFieldPassword.maskPassword": "Masquer le mot de passe", + "core.euiFieldPassword.showPassword": "Afficher le mot de passe en texte brut. Remarque : votre mot de passe sera visible à l'écran.", + "core.euiFilePicker.clearSelectedFiles": "Effacer les fichiers sélectionnés", + "core.euiFilePicker.removeSelected": "Supprimer", + "core.euiFlyout.closeAriaLabel": "Fermer cette boîte de dialogue", + "core.euiForm.addressFormErrors": "Veuillez remédier aux erreurs signalées en surbrillance.", + "core.euiFormControlLayoutClearButton.label": "Effacer l'entrée", + "core.euiHeaderLinks.appNavigation": "Menu de l'application", + "core.euiHeaderLinks.openNavigationMenu": "Ouvrir le menu", + "core.euiHue.label": "Sélectionner la valeur \"hue\" du mode de couleur HSV", + "core.euiImage.closeImage": "Fermer l'image {alt} en plein écran", + "core.euiImage.openImage": "Ouvrir l'image {alt} en plein écran", + "core.euiLink.external.ariaLabel": "Lien externe", + "core.euiLink.newTarget.screenReaderOnlyText": "(s’ouvre dans un nouvel onglet ou une nouvelle fenêtre)", + "core.euiMarkdownEditorFooter.closeButton": "Fermer", + "core.euiMarkdownEditorFooter.errorsTitle": "Erreurs", + "core.euiMarkdownEditorFooter.openUploadModal": "Activer le mode de chargement de fichiers", + "core.euiMarkdownEditorFooter.showMarkdownHelp": "Afficher l'aide de Markdown", + "core.euiMarkdownEditorFooter.showSyntaxErrors": "Afficher les erreurs", + "core.euiMarkdownEditorFooter.supportedFileTypes": "Fichiers pris en charge : {supportedFileTypes}", + "core.euiMarkdownEditorFooter.syntaxTitle": "Aide pour la syntaxe", + "core.euiMarkdownEditorFooter.unsupportedFileType": "Type de fichiers non pris en charge", + "core.euiMarkdownEditorFooter.uploadingFiles": "Cliquer pour charger des fichiers", + "core.euiMarkdownEditorToolbar.editor": "Éditeur", + "core.euiMarkdownEditorToolbar.previewMarkdown": "Aperçu", + "core.euiModal.closeModal": "Ferme cette fenêtre modale.", + "core.euiNotificationEventMessages.accordionAriaLabelButtonText": "+ {messagesLength} messages pour {eventName}", + "core.euiNotificationEventMessages.accordionButtonText": "+ {messagesLength} de plus", + "core.euiNotificationEventMessages.accordionHideText": "masquer", + "core.euiNotificationEventMeta.contextMenuButton": "Menu pour {eventName}", + "core.euiNotificationEventReadButton.markAsRead": "Marquer comme lu", + "core.euiNotificationEventReadButton.markAsReadAria": "Marquer {eventName} comme lu", + "core.euiNotificationEventReadButton.markAsUnread": "Marquer comme non lu", + "core.euiNotificationEventReadButton.markAsUnreadAria": "Marquer {eventName} comme non lu", + "core.euiNotificationEventReadIcon.read": "Lu", + "core.euiNotificationEventReadIcon.readAria": "{eventName} lu", + "core.euiNotificationEventReadIcon.unread": "Non lu", + "core.euiNotificationEventReadIcon.unreadAria": "{eventName} non lu", + "core.euiPagination.firstRangeAriaLabel": "Ignorer les pages 2 à {lastPage}", + "core.euiPagination.lastRangeAriaLabel": "Ignorer les pages {firstPage} à {lastPage}", + "core.euiPagination.pageOfTotalCompressed": "{page} sur {total}", + "core.euiPaginationButton.longPageString": "Page {page} sur {totalPages}", + "core.euiPaginationButton.shortPageString": "Page {page}", + "core.euiPinnableListGroup.pinExtraActionLabel": "Épingler l'élément", + "core.euiPinnableListGroup.pinnedExtraActionLabel": "Désépingler l'élément", + "core.euiPopover.screenReaderAnnouncement": "Il s’agit d’une boîte de dialogue. Appuyez sur Échap pour quitter.", + "core.euiProgress.valueText": "{value} %", + "core.euiQuickSelect.applyButton": "Appliquer", + "core.euiQuickSelect.fullDescription": "Actuellement défini sur {timeTense} {timeValue} {timeUnit}.", + "core.euiQuickSelect.legendText": "Sélection rapide d’une plage temporelle", + "core.euiQuickSelect.nextLabel": "Fenêtre temporelle suivante", + "core.euiQuickSelect.previousLabel": "Fenêtre temporelle précédente", + "core.euiQuickSelect.quickSelectTitle": "Sélection rapide", + "core.euiQuickSelect.tenseLabel": "Durée", + "core.euiQuickSelect.unitLabel": "Unité de temps", + "core.euiQuickSelect.valueLabel": "Valeur de temps", + "core.euiRecentlyUsed.legend": "Plages de dates récemment utilisées", + "core.euiRefreshInterval.legend": "Actualiser toutes les", + "core.euiRelativeTab.fullDescription": "L'unité peut être modifiée. Elle est actuellement définie sur {unit}.", + "core.euiRelativeTab.numberInputError": "Doit être >= 0.", + "core.euiRelativeTab.numberInputLabel": "Nombre d'intervalles", + "core.euiRelativeTab.relativeDate": "Date de {position}", + "core.euiRelativeTab.roundingLabel": "Arrondir à {unit}", + "core.euiRelativeTab.unitInputLabel": "Intervalle relatif", + "core.euiResizableButton.horizontalResizerAriaLabel": "Utilisez les flèches gauche et droite pour ajuster la taille des panneaux.", + "core.euiResizableButton.verticalResizerAriaLabel": "Utilisez les flèches vers le haut et vers le bas pour ajuster la taille des panneaux.", + "core.euiResizablePanel.toggleButtonAriaLabel": "Appuyez pour afficher/masquer ce panneau.", + "core.euiSaturation.ariaLabel": "Curseur à 2 axes de valeur et de saturation du mode de couleur HSV", + "core.euiSaturation.screenReaderInstructions": "Utilisez les touches fléchées pour parcourir le dégradé de couleurs. Les coordonnées seront utilisées pour calculer les chiffres de \"valeur\" et de \"saturation\" du mode de couleur HSV, dans une plage de 0 à 1. Les flèches gauche et droite permettent de modifier la saturation. Les flèches vers le haut et vers le bas permettent de modifier la valeur.", + "core.euiSelectable.loadingOptions": "Options de chargement", + "core.euiSelectable.noAvailableOptions": "Aucune option disponible", + "core.euiSelectable.noMatchingOptions": "{searchValue} ne correspond à aucune option.", + "core.euiSelectable.placeholderName": "Options de filtre", + "core.euiSelectableListItem.excludedOption": "Option exclue.", + "core.euiSelectableListItem.excludedOptionInstructions": "Pour désélectionner cette option, appuyez sur Entrée.", + "core.euiSelectableListItem.includedOption": "Option incluse.", + "core.euiSelectableListItem.includedOptionInstructions": "Pour exclure cette option, appuyez sur Entrée.", + "core.euiSelectableTemplateSitewide.loadingResults": "Chargement des résultats", + "core.euiSelectableTemplateSitewide.noResults": "Aucun résultat disponible", + "core.euiSelectableTemplateSitewide.onFocusBadgeGoTo": "Atteindre", + "core.euiSelectableTemplateSitewide.searchPlaceholder": "Rechercher tout...", + "core.euiStat.loadingText": "Statistiques en cours de chargement", + "core.euiStepStrings.complete": "L'étape {number} : {title} est terminée.", + "core.euiStepStrings.current": "L’étape {number} : {title} est en cours.", + "core.euiStepStrings.disabled": "L'étape {number} : {title} est désactivée.", + "core.euiStepStrings.errors": "L'étape {number} : {title} contient des erreurs.", + "core.euiStepStrings.incomplete": "L'étape {number} : {title} est incomplète.", + "core.euiStepStrings.loading": "L'étape {number} : {title} est en cours de chargement.", + "core.euiStepStrings.simpleComplete": "L'étape {number} est terminée.", + "core.euiStepStrings.simpleCurrent": "L’étape {number} est en cours.", + "core.euiStepStrings.simpleDisabled": "L'étape {number} est désactivée.", + "core.euiStepStrings.simpleErrors": "L'étape {number} contient des erreurs.", + "core.euiStepStrings.simpleIncomplete": "L'étape {number} est incomplète.", + "core.euiStepStrings.simpleLoading": "L'étape {number} est en cours de chargement.", + "core.euiStepStrings.simpleStep": "Étape {number}", + "core.euiStepStrings.simpleWarning": "L'étape {number} contient des avertissements.", + "core.euiStepStrings.step": "Étape {number} : {title}", + "core.euiStepStrings.warning": "L'étape {number} : {title} contient des avertissements.", + "core.euiSuperSelectControl.selectAnOption": "Sélectionner une option : l’option {selectedValue} est sélectionnée.", + "core.euiSuperUpdateButton.cannotUpdateTooltip": "Mise à jour impossible", + "core.euiSuperUpdateButton.clickToApplyTooltip": "Cliquer pour appliquer", + "core.euiSuperUpdateButton.refreshButtonLabel": "Actualiser", + "core.euiSuperUpdateButton.updateButtonLabel": "Mettre à jour", + "core.euiSuperUpdateButton.updatingButtonLabel": "Mise à jour", + "core.euiTableHeaderCell.titleTextWithDesc": "{innerText} ; {description}", + "core.euiTablePagination.rowsPerPage": "Lignes par page", + "core.euiTablePagination.rowsPerPageOption": "{rowsPerPage} lignes", + "core.euiTableSortMobile.sorting": "Tri", + "core.euiToast.dismissToast": "Rejeter le toast", + "core.euiToast.newNotification": "Une nouvelle notification apparaît.", + "core.euiToast.notification": "Notification", + "core.euiTourStep.closeTour": "Fermer la visite", + "core.euiTourStep.endTour": "Terminer la visite", + "core.euiTourStep.skipTour": "Ignorer la visite", + "core.euiTourStepIndicator.ariaLabel": "Étape {number} {status}", + "core.euiTourStepIndicator.isActive": "active", + "core.euiTourStepIndicator.isComplete": "terminée", + "core.euiTourStepIndicator.isIncomplete": "incomplète", + "core.euiTreeView.ariaLabel": "{nodeLabel} enfant de {ariaLabel}", + "core.euiTreeView.listNavigationInstructions": "Utilisez les touches fléchées pour parcourir rapidement cette liste.", + "core.fatalErrors.clearYourSessionButtonLabel": "Effacer votre session", + "core.fatalErrors.goBackButtonLabel": "Retour", + "core.fatalErrors.somethingWentWrongTitle": "Un problème est survenu.", + "core.fatalErrors.tryRefreshingPageDescription": "Essayez d'actualiser la page. Si cela ne fonctionne pas, retournez à la page précédente ou effacez vos données de session.", + "core.notifications.errorToast.closeModal": "Fermer", + "core.notifications.globalToast.ariaLabel": "Liste de messages de notification", + "core.notifications.unableUpdateUISettingNotificationMessageTitle": "Impossible de mettre à jour le paramètre de l'interface utilisateur", + "core.status.greenTitle": "Vert", + "core.status.redTitle": "Rouge", + "core.status.yellowTitle": "Jaune", + "core.statusPage.loadStatus.serverIsDownErrorMessage": "Échec de requête du statut du serveur. Votre serveur est peut-être indisponible ?", + "core.statusPage.loadStatus.serverStatusCodeErrorMessage": "Échec de requête du statut du serveur avec le code de statut {responseStatus}.", + "core.statusPage.metricsTiles.columns.heapTotalHeader": "Tas total", + "core.statusPage.metricsTiles.columns.heapUsedHeader": "Tas utilisé", + "core.statusPage.metricsTiles.columns.loadHeader": "Charger", + "core.statusPage.metricsTiles.columns.requestsPerSecHeader": "Requêtes par seconde", + "core.statusPage.metricsTiles.columns.resTimeAvgHeader": "Temps de réponse moyen", + "core.statusPage.metricsTiles.columns.resTimeMaxHeader": "Temps de réponse max.", + "core.statusPage.serverStatus.statusTitle": "Statut Kibana : {kibanaStatus}", + "core.statusPage.statusApp.loadingErrorText": "Une erreur s'est produite lors du chargement du statut.", + "core.statusPage.statusApp.statusActions.buildText": "CRÉER {buildNum}", + "core.statusPage.statusApp.statusActions.commitText": "VALIDER {buildSha}", + "core.statusPage.statusApp.statusTitle": "Statut du plug-in", + "core.statusPage.statusTable.columns.idHeader": "ID", + "core.statusPage.statusTable.columns.statusHeader": "Statut", + "core.toasts.errorToast.seeFullError": "Voir l'erreur en intégralité", + "core.ui_settings.params.darkModeText": "Activez le mode sombre pour l'interface utilisateur Kibana. Vous devez actualiser la page pour que ce paramètre s’applique.", + "core.ui_settings.params.darkModeTitle": "Mode sombre", + "core.ui_settings.params.dateFormat.dayOfWeekText": "Quel est le premier jour de la semaine ?", + "core.ui_settings.params.dateFormat.dayOfWeekTitle": "Jour de la semaine", + "core.ui_settings.params.dateFormat.optionsLinkText": "format", + "core.ui_settings.params.dateFormat.scaled.intervalsLinkText": "Intervalles ISO8601", + "core.ui_settings.params.dateFormat.scaledText": "Les valeurs qui définissent le format utilisé lorsque les données temporelles sont rendues dans l'ordre, et lorsque les horodatages formatés doivent s'adapter à l'intervalle entre les mesures. Les clés sont {intervalsLink}.", + "core.ui_settings.params.dateFormat.scaledTitle": "Format de date scalé", + "core.ui_settings.params.dateFormat.timezone.invalidValidationMessage": "Fuseau horaire non valide : {timezone}", + "core.ui_settings.params.dateFormat.timezoneText": "Fuseau horaire à utiliser. L’option {defaultOption} utilise le fuseau horaire détecté par le navigateur.", + "core.ui_settings.params.dateFormat.timezoneTitle": "Fuseau horaire pour le format de date", + "core.ui_settings.params.dateFormatText": "{formatLink} utilisé pour les dates formatées", + "core.ui_settings.params.dateFormatTitle": "Format de date", + "core.ui_settings.params.dateNanosFormatText": "Utilisé pour le type de données {dateNanosLink} d'Elasticsearch", + "core.ui_settings.params.dateNanosFormatTitle": "Date au format nanosecondes", + "core.ui_settings.params.dateNanosLinkTitle": "date_nanos", + "core.ui_settings.params.dayOfWeekText.invalidValidationMessage": "Jour de la semaine non valide : {dayOfWeek}", + "core.ui_settings.params.defaultRoute.defaultRouteIsRelativeValidationMessage": "Doit être une URL relative.", + "core.ui_settings.params.defaultRoute.defaultRouteText": "Ce paramètre spécifie le chemin par défaut lors de l'ouverture de Kibana. Vous pouvez utiliser ce paramètre pour modifier la page de destination à l'ouverture de Kibana. Le chemin doit être une URL relative.", + "core.ui_settings.params.defaultRoute.defaultRouteTitle": "Chemin par défaut", + "core.ui_settings.params.disableAnimationsText": "Désactivez toutes les animations non nécessaires dans l'interface utilisateur de Kibana. Actualisez la page pour appliquer les modifications.", + "core.ui_settings.params.disableAnimationsTitle": "Désactiver les animations", + "core.ui_settings.params.notifications.banner.markdownLinkText": "Markdown pris en charge", + "core.ui_settings.params.notifications.bannerLifetimeText": "La durée en millisecondes durant laquelle une notification de bannière s'affiche à l'écran. ", + "core.ui_settings.params.notifications.bannerLifetimeTitle": "Durée des notifications de bannière", + "core.ui_settings.params.notifications.bannerText": "Une bannière personnalisée à des fins de notification temporaire de l’ensemble des utilisateurs. {markdownLink}.", + "core.ui_settings.params.notifications.bannerTitle": "Notification de bannière personnalisée", + "core.ui_settings.params.notifications.errorLifetimeText": "La durée en millisecondes durant laquelle une notification d'erreur s'affiche à l'écran. ", + "core.ui_settings.params.notifications.errorLifetimeTitle": "Durée des notifications d'erreur", + "core.ui_settings.params.notifications.infoLifetimeText": "La durée en millisecondes durant laquelle une notification d'information s'affiche à l'écran. ", + "core.ui_settings.params.notifications.infoLifetimeTitle": "Durée des notifications d'information", + "core.ui_settings.params.notifications.warningLifetimeText": "La durée en millisecondes durant laquelle une notification d'avertissement s'affiche à l'écran. ", + "core.ui_settings.params.notifications.warningLifetimeTitle": "Durée des notifications d'avertissement", + "core.ui_settings.params.storeUrlText": "L'URL peut parfois devenir trop longue pour être gérée par certains navigateurs. Pour pallier ce problème, nous testons actuellement le stockage de certaines parties de l'URL dans le stockage de session. N’hésitez pas à nous faire part de vos commentaires.", + "core.ui_settings.params.storeUrlTitle": "Stocker les URL dans le stockage de session", + "core.ui_settings.params.themeVersionTitle": "Version du thème", + "core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel": "Accueil d'Elastic", + "core.ui.chrome.headerGlobalNav.helpMenuAskElasticTitle": "Questions Elastic", + "core.ui.chrome.headerGlobalNav.helpMenuButtonAriaLabel": "Menu d'aide", + "core.ui.chrome.headerGlobalNav.helpMenuDocumentation": "Documentation", + "core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackOnApp": "Donner un retour sur {appName}", + "core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackTitle": "Donner un retour", + "core.ui.chrome.headerGlobalNav.helpMenuKibanaDocumentationTitle": "Documentation Kibana", + "core.ui.chrome.headerGlobalNav.helpMenuOpenGitHubIssueTitle": "Ouvrir un ticket dans GitHub", + "core.ui.chrome.headerGlobalNav.helpMenuTitle": "Aide", + "core.ui.chrome.headerGlobalNav.helpMenuVersion": "v {version}", + "core.ui.chrome.headerGlobalNav.logoAriaLabel": "Logo Elastic", + "core.ui.enterpriseSearchNavList.label": "Enterprise Search", + "core.ui.errorUrlOverflow.bigUrlWarningNotificationMessage": "Activez l'option {storeInSessionStorageParam} dans les {advancedSettingsLink} ou simplifiez les visuels à l'écran.", + "core.ui.errorUrlOverflow.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "paramètres avancés", + "core.ui.errorUrlOverflow.bigUrlWarningNotificationTitle": "L'URL est longue et Kibana pourrait cesser de fonctionner.", + "core.ui.errorUrlOverflow.errorTitle": "L'URL pour cet objet est trop longue, et nous ne pouvons pas l'afficher.", + "core.ui.errorUrlOverflow.optionsToFixError.doNotUseIEText": "Veuillez utiliser un navigateur moderne. Tous les autres navigateurs pris en charge connus n'ont pas cette limitation.", + "core.ui.errorUrlOverflow.optionsToFixError.enableOptionText": "Activez l'option {storeInSessionStorageConfig} sous {kibanaSettingsLink}.", + "core.ui.errorUrlOverflow.optionsToFixError.enableOptionText.advancedSettingsLinkText": "Paramètres avancés", + "core.ui.errorUrlOverflow.optionsToFixError.removeStuffFromDashboardText": "Simplifiez l'objet en cours de modification en supprimant du contenu ou des filtres.", + "core.ui.errorUrlOverflow.optionsToFixErrorDescription": "À essayer :", + "core.ui.kibanaNavList.label": "Analytique", + "core.ui.legacyBrowserMessage": "Cette installation Elastic présente des exigences de sécurité strictes auxquelles votre navigateur ne satisfait pas.", + "core.ui.legacyBrowserTitle": "Merci de mettre votre navigateur à niveau.", + "core.ui.loadingIndicatorAriaLabel": "Chargement du contenu", + "core.ui.managementNavList.label": "Gestion", + "core.ui.observabilityNavList.label": "Observabilité", + "core.ui.overlays.banner.attentionTitle": "Attention", + "core.ui.overlays.banner.closeButtonLabel": "Fermer", + "core.ui.primaryNav.pinnedLinksAriaLabel": "Liens épinglés", + "core.ui.primaryNav.screenReaderLabel": "Principale", + "core.ui.primaryNav.toggleNavAriaLabel": "Activer/Désactiver la navigation principale", + "core.ui.primaryNavSection.screenReaderLabel": "Liens de navigation principale, {category}", + "core.ui.publicBaseUrlWarning.muteWarningButtonLabel": "Avertissement de mise sur Muet", + "core.ui.recentLinks.linkItem.screenReaderLabel": "{recentlyAccessedItemLinklabel}, type : {pageType}", + "core.ui.recentlyViewed": "Récemment consulté", + "core.ui.recentlyViewedAriaLabel": "Liens récemment consultés", + "core.ui.securityNavList.label": "Security", + "core.ui.welcomeErrorMessage": "Elastic ne s'est pas chargé correctement. Vérifiez la sortie du serveur pour plus d'informations.", + "core.ui.welcomeMessage": "Chargement d'Elastic", + "dashboard.actions.DownloadCreateDrilldownAction.displayName": "Télécharger au format CSV", + "dashboard.actions.downloadOptionsUnsavedFilename": "sans titre", + "dashboard.actions.toggleExpandPanelMenuItem.expandedDisplayName": "Minimiser", + "dashboard.actions.toggleExpandPanelMenuItem.notExpandedDisplayName": "Maximiser le panneau", + "dashboard.addPanel.noMatchingObjectsMessage": "Aucun objet correspondant trouvé.", + "dashboard.addPanel.savedObjectAddedToContainerSuccessMessageTitle": "{savedObjectName} a été ajouté.", + "dashboard.appLeaveConfirmModal.cancelButtonLabel": "Annuler", + "dashboard.appLeaveConfirmModal.unsavedChangesSubtitle": "Quitter le tableau de bord sans enregistrer ?", + "dashboard.appLeaveConfirmModal.unsavedChangesTitle": "Modifications non enregistrées", + "dashboard.badge.readOnly.text": "Lecture seule", + "dashboard.badge.readOnly.tooltip": "Impossible d'enregistrer les tableaux de bord", + "dashboard.changeViewModeConfirmModal.cancelButtonLabel": "Poursuivre les modifications", + "dashboard.changeViewModeConfirmModal.confirmButtonLabel": "Ignorer les modifications", + "dashboard.changeViewModeConfirmModal.description": "Vous pouvez conserver ou ignorer vos modifications lors du retour en mode Affichage. Les modifications ignorées ne peuvent toutefois pas être récupérées.", + "dashboard.changeViewModeConfirmModal.keepUnsavedChangesButtonLabel": "Conserver les modifications", + "dashboard.changeViewModeConfirmModal.leaveEditModeTitle": "Vous avez des modifications non enregistrées.", + "dashboard.cloneModal.cloneDashboardTitleAriaLabel": "Titre du tableau de bord cloné", + "dashboard.createConfirmModal.cancelButtonLabel": "Annuler", + "dashboard.createConfirmModal.confirmButtonLabel": "Redémarrer", + "dashboard.createConfirmModal.continueButtonLabel": "Poursuivre les modifications", + "dashboard.createConfirmModal.unsavedChangesSubtitle": "Vous pouvez poursuivre les modifications ou utiliser un tableau de bord vierge.", + "dashboard.createConfirmModal.unsavedChangesTitle": "Nouveau tableau de bord déjà en cours", + "dashboard.dashboardAppBreadcrumbsTitle": "Tableau de bord", + "dashboard.dashboardGrid.toast.unableToLoadDashboardDangerMessage": "Impossible de charger le tableau de bord.", + "dashboard.dashboardPageTitle": "Tableaux de bord", + "dashboard.dashboardWasNotSavedDangerMessage": "Le tableau de bord \"{dashTitle}\" n'a pas été enregistré. Erreur : {errorMessage}", + "dashboard.dashboardWasSavedSuccessMessage": "Le tableau de bord \"{dashTitle}\" a été enregistré.", + "dashboard.discardChangesConfirmModal.cancelButtonLabel": "Annuler", + "dashboard.discardChangesConfirmModal.confirmButtonLabel": "Ignorer les modifications", + "dashboard.discardChangesConfirmModal.discardChangesDescription": "Une fois les modifications ignorées, vous ne pourrez pas les récupérer.", + "dashboard.discardChangesConfirmModal.discardChangesTitle": "Ignorer les modifications apportées au tableau de bord ?", + "dashboard.editorMenu.aggBasedGroupTitle": "Basé sur une agrégation", + "dashboard.embedUrlParamExtension.filterBar": "Barre de filtre", + "dashboard.embedUrlParamExtension.include": "Inclure", + "dashboard.embedUrlParamExtension.query": "Requête", + "dashboard.embedUrlParamExtension.timeFilter": "Filtre temporel", + "dashboard.embedUrlParamExtension.topMenu": "Menu supérieur", + "dashboard.emptyDashboardAdditionalPrivilege": "Des privilèges supplémentaires sont requis pour pouvoir modifier ce tableau de bord.", + "dashboard.emptyDashboardTitle": "Ce tableau de bord est vide.", + "dashboard.emptyWidget.addPanelDescription": "Créez du contenu qui raconte une histoire sur vos données.", + "dashboard.emptyWidget.addPanelTitle": "Ajoutez votre première visualisation.", + "dashboard.factory.displayName": "Tableau de bord", + "dashboard.featureCatalogue.dashboardDescription": "Affichez et partagez une collection de visualisations et de recherches enregistrées.", + "dashboard.featureCatalogue.dashboardSubtitle": "Analysez des données à l’aide de tableaux de bord.", + "dashboard.featureCatalogue.dashboardTitle": "Tableau de bord", + "dashboard.fillDashboardTitle": "Ce tableau de bord est vide. Remplissons-le.", + "dashboard.helpMenu.appName": "Tableaux de bord", + "dashboard.howToStartWorkingOnNewDashboardDescription": "Cliquez sur Modifier dans la barre de menu ci-dessus pour commencer à ajouter des panneaux.", + "dashboard.howToStartWorkingOnNewDashboardEditLinkAriaLabel": "Modifier le tableau de bord", + "dashboard.labs.enableLabsDescription": "Cet indicateur détermine si l'observateur a accès au bouton Ateliers, un moyen rapide d'activer et de désactiver les fonctionnalités expérimentales dans le tableau de bord.", + "dashboard.labs.enableUI": "Activer le bouton Ateliers dans le tableau de bord", + "dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription": "Vous pouvez combiner les vues de données de n'importe quelle application Kibana dans un seul tableau de bord afin de tout regrouper.", + "dashboard.listing.createNewDashboard.createButtonLabel": "Créer un nouveau tableau de bord", + "dashboard.listing.createNewDashboard.newToKibanaDescription": "Vous êtes nouveau sur Kibana ? {sampleDataInstallLink} pour découvrir l'application.", + "dashboard.listing.createNewDashboard.sampleDataInstallLinkText": "Installez un exemple de données", + "dashboard.listing.createNewDashboard.title": "Créer votre premier tableau de bord", + "dashboard.listing.readonlyNoItemsBody": "Aucun tableau de bord n'est disponible. Pour modifier vos autorisations afin d’afficher les tableaux de bord dans cet espace, contactez votre administrateur.", + "dashboard.listing.readonlyNoItemsTitle": "Aucun tableau de bord à afficher", + "dashboard.listing.table.descriptionColumnName": "Description", + "dashboard.listing.table.entityName": "tableau de bord", + "dashboard.listing.table.entityNamePlural": "tableaux de bord", + "dashboard.listing.table.titleColumnName": "Titre", + "dashboard.listing.unsaved.discardAria": "Ignorer les modifications apportées à {title}", + "dashboard.listing.unsaved.discardTitle": "Ignorer les modifications", + "dashboard.listing.unsaved.editAria": "Poursuivre les modifications apportées à {title}", + "dashboard.listing.unsaved.editTitle": "Poursuivre les modifications", + "dashboard.listing.unsaved.loading": "Chargement", + "dashboard.listing.unsaved.unsavedChangesTitle": "Vous avez des modifications non enregistrées dans le {dash} suivant.", + "dashboard.migratedChanges": "Certains des panneaux ont été mis à jour vers la version la plus récente.", + "dashboard.noMatchRoute.bannerText": "L'application de tableau de bord ne reconnaît pas ce chemin : {route}.", + "dashboard.noMatchRoute.bannerTitleText": "Page introuvable", + "dashboard.panel.AddToLibrary": "Enregistrer dans la bibliothèque", + "dashboard.panel.addToLibrary.successMessage": "Le panneau {panelTitle} a été ajouté à la bibliothèque Visualize.", + "dashboard.panel.clonedToast": "Panneau cloné", + "dashboard.panel.clonePanel": "Cloner le panneau", + "dashboard.panel.copyToDashboard.cancel": "Annuler", + "dashboard.panel.copyToDashboard.description": "Sélectionnez l'emplacement où copier le panneau. Vous avez été redirigé vers le tableau de bord de destination.", + "dashboard.panel.copyToDashboard.existingDashboardOptionLabel": "Tableau de bord existant", + "dashboard.panel.copyToDashboard.goToDashboard": "Copier et accéder au tableau de bord", + "dashboard.panel.copyToDashboard.newDashboardOptionLabel": "Nouveau tableau de bord", + "dashboard.panel.copyToDashboard.title": "Copier dans le tableau de bord", + "dashboard.panel.invalidData": "Données non valides dans l'url", + "dashboard.panel.LibraryNotification": "Notification de la bibliothèque Visualize", + "dashboard.panel.libraryNotification.ariaLabel": "Afficher les informations de la bibliothèque et dissocier ce panneau", + "dashboard.panel.libraryNotification.toolTip": "La modification de ce panneau pourrait affecter d’autres tableaux de bord. Pour modifier ce panneau uniquement, dissociez-le de la bibliothèque.", + "dashboard.panel.removePanel.replacePanel": "Remplacer le panneau", + "dashboard.panel.title.clonedTag": "copier", + "dashboard.panel.unableToMigratePanelDataForSixOneZeroErrorMessage": "Impossible de migrer les données du panneau pour une rétro-compatibilité \"6.1.0\". Le panneau ne contient pas les champs de colonne et/ou de ligne attendus.", + "dashboard.panel.unableToMigratePanelDataForSixThreeZeroErrorMessage": "Impossible de migrer les données du panneau pour une rétro-compatibilité \"6.3.0\". Le panneau ne contient pas le champ attendu : {key}.", + "dashboard.panel.unlinkFromLibrary": "Dissocier de la bibliothèque", + "dashboard.panel.unlinkFromLibrary.successMessage": "Le panneau {panelTitle} n'est plus connecté à la bibliothèque Visualize.", + "dashboard.panelStorageError.clearError": "Une erreur s'est produite lors de la suppression des modifications non enregistrées : {message}.", + "dashboard.panelStorageError.getError": "Une erreur s'est produite lors de la récupération des modifications non enregistrées : {message}.", + "dashboard.panelStorageError.setError": "Une erreur s'est produite lors de la définition des modifications non enregistrées : {message}.", + "dashboard.placeholder.factory.displayName": "paramètre fictif", + "dashboard.savedDashboard.newDashboardTitle": "Nouveau tableau de bord", + "dashboard.solutionToolbar.addPanelButtonLabel": "Créer une visualisation", + "dashboard.solutionToolbar.editorMenuButtonLabel": "Tous les types", + "dashboard.strings.dashboardEditTitle": "Modification de {title}", + "dashboard.topNav.cloneModal.cancelButtonLabel": "Annuler", + "dashboard.topNav.cloneModal.cloneDashboardModalHeaderTitle": "Cloner le tableau de bord", + "dashboard.topNav.cloneModal.confirmButtonLabel": "Confirmer le clonage", + "dashboard.topNav.cloneModal.confirmCloneDescription": "Confirmer le clonage", + "dashboard.topNav.cloneModal.dashboardExistsDescription": "Cliquez sur {confirmClone} pour cloner le tableau de bord avec le titre dupliqué.", + "dashboard.topNav.cloneModal.dashboardExistsTitle": "Un tableau de bord nommé {newDashboardName} existe déjà.", + "dashboard.topNav.cloneModal.enterNewNameForDashboardDescription": "Veuillez saisir un autre nom pour votre tableau de bord.", + "dashboard.topNav.labsButtonAriaLabel": "ateliers", + "dashboard.topNav.labsConfigDescription": "Ateliers", + "dashboard.topNav.options.hideAllPanelTitlesSwitchLabel": "Afficher les titres de panneau", + "dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel": "Synchroniser les palettes de couleur de tous les panneaux", + "dashboard.topNav.options.useMarginsBetweenPanelsSwitchLabel": "Utiliser des marges entre les panneaux", + "dashboard.topNav.saveModal.descriptionFormRowLabel": "Description", + "dashboard.topNav.saveModal.objectType": "tableau de bord", + "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowHelpText": "Le filtre temporel est défini sur l’option sélectionnée chaque fois que ce tableau de bord est chargé.", + "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowLabel": "Enregistrer la plage temporelle avec le tableau de bord", + "dashboard.topNav.showCloneModal.dashboardCopyTitle": "Copie de {title}", + "dashboard.topNave.cancelButtonAriaLabel": "Basculer en mode Affichage", + "dashboard.topNave.cloneButtonAriaLabel": "cloner", + "dashboard.topNave.cloneConfigDescription": "Créer une copie du tableau de bord", + "dashboard.topNave.editButtonAriaLabel": "modifier", + "dashboard.topNave.editConfigDescription": "Basculer en mode Édition", + "dashboard.topNave.fullScreenButtonAriaLabel": "plein écran", + "dashboard.topNave.fullScreenConfigDescription": "Mode Plein écran", + "dashboard.topNave.optionsButtonAriaLabel": "options", + "dashboard.topNave.optionsConfigDescription": "Options", + "dashboard.topNave.saveAsButtonAriaLabel": "enregistrer sous", + "dashboard.topNave.saveAsConfigDescription": "Enregistrer en tant que nouveau tableau de bord", + "dashboard.topNave.saveButtonAriaLabel": "enregistrer", + "dashboard.topNave.saveConfigDescription": "Enregistrer le tableau de bord sans invite de confirmation", + "dashboard.topNave.shareButtonAriaLabel": "partager", + "dashboard.topNave.shareConfigDescription": "Partager le tableau de bord", + "dashboard.topNave.viewConfigDescription": "Basculer en mode Affichage uniquement", + "dashboard.unsavedChangesBadge": "Modifications non enregistrées", + "dashboard.urlWasRemovedInSixZeroWarningMessage": "L'url \"dashboard/create\" a été supprimée dans la version 6.0. Veuillez mettre vos signets à jour.", + "data.advancedSettings.autocompleteIgnoreTimerange": "Utiliser la plage temporelle", + "data.advancedSettings.autocompleteIgnoreTimerangeText": "Désactivez cette propriété pour obtenir des suggestions de saisie semi-automatique depuis l’intégralité de l’ensemble de données plutôt que depuis la plage temporelle définie. {learnMoreLink}", + "data.advancedSettings.autocompleteValueSuggestionMethod": "Méthode de suggestion de saisie semi-automatique", + "data.advancedSettings.autocompleteValueSuggestionMethodLearnMoreLink": "En savoir plus.", + "data.advancedSettings.autocompleteValueSuggestionMethodLink": "En savoir plus.", + "data.advancedSettings.autocompleteValueSuggestionMethodText": "La méthode utilisée pour générer des suggestions de valeur pour la saisie semi-automatique KQL. Sélectionnez terms_enum pour utiliser l'API d'énumération de termes d'Elasticsearch afin d’améliorer les performances de suggestion de saisie semi-automatique. Sélectionnez terms_agg pour utiliser l'agrégation de termes d'Elasticsearch. {learnMoreLink}", + "data.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText": "Préférence de requête", + "data.advancedSettings.courier.customRequestPreferenceText": "{requestPreferenceLink} utilisé lorsque {setRequestReferenceSetting} est défini sur {customSettingValue}.", + "data.advancedSettings.courier.customRequestPreferenceTitle": "Préférence de requête personnalisée", + "data.advancedSettings.courier.ignoreFilterText": "Cette configuration améliore la prise en charge des tableaux de bord contenant des visualisations accédant à des index différents. Lorsque ce paramètre est désactivé, tous les filtres sont appliqués à toutes les visualisations. En cas d'activation, le ou les filtres sont ignorés pour une visualisation lorsque l'index de celle-ci ne contient pas le champ de filtrage.", + "data.advancedSettings.courier.ignoreFilterTitle": "Ignorer le ou les filtres", + "data.advancedSettings.courier.maxRequestsText": "Contrôle le paramètre {maxRequestsLink} utilisé pour les requêtes _msearch envoyées par Kibana. Définir ce paramètre sur 0 permet d’utiliser la valeur Elasticsearch par défaut.", + "data.advancedSettings.courier.maxRequestsTitle": "Requêtes de partitions simultanées max.", + "data.advancedSettings.courier.requestPreferenceCustom": "Personnalisée", + "data.advancedSettings.courier.requestPreferenceNone": "Aucune", + "data.advancedSettings.courier.requestPreferenceSessionId": "ID session", + "data.advancedSettings.courier.requestPreferenceText": "Permet de définir quelles partitions doivent gérer les requêtes de recherche.\n
    \n
  • {sessionId} : limite les opérations pour exécuter toutes les requêtes de recherche sur les mêmes partitions.\n Cela a l'avantage de réutiliser les caches de partition pour toutes les requêtes.
  • \n
  • {custom} : permet de définir une valeur de préférence.\n Utilisez \"courier:customRequestPreference\" pour personnaliser votre valeur de préférence.
  • \n
  • {none} : permet de ne pas définir de préférence.\n Cela peut permettre de meilleures performances, car les requêtes peuvent être réparties entre toutes les copies de partition.\n Cependant, les résultats peuvent être incohérents, les différentes partitions pouvant se trouver dans différents états d'actualisation.
  • \n
", + "data.advancedSettings.courier.requestPreferenceTitle": "Préférence de requête", + "data.advancedSettings.defaultIndexText": "L’index utilisé en l’absence de spécification.", + "data.advancedSettings.defaultIndexTitle": "Index par défaut", + "data.advancedSettings.docTableHighlightText": "Cela permet de mettre les résultats en surbrillance dans le tableau de bord Discover ainsi que dans les recherches enregistrées. À noter que la mise en surbrillance ralentit les requêtes dans le cas de documents volumineux.", + "data.advancedSettings.docTableHighlightTitle": "Mettre les résultats en surbrillance", + "data.advancedSettings.histogram.barTargetText": "Tente de générer ce nombre de compartiments lorsque l’intervalle \"auto\" est utilisé dans des histogrammes numériques et de date.", + "data.advancedSettings.histogram.barTargetTitle": "Nombre de compartiments cible", + "data.advancedSettings.histogram.maxBarsText": "\n Limite la densité des histogrammes numériques et de date dans tout Kibana\n pour de meilleures performances à l’aide d’une requête de test. Si la requête de test génère trop de compartiments,\n l'intervalle entre les compartiments est augmenté. Ce paramètre s'applique séparément\n pour chaque agrégation d'histogrammes et ne s'applique pas aux autres types d'agrégations.\n Pour identifier la valeur maximale de ce paramètre, divisez la valeur \"search.max_buckets\" d'Elasticsearch\n par le nombre maximal d'agrégations dans chaque visualisation.\n ", + "data.advancedSettings.histogram.maxBarsTitle": "Nombre maximal de compartiments", + "data.advancedSettings.historyLimitText": "Le nombre de valeurs les plus récentes qui s’affichent pour les champs associés à un historique (par exemple, les entrées de requête).", + "data.advancedSettings.historyLimitTitle": "Limite d'historique", + "data.advancedSettings.metaFieldsText": "Champs qui existent en dehors de _source pour fusionner avec le document lors de l'affichage.", + "data.advancedSettings.metaFieldsTitle": "Champs méta", + "data.advancedSettings.pinFiltersText": "Détermine si les filtres doivent avoir un certain état global (être épinglés) par défaut.", + "data.advancedSettings.pinFiltersTitle": "Épingler les filtres par défaut", + "data.advancedSettings.query.allowWildcardsText": "Lorsque ce paramètre est activé, le caractère \"*\" est autorisé en tant que premier caractère dans une clause de requête. Ne s'applique actuellement que lorsque les fonctionnalités de requête expérimentales sont activées dans la barre de requête. Pour ne plus autoriser l’utilisation de caractères génériques au début des requêtes Lucene de base, utilisez {queryStringOptionsPattern}.", + "data.advancedSettings.query.allowWildcardsTitle": "Autoriser les caractères génériques au début des requêtes", + "data.advancedSettings.query.queryStringOptions.optionsLinkText": "Options", + "data.advancedSettings.query.queryStringOptionsText": "{optionsLink} pour l'analyseur de chaînes de requête Lucene. Uniquement utilisé lorsque \"{queryLanguage}\" est défini sur {luceneLanguage}.", + "data.advancedSettings.query.queryStringOptionsTitle": "Options de chaîne de requête", + "data.advancedSettings.searchQueryLanguageKql": "KQL", + "data.advancedSettings.searchQueryLanguageLucene": "Lucene", + "data.advancedSettings.searchQueryLanguageText": "Le langage de requête utilisé par la barre de requête. KQL est un nouveau langage spécialement conçu pour Kibana.", + "data.advancedSettings.searchQueryLanguageTitle": "Langage de requête", + "data.advancedSettings.searchTimeout": "Délai d'expiration de la recherche", + "data.advancedSettings.searchTimeoutDesc": "Permet de définir le délai d'expiration maximal pour une session de recherche. La valeur 0 permet de désactiver le délai d’expiration afin que les requêtes soient exécutées jusqu'au bout.", + "data.advancedSettings.sortOptions.optionsLinkText": "Options", + "data.advancedSettings.sortOptionsText": "{optionsLink} pour le paramètre de tri Elasticsearch", + "data.advancedSettings.sortOptionsTitle": "Options de tri", + "data.advancedSettings.suggestFilterValuesText": "Définir cette propriété sur \"faux\" permet d’empêcher l'éditeur de filtres de suggérer des valeurs pour les champs.", + "data.advancedSettings.suggestFilterValuesTitle": "Suggestions de l'éditeur de filtres", + "data.advancedSettings.timepicker.last15Minutes": "Dernières 15 minutes", + "data.advancedSettings.timepicker.last1Hour": "Dernière heure", + "data.advancedSettings.timepicker.last1Year": "Dernière année", + "data.advancedSettings.timepicker.last24Hours": "Dernières 24 heures", + "data.advancedSettings.timepicker.last30Days": "30 derniers jours", + "data.advancedSettings.timepicker.last30Minutes": "30 dernières minutes", + "data.advancedSettings.timepicker.last7Days": "7 derniers jours", + "data.advancedSettings.timepicker.last90Days": "90 derniers jours", + "data.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText": "formats acceptés", + "data.advancedSettings.timepicker.quickRangesText": "La liste des plages à afficher dans la section rapide du filtre temporel. Il s’agit d’un tableau d'objets, avec chaque objet contenant \"de\", \"à\" (voir {acceptedFormatsLink}) et \"afficher\" (le titre à afficher).", + "data.advancedSettings.timepicker.quickRangesTitle": "Plages rapides du filtre temporel", + "data.advancedSettings.timepicker.refreshIntervalDefaultsText": "L'intervalle d'actualisation par défaut du filtre temporel. La valeur doit être spécifiée en millisecondes.", + "data.advancedSettings.timepicker.refreshIntervalDefaultsTitle": "Intervalle d'actualisation du filtre temporel", + "data.advancedSettings.timepicker.thisWeek": "Cette semaine", + "data.advancedSettings.timepicker.timeDefaultsText": "L’option de filtre temporel à utiliser lorsque Kibana est démarré sans filtre", + "data.advancedSettings.timepicker.timeDefaultsTitle": "Filtre temporel par défaut", + "data.advancedSettings.timepicker.today": "Aujourd'hui", + "data.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} et {lt} {to}", + "data.aggTypes.buckets.ranges.rangesFormatMessageArrowRight": "{from} → {to}", + "data.errors.fetchError": "Vérifiez votre réseau et la configuration de votre proxy. Si le problème persiste, contactez votre administrateur réseau.", + "data.filter.applyFilterActionTitle": "Appliquer le filtre à la vue en cours", + "data.filter.applyFilters.popupHeader": "Sélectionner les filtres à appliquer", + "data.filter.applyFiltersPopup.cancelButtonLabel": "Annuler", + "data.filter.applyFiltersPopup.saveButtonLabel": "Appliquer", + "data.filter.filterBar.addFilterButtonLabel": "Ajouter un filtre", + "data.filter.filterBar.deleteFilterButtonLabel": "Supprimer", + "data.filter.filterBar.disabledFilterPrefix": "Désactivé", + "data.filter.filterBar.disableFilterButtonLabel": "Désactiver temporairement", + "data.filter.filterBar.editFilterButtonLabel": "Modifier le filtre", + "data.filter.filterBar.enableFilterButtonLabel": "Réactiver", + "data.filter.filterBar.excludeFilterButtonLabel": "Exclure les résultats", + "data.filter.filterBar.fieldNotFound": "Champ {key} introuvable dans le modèle d'indexation {indexPattern}", + "data.filter.filterBar.filterItemBadgeAriaLabel": "Actions de filtrage", + "data.filter.filterBar.filterItemBadgeIconAriaLabel": "Supprimer {filter}", + "data.filter.filterBar.includeFilterButtonLabel": "Inclure les résultats", + "data.filter.filterBar.indexPatternSelectPlaceholder": "Sélectionner un modèle d'indexation", + "data.filter.filterBar.labelErrorInfo": "Modèle d'indexation {indexPattern} introuvable", + "data.filter.filterBar.labelErrorText": "Erreur", + "data.filter.filterBar.labelWarningInfo": "Le champ {fieldName} n'existe pas dans la vue en cours.", + "data.filter.filterBar.labelWarningText": "Avertissement", + "data.filter.filterBar.moreFilterActionsMessage": "Filtre : {innerText}. Sélectionner pour plus d’actions de filtrage.", + "data.filter.filterBar.negatedFilterPrefix": "NON ", + "data.filter.filterBar.pinFilterButtonLabel": "Épingler dans toutes les applications", + "data.filter.filterBar.pinnedFilterPrefix": "Épinglé", + "data.filter.filterBar.unpinFilterButtonLabel": "Désépingler", + "data.filter.filterEditor.cancelButtonLabel": "Annuler", + "data.filter.filterEditor.createCustomLabelInputLabel": "Étiquette personnalisée", + "data.filter.filterEditor.createCustomLabelSwitchLabel": "Créer une étiquette personnalisée ?", + "data.filter.filterEditor.doesNotExistOperatorOptionLabel": "n'existe pas", + "data.filter.filterEditor.editFilterPopupTitle": "Modifier le filtre", + "data.filter.filterEditor.editFilterValuesButtonLabel": "Modifier les valeurs du filtre", + "data.filter.filterEditor.editQueryDslButtonLabel": "Modifier en tant que Query DSL", + "data.filter.filterEditor.existsOperatorOptionLabel": "existe", + "data.filter.filterEditor.falseOptionLabel": "false", + "data.filter.filterEditor.fieldSelectLabel": "Champ", + "data.filter.filterEditor.fieldSelectPlaceholder": "Sélectionner d'abord un champ", + "data.filter.filterEditor.indexPatternSelectLabel": "Modèle d'indexation", + "data.filter.filterEditor.isBetweenOperatorOptionLabel": "est entre", + "data.filter.filterEditor.isNotBetweenOperatorOptionLabel": "n'est pas entre", + "data.filter.filterEditor.isNotOneOfOperatorOptionLabel": "n'est pas l'une des options suivantes", + "data.filter.filterEditor.isNotOperatorOptionLabel": "n'est pas", + "data.filter.filterEditor.isOneOfOperatorOptionLabel": "est l'une des options suivantes", + "data.filter.filterEditor.isOperatorOptionLabel": "est", + "data.filter.filterEditor.operatorSelectLabel": "Opérateur", + "data.filter.filterEditor.operatorSelectPlaceholderSelect": "Sélectionner", + "data.filter.filterEditor.operatorSelectPlaceholderWaiting": "En attente", + "data.filter.filterEditor.queryDslLabel": "Query DSL d'Elasticsearch", + "data.filter.filterEditor.rangeEndInputPlaceholder": "Fin de la plage", + "data.filter.filterEditor.rangeInputLabel": "Plage", + "data.filter.filterEditor.rangeStartInputPlaceholder": "Début de la plage", + "data.filter.filterEditor.saveButtonLabel": "Enregistrer", + "data.filter.filterEditor.trueOptionLabel": "vrai", + "data.filter.filterEditor.valueInputLabel": "Valeur", + "data.filter.filterEditor.valueInputPlaceholder": "Saisir une valeur", + "data.filter.filterEditor.valueSelectPlaceholder": "Sélectionner une valeur", + "data.filter.filterEditor.valuesSelectLabel": "Valeurs", + "data.filter.filterEditor.valuesSelectPlaceholder": "Sélectionner des valeurs", + "data.filter.options.changeAllFiltersButtonLabel": "Changer tous les filtres", + "data.filter.options.deleteAllFiltersButtonLabel": "Tout supprimer", + "data.filter.options.disableAllFiltersButtonLabel": "Tout désactiver", + "data.filter.options.enableAllFiltersButtonLabel": "Tout activer", + "data.filter.options.invertDisabledFiltersButtonLabel": "Inverser l’activation/désactivation", + "data.filter.options.invertNegatedFiltersButtonLabel": "Inverser l'inclusion", + "data.filter.options.pinAllFiltersButtonLabel": "Tout épingler", + "data.filter.options.unpinAllFiltersButtonLabel": "Tout désépingler", + "data.filter.searchBar.changeAllFiltersTitle": "Changer tous les filtres", + "data.functions.esaggs.help": "Exécuter l'agrégation AggConfig", + "data.functions.esaggs.inspector.dataRequest.description": "Cette requête interroge Elasticsearch pour récupérer les données pour la visualisation.", + "data.functions.esaggs.inspector.dataRequest.title": "Données", + "data.inspector.table..dataDescriptionTooltip": "Afficher les données derrière la visualisation", + "data.inspector.table.dataTitle": "Données", + "data.inspector.table.downloadCSVToggleButtonLabel": "Télécharger CSV", + "data.inspector.table.downloadOptionsUnsavedFilename": "non enregistré", + "data.inspector.table.exportButtonFormulasWarning": "Votre fichier CSV contient des caractères que les applications de feuilles de calcul pourraient considérer comme des formules.", + "data.inspector.table.filterForValueButtonAriaLabel": "Filtrer sur la valeur", + "data.inspector.table.filterForValueButtonTooltip": "Filtrer sur la valeur", + "data.inspector.table.filterOutValueButtonAriaLabel": "Exclure la valeur", + "data.inspector.table.filterOutValueButtonTooltip": "Exclure la valeur", + "data.inspector.table.formattedCSVButtonLabel": "CSV formaté", + "data.inspector.table.formattedCSVButtonTooltip": "Télécharger les données sous forme de tableau", + "data.inspector.table.noDataAvailableDescription": "L'élément n'a fourni aucune donnée.", + "data.inspector.table.noDataAvailableTitle": "Aucune donnée disponible", + "data.inspector.table.rawCSVButtonLabel": "CSV brut", + "data.inspector.table.rawCSVButtonTooltip": "Télécharger les données telles que fournies, par exemple, les dates sous forme d'horodatages", + "data.inspector.table.tableLabel": "Tableau {index}", + "data.inspector.table.tablesDescription": "Il y a {tablesCount, plural, one {# tableau} other {# tableaux} } au total.", + "data.inspector.table.tableSelectorLabel": "Sélectionné :", + "data.kueryAutocomplete.andOperatorDescription": "Nécessite que {bothArguments} soient ''vrai''.", + "data.kueryAutocomplete.andOperatorDescription.bothArgumentsText": "les deux arguments", + "data.kueryAutocomplete.equalOperatorDescription": "{equals} une certaine valeur", + "data.kueryAutocomplete.equalOperatorDescription.equalsText": "égale", + "data.kueryAutocomplete.existOperatorDescription": "{exists} sous un certain format", + "data.kueryAutocomplete.existOperatorDescription.existsText": "existe", + "data.kueryAutocomplete.filterResultsDescription": "Filtrer les résultats contenant {fieldName}", + "data.kueryAutocomplete.greaterThanOperatorDescription": "est {greaterThan} une certaine valeur", + "data.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText": "supérieur à", + "data.kueryAutocomplete.greaterThanOrEqualOperatorDescription": "est {greaterThanOrEqualTo} une certaine valeur", + "data.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText": "supérieur ou égal à", + "data.kueryAutocomplete.lessThanOperatorDescription": "est {lessThan} une certaine valeur", + "data.kueryAutocomplete.lessThanOperatorDescription.lessThanText": "inférieur à", + "data.kueryAutocomplete.lessThanOrEqualOperatorDescription": "est {lessThanOrEqualTo} une certaine valeur", + "data.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "inférieur ou égal à", + "data.kueryAutocomplete.orOperatorDescription": "Nécessite qu’{oneOrMoreArguments} soit ''vrai''.", + "data.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "au moins un argument", + "data.noDataPopover.content": "Cette plage temporelle ne contient pas de données. Étendez ou ajustez la plage temporelle pour obtenir plus de champs et pouvoir créer des graphiques.", + "data.noDataPopover.dismissAction": "Ne plus afficher", + "data.noDataPopover.subtitle": "Conseil", + "data.noDataPopover.title": "Ensemble de données vide", + "data.painlessError.buttonTxt": "Modifier le script", + "data.painlessError.painlessScriptedFieldErrorMessage": "Erreur d'exécution du champ d'exécution ou du champ scripté sur le modèle d'indexation {indexPatternName}", + "data.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "Intervalle de calendrier non valide : {interval} ; la valeur doit être 1.", + "data.parseEsInterval.invalidEsIntervalFormatErrorMessage": "Format d'intervalle non valide : {interval}", + "data.query.queryBar.clearInputLabel": "Effacer l'entrée", + "data.query.queryBar.comboboxAriaLabel": "Rechercher et filtrer la page {pageType}", + "data.query.queryBar.kqlFullLanguageName": "Langage de requête Kibana", + "data.query.queryBar.kqlLanguageName": "KQL", + "data.query.queryBar.KQLNestedQuerySyntaxInfoDocLinkText": "documents", + "data.query.queryBar.KQLNestedQuerySyntaxInfoOptOutText": "Ne plus afficher", + "data.query.queryBar.KQLNestedQuerySyntaxInfoText": "Il semblerait que votre requête porte sur un champ imbriqué. Selon le résultat visé, il existe plusieurs façons de construire une syntaxe KQL pour des requêtes imbriquées. Apprenez-en plus avec notre {link}.", + "data.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "Syntaxe de requête imbriquée KQL", + "data.query.queryBar.kqlOffLabel": "Off", + "data.query.queryBar.kqlOnLabel": "On", + "data.query.queryBar.languageSwitcher.toText": "Passer au langage de requête Kibana pour la recherche", + "data.query.queryBar.luceneLanguageName": "Lucene", + "data.query.queryBar.searchInputAriaLabel": "Commencer à taper pour rechercher et filtrer la page {pageType}", + "data.query.queryBar.searchInputPlaceholder": "Recherche", + "data.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) offre une syntaxe de requête simplifiée et la prise en charge des champs scriptés. KQL offre également une fonctionnalité de saisie semi-automatique. Si vous désactivez KQL, {nonKqlModeHelpText}.", + "data.query.queryBar.syntaxOptionsDescription.nonKqlModeHelpText": "Kibana utilise Lucene.", + "data.query.queryBar.syntaxOptionsTitle": "Options de syntaxe", + "data.search.aggs.aggGroups.bucketsText": "Compartiments", + "data.search.aggs.aggGroups.metricsText": "Indicateurs", + "data.search.aggs.aggGroups.noneText": "Aucune", + "data.search.aggs.aggTypesLabel": "plages {fieldName}", + "data.search.aggs.buckets.dateHistogram.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.dropPartials.help": "Spécifie l'utilisation ou non de drop_partials pour cette agrégation.", + "data.search.aggs.buckets.dateHistogram.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.dateHistogram.extendedBounds.help": "Avec le paramètre extended_bounds, il est désormais possible de \"forcer\" l'agrégation d'histogrammes à démarrer la conception des compartiments sur une valeur minimale spécifique et à continuer jusqu'à une valeur maximale. ", + "data.search.aggs.buckets.dateHistogram.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.format.help": "Format à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.interval.help": "Intervalle à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.dateHistogram.minDocCount.help": "Nombre minimal de documents à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.scaleMetricValues.help": "Spécifie l'utilisation ou non de scaleMetricValues pour cette agrégation.", + "data.search.aggs.buckets.dateHistogram.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.timeRange.help": "Plage temporelle à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.timeZone.help": "Fuseau horaire à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateHistogram.useNormalizedEsInterval.help": "Spécifie l'utilisation ou non de useNormalizedEsInterval pour cette agrégation.", + "data.search.aggs.buckets.dateHistogramLabel": "{fieldName} par {intervalDescription}", + "data.search.aggs.buckets.dateHistogramTitle": "Histogramme de date", + "data.search.aggs.buckets.dateRange.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.dateRange.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.dateRange.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateRange.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.dateRange.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.dateRange.ranges.help": "Plages à utiliser pour cette agrégation.", + "data.search.aggs.buckets.dateRange.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.dateRange.timeZone.help": "Fuseau horaire à utiliser pour cette agrégation.", + "data.search.aggs.buckets.dateRangeTitle": "Plage de dates", + "data.search.aggs.buckets.filter.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.filter.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.filter.filter.help": "Pour filtrer les résultats en fonction d’une requête KQL ou Lucene. Ne pas utiliser en association avec geo_bounding_box.", + "data.search.aggs.buckets.filter.geoBoundingBox.help": "Pour filtrer les résultats en fonction d’une localisation au sein d’une zone de délimitation", + "data.search.aggs.buckets.filter.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.filter.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.filter.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.filters.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.filters.filters.help": "Filtres à utiliser pour cette agrégation", + "data.search.aggs.buckets.filters.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.filters.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.filters.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.filtersTitle": "Filtres", + "data.search.aggs.buckets.filterTitle": "Filtre", + "data.search.aggs.buckets.geoHash.autoPrecision.help": "Spécifie l'utilisation ou non de la précision automatique pour cette agrégation.", + "data.search.aggs.buckets.geoHash.boundingBox.help": "Pour filtrer les résultats en fonction d’une localisation au sein d’une zone de délimitation", + "data.search.aggs.buckets.geoHash.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.geoHash.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.geoHash.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.geoHash.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.geoHash.isFilteredByCollar.help": "Spécifie le filtrage ou non par collier.", + "data.search.aggs.buckets.geoHash.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.geoHash.precision.help": "Précision à utiliser pour cette agrégation.", + "data.search.aggs.buckets.geoHash.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.geoHash.useGeocentroid.help": "Spécifie l'utilisation ou non d’un centroïde géométrique pour cette agrégation.", + "data.search.aggs.buckets.geohashGridTitle": "Geohash", + "data.search.aggs.buckets.geoTile.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.geoTile.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.geoTile.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.geoTile.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.geoTile.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.geoTile.precision.help": "Précision à utiliser pour cette agrégation.", + "data.search.aggs.buckets.geoTile.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.geoTile.useGeocentroid.help": "Spécifie l'utilisation ou non d’un centroïde géométrique pour cette agrégation.", + "data.search.aggs.buckets.geotileGridTitle": "Geotile", + "data.search.aggs.buckets.histogram.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.histogram.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.histogram.extendedBounds.help": "Avec le paramètre extended_bounds, il est désormais possible de \"forcer\" l'agrégation d'histogrammes à démarrer la conception des compartiments sur une valeur minimale spécifique et à continuer jusqu'à une valeur maximale. ", + "data.search.aggs.buckets.histogram.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.histogram.hasExtendedBounds.help": "Spécifie l'utilisation ou non de has_extended_bounds pour cette agrégation.", + "data.search.aggs.buckets.histogram.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.histogram.interval.help": "Intervalle à utiliser pour cette agrégation", + "data.search.aggs.buckets.histogram.intervalBase.help": "Intervalle de base à utiliser pour cette agrégation", + "data.search.aggs.buckets.histogram.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.histogram.maxBars.help": "Calcule l'intervalle pour obtenir approximativement le nombre de barres spécifié.", + "data.search.aggs.buckets.histogram.minDocCount.help": "Spécifie l'utilisation ou non de min_doc_count pour cette agrégation.", + "data.search.aggs.buckets.histogram.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.histogramTitle": "Histogramme", + "data.search.aggs.buckets.intervalOptions.autoDisplayName": "Auto", + "data.search.aggs.buckets.intervalOptions.dailyDisplayName": "Jour", + "data.search.aggs.buckets.intervalOptions.hourlyDisplayName": "Heure", + "data.search.aggs.buckets.intervalOptions.millisecondDisplayName": "Milliseconde", + "data.search.aggs.buckets.intervalOptions.minuteDisplayName": "Minute", + "data.search.aggs.buckets.intervalOptions.monthlyDisplayName": "Mois", + "data.search.aggs.buckets.intervalOptions.secondDisplayName": "Seconde", + "data.search.aggs.buckets.intervalOptions.weeklyDisplayName": "Semaine", + "data.search.aggs.buckets.intervalOptions.yearlyDisplayName": "Année", + "data.search.aggs.buckets.ipRange.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.ipRange.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.ipRange.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.ipRange.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.ipRange.ipRangeType.help": "Type de plage d'IP à utiliser pour cette agrégation. Doit être l’une des valeurs suivantes : mask, fromTo.", + "data.search.aggs.buckets.ipRange.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.ipRange.ranges.help": "Plages à utiliser pour cette agrégation.", + "data.search.aggs.buckets.ipRange.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.ipRangeLabel": "Plages d'IP de {fieldName}", + "data.search.aggs.buckets.ipRangeTitle": "Plage d'IP", + "data.search.aggs.buckets.range.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.range.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.range.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.range.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.range.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.range.ranges.help": "Plages en série à utiliser pour cette agrégation.", + "data.search.aggs.buckets.range.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.rangeTitle": "Plage", + "data.search.aggs.buckets.shardDelay.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.shardDelay.delay.help": "Délai entre les partitions à traiter. Exemple : \"5s\".", + "data.search.aggs.buckets.shardDelay.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.shardDelay.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.shardDelay.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.shardDelay.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.significantTerms.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.significantTerms.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.significantTerms.exclude.help": "Valeurs de compartiment spécifiques à exclure des résultats", + "data.search.aggs.buckets.significantTerms.excludeLabel": "Exclure", + "data.search.aggs.buckets.significantTerms.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.significantTerms.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.significantTerms.include.help": "Valeurs de compartiment spécifiques à inclure dans les résultats", + "data.search.aggs.buckets.significantTerms.includeLabel": "Inclure", + "data.search.aggs.buckets.significantTerms.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.significantTerms.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.significantTerms.size.help": "Nombre maximal de compartiments à extraire", + "data.search.aggs.buckets.significantTermsLabel": "Top {size} des termes les plus inhabituels pour {fieldName}", + "data.search.aggs.buckets.significantTermsTitle": "Termes importants", + "data.search.aggs.buckets.terms.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.buckets.terms.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.buckets.terms.exclude.help": "Valeurs de compartiment spécifiques à exclure des résultats", + "data.search.aggs.buckets.terms.excludeLabel": "Exclure", + "data.search.aggs.buckets.terms.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.buckets.terms.id.help": "ID pour cette agrégation", + "data.search.aggs.buckets.terms.include.help": "Valeurs de compartiment spécifiques à inclure dans les résultats", + "data.search.aggs.buckets.terms.includeLabel": "Inclure", + "data.search.aggs.buckets.terms.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.buckets.terms.missingBucket.help": "Lorsqu'il est défini sur ''vrai'', ce paramètre regroupe tous les compartiments avec des champs manquants.", + "data.search.aggs.buckets.terms.missingBucketLabel": "Manquant", + "data.search.aggs.buckets.terms.missingBucketLabel.help": "Étiquette par défaut utilisée dans les graphiques lorsqu'il manque un champ aux documents.", + "data.search.aggs.buckets.terms.order.help": "Ordre dans lequel renvoyer les résultats : croissant ou décroissant", + "data.search.aggs.buckets.terms.orderAgg.help": "Configuration d'agrégation à utiliser pour ordonner les résultats", + "data.search.aggs.buckets.terms.orderAscendingTitle": "Croissant", + "data.search.aggs.buckets.terms.orderBy.help": "Champ selon lequel ordonner les résultats", + "data.search.aggs.buckets.terms.orderDescendingTitle": "Décroissant", + "data.search.aggs.buckets.terms.otherBucket.help": "Lorsqu'il est défini sur ''vrai'', ce paramètre regroupe tous les compartiments au-delà de la taille autorisée.", + "data.search.aggs.buckets.terms.otherBucketDescription": "Cette requête comptabilise le nombre de documents qui ne répondent pas au critère des compartiments de données.", + "data.search.aggs.buckets.terms.otherBucketLabel": "Autre", + "data.search.aggs.buckets.terms.otherBucketLabel.help": "Étiquette par défaut utilisée dans les graphiques pour les documents du compartiment Autre", + "data.search.aggs.buckets.terms.otherBucketTitle": "Compartiment Autre", + "data.search.aggs.buckets.terms.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.buckets.terms.size.help": "Nombre maximal de compartiments à extraire", + "data.search.aggs.buckets.termsTitle": "Termes", + "data.search.aggs.error.aggNotFound": "Aucun type d'agrégation enregistré pour \"{type}\".", + "data.search.aggs.function.buckets.dateHistogram.help": "Génère une configuration d'agrégation en série pour une agrégation Histogramme.", + "data.search.aggs.function.buckets.dateRange.help": "Génère une configuration d'agrégation en série pour une agrégation Plage de dates.", + "data.search.aggs.function.buckets.filter.help": "Génère une configuration d'agrégation en série pour une agrégation Filtre.", + "data.search.aggs.function.buckets.filters.help": "Génère une configuration d'agrégation en série pour une agrégation Filtre.", + "data.search.aggs.function.buckets.geoHash.help": "Génère une configuration d'agrégation en série pour une agrégation Geohash.", + "data.search.aggs.function.buckets.geoTile.help": "Génère une configuration d'agrégation en série pour une agrégation Geotile.", + "data.search.aggs.function.buckets.histogram.help": "Génère une configuration d'agrégation en série pour une agrégation Histogramme.", + "data.search.aggs.function.buckets.ipRange.help": "Génère une configuration d'agrégation en série pour une agrégation Plage d'IP.", + "data.search.aggs.function.buckets.range.help": "Génère une configuration d'agrégation en série pour une agrégation Plage.", + "data.search.aggs.function.buckets.shardDelay.help": "Génère une configuration d'agrégation en série pour une agrégation Délai de partition.", + "data.search.aggs.function.buckets.significantTerms.help": "Génère une configuration d'agrégation en série pour une agrégation Termes importants.", + "data.search.aggs.function.buckets.terms.help": "Génère une configuration d'agrégation en série pour une agrégation Termes.", + "data.search.aggs.function.metrics.avg.help": "Génère une configuration d'agrégation en série pour une agrégation Moyenne.", + "data.search.aggs.function.metrics.bucket_avg.help": "Génère une configuration d'agrégation en série pour une agrégation Moyenne compartiment.", + "data.search.aggs.function.metrics.bucket_max.help": "Génère une configuration d'agrégation en série pour une agrégation Max. compartiment.", + "data.search.aggs.function.metrics.bucket_min.help": "Génère une configuration d'agrégation en série pour une agrégation Min. compartiment.", + "data.search.aggs.function.metrics.bucket_sum.help": "Génère une configuration d'agrégation en série pour une agrégation Somme compartiment.", + "data.search.aggs.function.metrics.cardinality.help": "Génère une configuration d'agrégation en série pour une agrégation Cardinalité.", + "data.search.aggs.function.metrics.count.help": "Génère une configuration d'agrégation en série pour une agrégation Décompte.", + "data.search.aggs.function.metrics.cumulative_sum.help": "Génère une configuration d'agrégation en série pour une agrégation Somme cumulée.", + "data.search.aggs.function.metrics.derivative.help": "Génère une configuration d'agrégation en série pour une agrégation Dérivée.", + "data.search.aggs.function.metrics.filtered_metric.help": "Génère une configuration d'agrégation en série pour une agrégation Indicateur filtré.", + "data.search.aggs.function.metrics.geo_bounds.help": "Génère une configuration d'agrégation en série pour une agrégation Délimitation géométrique.", + "data.search.aggs.function.metrics.geo_centroid.help": "Génère une configuration d'agrégation en série pour une agrégation Centroïde géométrique.", + "data.search.aggs.function.metrics.max.help": "Génère une configuration d'agrégation en série pour une agrégation Max.", + "data.search.aggs.function.metrics.median.help": "Génère une configuration d'agrégation en série pour une agrégation Médiane.", + "data.search.aggs.function.metrics.min.help": "Génère une configuration d'agrégation en série pour une agrégation Min.", + "data.search.aggs.function.metrics.moving_avg.help": "Génère une configuration d'agrégation en série pour une agrégation Moyenne mobile.", + "data.search.aggs.function.metrics.percentile_ranks.help": "Génère une configuration d'agrégation en série pour une agrégation Rangs centiles.", + "data.search.aggs.function.metrics.percentiles.help": "Génère une configuration d'agrégation en série pour une agrégation Centiles.", + "data.search.aggs.function.metrics.serial_diff.help": "Génère une configuration d'agrégation en série pour une agrégation Différenciation en série.", + "data.search.aggs.function.metrics.singlePercentile.help": "Génère une configuration d'agrégation en série pour une agrégation Centile unique.", + "data.search.aggs.function.metrics.std_deviation.help": "Génère une configuration d'agrégation en série pour une agrégation Écart-type.", + "data.search.aggs.function.metrics.sum.help": "Génère une configuration d'agrégation en série pour une agrégation Somme.", + "data.search.aggs.function.metrics.top_hit.help": "Génère une configuration d'agrégation en série pour une agrégation Meilleur résultat.", + "data.search.aggs.histogram.missingMaxMinValuesWarning": "Impossible d’extraire les valeurs max. et min. pour scaler automatiquement les compartiments de l'histogramme. Cela peut entraîner des performances de visualisation médiocres.", + "data.search.aggs.metrics.averageBucketTitle": "Moyenne compartiment", + "data.search.aggs.metrics.averageLabel": "Moyenne {field}", + "data.search.aggs.metrics.averageTitle": "Moyenne", + "data.search.aggs.metrics.avg.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.avg.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.avg.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.avg.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.avg.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.avg.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.bucket_avg.customBucket.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_avg.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.bucket_avg.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_avg.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.bucket_avg.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.bucket_avg.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.bucket_avg.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.bucket_max.customBucket.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_max.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.bucket_max.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_max.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.bucket_max.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.bucket_max.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.bucket_max.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.bucket_min.customBucket.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_min.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.bucket_min.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_min.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.bucket_min.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.bucket_min.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.bucket_min.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.bucket_sum.customBucket.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_sum.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.bucket_sum.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.bucket_sum.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.bucket_sum.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.bucket_sum.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.bucket_sum.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.cardinality.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.cardinality.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.cardinality.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.cardinality.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.cardinality.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.cardinality.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.count.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.count.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.count.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.count.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.countLabel": "Décompte", + "data.search.aggs.metrics.countTitle": "Décompte", + "data.search.aggs.metrics.cumulative_sum.buckets_path.help": "Chemin d’accès à l'indicateur d’intérêt", + "data.search.aggs.metrics.cumulative_sum.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.cumulative_sum.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.cumulative_sum.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.cumulative_sum.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.cumulative_sum.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.cumulative_sum.metricAgg.help": "ID correspondant à la configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.cumulative_sum.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.cumulativeSumLabel": "somme cumulée", + "data.search.aggs.metrics.cumulativeSumTitle": "Somme cumulée", + "data.search.aggs.metrics.derivative.buckets_path.help": "Chemin d’accès à l'indicateur d’intérêt", + "data.search.aggs.metrics.derivative.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.derivative.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.derivative.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.derivative.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.derivative.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.derivative.metricAgg.help": "ID correspondant à la configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.derivative.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.derivativeLabel": "dérivée", + "data.search.aggs.metrics.derivativeTitle": "Dérivée", + "data.search.aggs.metrics.filtered_metric.customBucket.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants. Doit être une agrégation de filtres.", + "data.search.aggs.metrics.filtered_metric.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.filtered_metric.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines enfants", + "data.search.aggs.metrics.filtered_metric.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.filtered_metric.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.filtered_metric.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.filteredMetricLabel": "filtré", + "data.search.aggs.metrics.filteredMetricTitle": "Indicateur filtré", + "data.search.aggs.metrics.geo_bounds.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.geo_bounds.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.geo_bounds.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.geo_bounds.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.geo_bounds.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.geo_bounds.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.geo_centroid.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.geo_centroid.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.geo_centroid.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.geo_centroid.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.geo_centroid.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.geo_centroid.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.geoBoundsLabel": "Délimitation géométrique", + "data.search.aggs.metrics.geoBoundsTitle": "Délimitation géométrique", + "data.search.aggs.metrics.geoCentroidLabel": "Centroïde géométrique", + "data.search.aggs.metrics.geoCentroidTitle": "Centroïde géométrique", + "data.search.aggs.metrics.max.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.max.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.max.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.max.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.max.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.max.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.maxBucketTitle": "Max. compartiment", + "data.search.aggs.metrics.maxLabel": "Max. {field}", + "data.search.aggs.metrics.maxTitle": "Max.", + "data.search.aggs.metrics.median.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.median.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.median.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.median.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.median.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.median.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.medianLabel": "Médiane {field}", + "data.search.aggs.metrics.medianTitle": "Médiane", + "data.search.aggs.metrics.metricAggregationsSubtypeTitle": "Agrégations d'indicateurs", + "data.search.aggs.metrics.min.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.min.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.min.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.min.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.min.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.min.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.minBucketTitle": "Min. compartiment", + "data.search.aggs.metrics.minLabel": "Min. {field}", + "data.search.aggs.metrics.minTitle": "Min.", + "data.search.aggs.metrics.moving_avg.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.moving_avg.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.moving_avg.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.moving_avg.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.moving_avg.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.moving_avg.metricAgg.help": "ID correspondant à la configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.moving_avg.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.moving_avg.script.help": "ID correspondant à la configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.moving_avg.window.help": "La taille de la fenêtre à \"faire glisser\" le long de l'histogramme.", + "data.search.aggs.metrics.movingAvgLabel": "moyenne mobile", + "data.search.aggs.metrics.movingAvgTitle": "Moyenne mobile", + "data.search.aggs.metrics.overallAverageLabel": "moyenne générale", + "data.search.aggs.metrics.overallMaxLabel": "max. général", + "data.search.aggs.metrics.overallMinLabel": "min. général", + "data.search.aggs.metrics.overallSumLabel": "somme générale", + "data.search.aggs.metrics.parentPipelineAggregationsSubtypeTitle": "Agrégations de pipelines parents", + "data.search.aggs.metrics.percentile_ranks.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.percentile_ranks.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.percentile_ranks.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.percentile_ranks.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.percentile_ranks.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.percentile_ranks.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.percentile_ranks.values.help": "Plage de rangs centiles", + "data.search.aggs.metrics.percentileRanks.valuePropsLabel": "Rang centile {format} de \"{label}\"", + "data.search.aggs.metrics.percentileRanksLabel": "Rangs centiles de {field}", + "data.search.aggs.metrics.percentileRanksTitle": "Rangs centiles", + "data.search.aggs.metrics.percentiles.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.percentiles.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.percentiles.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.percentiles.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.percentiles.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.percentiles.percents.help": "Plage de rangs centiles", + "data.search.aggs.metrics.percentiles.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.percentiles.valuePropsLabel": "{percentile} centile de {label}", + "data.search.aggs.metrics.percentilesLabel": "Centiles de {field}", + "data.search.aggs.metrics.percentilesTitle": "Centiles", + "data.search.aggs.metrics.serial_diff.buckets_path.help": "Chemin d’accès à l'indicateur d’intérêt", + "data.search.aggs.metrics.serial_diff.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.serial_diff.customMetric.help": "Configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.serial_diff.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.serial_diff.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.serial_diff.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.serial_diff.metricAgg.help": "ID correspondant à la configuration d'agrégation à utiliser pour la conception d'agrégations de pipelines parents", + "data.search.aggs.metrics.serial_diff.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.serialDiffLabel": "différenciation en série", + "data.search.aggs.metrics.serialDiffTitle": "Différenciation en série", + "data.search.aggs.metrics.siblingPipelineAggregationsSubtypeTitle": "Agrégations de pipelines enfants", + "data.search.aggs.metrics.singlePercentile.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.singlePercentile.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.singlePercentile.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.singlePercentile.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.singlePercentile.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.singlePercentile.percentile.help": "Centile à récupérer", + "data.search.aggs.metrics.singlePercentile.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.singlePercentileLabel": "Centile {field}", + "data.search.aggs.metrics.singlePercentileTitle": "Centile", + "data.search.aggs.metrics.standardDeviation.keyDetailsLabel": "Écart-type de {fieldDisplayName}", + "data.search.aggs.metrics.standardDeviation.lowerKeyDetailsTitle": "{label} inférieur", + "data.search.aggs.metrics.standardDeviation.upperKeyDetailsTitle": "{label} supérieur", + "data.search.aggs.metrics.standardDeviationLabel": "Écart-type de {field}", + "data.search.aggs.metrics.standardDeviationTitle": "Écart-type", + "data.search.aggs.metrics.std_deviation.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.std_deviation.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.std_deviation.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.std_deviation.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.std_deviation.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.std_deviation.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.sum.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.sum.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.sum.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.sum.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.sum.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.sum.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.sumBucketTitle": "Somme compartiment", + "data.search.aggs.metrics.sumLabel": "Somme de {field}", + "data.search.aggs.metrics.sumTitle": "Somme", + "data.search.aggs.metrics.timeShift.help": "Décalez la plage temporelle de l'indicateur d'une durée définie, par exemple 1 h ou 7 j. \"précédent\" utilisera la plage temporelle la plus proche du filtre d'histogramme de date ou de plage temporelle.", + "data.search.aggs.metrics.top_hit.aggregate.help": "Agréger le type", + "data.search.aggs.metrics.top_hit.customLabel.help": "Représente une étiquette personnalisée pour cette agrégation", + "data.search.aggs.metrics.top_hit.enabled.help": "Spécifie si cette agrégation doit être activée.", + "data.search.aggs.metrics.top_hit.field.help": "Champ à utiliser pour cette agrégation", + "data.search.aggs.metrics.top_hit.id.help": "ID pour cette agrégation", + "data.search.aggs.metrics.top_hit.json.help": "Json avancé à inclure lorsque l'agrégation est envoyée vers Elasticsearch", + "data.search.aggs.metrics.top_hit.schema.help": "Schéma à utiliser pour cette agrégation", + "data.search.aggs.metrics.top_hit.size.help": "Nombre maximal de compartiments à extraire", + "data.search.aggs.metrics.top_hit.sortField.help": "Champ selon lequel ordonner les résultats", + "data.search.aggs.metrics.top_hit.sortOrder.help": "Ordre dans lequel renvoyer les résultats : croissant ou décroissant", + "data.search.aggs.metrics.topHit.ascendingLabel": "Croissant", + "data.search.aggs.metrics.topHit.averageLabel": "Moyenne", + "data.search.aggs.metrics.topHit.concatenateLabel": "Concaténer", + "data.search.aggs.metrics.topHit.descendingLabel": "Décroissant", + "data.search.aggs.metrics.topHit.firstPrefixLabel": "Premier", + "data.search.aggs.metrics.topHit.lastPrefixLabel": "Dernier", + "data.search.aggs.metrics.topHit.maxLabel": "Max.", + "data.search.aggs.metrics.topHit.minLabel": "Min.", + "data.search.aggs.metrics.topHit.sumLabel": "Somme", + "data.search.aggs.metrics.topHitTitle": "Meilleur résultat", + "data.search.aggs.metrics.uniqueCountLabel": "Décompte unique de {field}", + "data.search.aggs.metrics.uniqueCountTitle": "Décompte unique", + "data.search.aggs.otherBucket.labelForMissingValuesLabel": "Étiquette pour des valeurs manquantes", + "data.search.aggs.otherBucket.labelForOtherBucketLabel": "Étiquette pour le compartiment Autre", + "data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "Le champ enregistré \"{fieldParameter}\" du modèle d'indexation \"{indexPatternTitle}\" n'est pas valide pour une utilisation avec l'agrégation \"{aggType}\". Veuillez sélectionner un nouveau champ.", + "data.search.aggs.paramTypes.field.notFoundSavedFieldParameterErrorMessage": "Le champ \"{fieldParameter}\" associé à cet objet n'existe plus dans le modèle d'indexation. Veuillez utiliser un autre champ.", + "data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} est un paramètre requis.", + "data.search.aggs.percentageOfLabel": "Pourcentage de {label}", + "data.search.aggs.string.customLabel": "Étiquette personnalisée", + "data.search.dataRequest.title": "Données", + "data.search.es_search.dataRequest.description": "Cette requête interroge Elasticsearch pour récupérer les données pour la visualisation.", + "data.search.es_search.hitsDescription": "Le nombre de documents renvoyés par la requête.", + "data.search.es_search.hitsLabel": "Résultats", + "data.search.es_search.hitsTotalDescription": "Le nombre de documents correspondant à la requête.", + "data.search.es_search.hitsTotalLabel": "Résultats (total)", + "data.search.es_search.indexPatternDescription": "Le modèle d'indexation qui se connecte aux index Elasticsearch.", + "data.search.es_search.queryTimeDescription": "Le temps qu'il a fallu pour traiter la requête. Ne comprend pas le temps nécessaire pour envoyer la requête ni l'analyser dans le navigateur.", + "data.search.es_search.queryTimeLabel": "Durée de la requête", + "data.search.es_search.queryTimeValue": "{queryTime}ms", + "data.search.esaggs.error.kibanaRequest": "Une requête Kibana est nécessaire pour exécuter cette recherche sur le serveur. Veuillez fournir un objet de requête pour les paramètres d'exécution de l'expression.", + "data.search.esdsl.help": "Exécuter une requête Elasticsearch", + "data.search.esdsl.index.help": "Index Elasticsearch à interroger", + "data.search.esdsl.q.help": "Requête DSL", + "data.search.esdsl.size.help": "Paramètre de taille de l’API de recherche d’Elasticsearch", + "data.search.esErrorTitle": "Impossible d’extraire les résultats de recherche", + "data.search.functions.cidr.cidr.help": "Spécifier le bloc CIDR", + "data.search.functions.cidr.help": "Créer une plage CIDR", + "data.search.functions.dateRange.from.help": "Spécifier la date de début", + "data.search.functions.dateRange.help": "Créer une plage de dates", + "data.search.functions.dateRange.to.help": "Spécifier la date de fin", + "data.search.functions.esaggs.aggConfigs.help": "Liste des agrégations configurées avec des fonctions agg_type", + "data.search.functions.esaggs.index.help": "Modèle d'indexation extrait avec indexPatternLoad", + "data.search.functions.esaggs.metricsAtAllLevels.help": "Spécifie l’inclusion ou non des colonnes avec indicateurs pour chaque niveau de compartiment.", + "data.search.functions.esaggs.partialRows.help": "Détermine s'il faut renvoyer ou non les lignes ne contenant que des données partielles.", + "data.search.functions.esaggs.timeFields.help": "Spécifiez des champs temporels afin d’obtenir les plages temporelles résolues pour la requête.", + "data.search.functions.existsFilter.field.help": "Spécifiez le champ que vous souhaitez filtrer. Utilisez la fonction ''field''.", + "data.search.functions.existsFilter.help": "Créer un filtre Kibana existant", + "data.search.functions.existsFilter.negate.help": "Si le filtre doit être inversé.", + "data.search.functions.extendedBounds.help": "Créer des limites étendues", + "data.search.functions.extendedBounds.max.help": "Spécifier la valeur de la limite supérieure", + "data.search.functions.extendedBounds.min.help": "Spécifier la valeur de la limite inférieure", + "data.search.functions.field.help": "Créer un champ Kibana", + "data.search.functions.field.name.help": "Nom du champ", + "data.search.functions.field.script.help": "Script de champ, au cas où le champ serait scripté.", + "data.search.functions.field.type.help": "Type du champ", + "data.search.functions.geoBoundingBox.arguments.error": "Au moins un des groupes de paramètres suivants doit être fourni : {parameters}.", + "data.search.functions.geoBoundingBox.bottom_left.help": "Spécifier l’angle inférieur gauche", + "data.search.functions.geoBoundingBox.bottom_right.help": "Spécifier l’angle inférieur droit", + "data.search.functions.geoBoundingBox.bottom.help": "Spécifier la coordonnée inférieure", + "data.search.functions.geoBoundingBox.help": "Créer une zone de délimitation géométrique", + "data.search.functions.geoBoundingBox.left.help": "Spécifier la coordonnée gauche", + "data.search.functions.geoBoundingBox.right.help": "Spécifier la coordonnée droite", + "data.search.functions.geoBoundingBox.top_left.help": "Spécifier l’angle supérieur gauche", + "data.search.functions.geoBoundingBox.top_right.help": "Spécifier l’angle supérieur droit", + "data.search.functions.geoBoundingBox.top.help": "Spécifier la coordonnée supérieure", + "data.search.functions.geoBoundingBox.wkt.help": "Spécifier le texte bien connu (WKT)", + "data.search.functions.geoPoint.arguments.error": "Les paramètres \"lat\" et \"lon\" ou \"point\" doivent être spécifiés.", + "data.search.functions.geoPoint.help": "Créer un point géographique", + "data.search.functions.geoPoint.lat.help": "Spécifier la latitude", + "data.search.functions.geoPoint.lon.help": "Spécifier la longitude", + "data.search.functions.geoPoint.point.error": "Le paramètre du point doit être une chaîne ou deux valeurs numériques.", + "data.search.functions.geoPoint.point.help": "Spécifiez le point sous la forme d’une chaîne de coordonnées séparées par des virgules ou sous la forme de deux valeurs numériques.", + "data.search.functions.ipRange.from.help": "Spécifier l'adresse de début", + "data.search.functions.ipRange.help": "Créer une plage d'IP", + "data.search.functions.ipRange.to.help": "Spécifier l'adresse de fin", + "data.search.functions.kibana_context.filters.help": "Spécifier des filtres génériques Kibana", + "data.search.functions.kibana_context.help": "Met à jour le contexte général de Kibana.", + "data.search.functions.kibana_context.q.help": "Spécifier une recherche en texte libre Kibana", + "data.search.functions.kibana_context.savedSearchId.help": "Spécifier l'ID de recherche enregistrée à utiliser pour les requêtes et les filtres", + "data.search.functions.kibana_context.timeRange.help": "Spécifier le filtre de plage temporelle Kibana", + "data.search.functions.kibana.help": "Permet d’obtenir le contexte général de Kibana.", + "data.search.functions.kibanaFilter.disabled.help": "Si le filtre doit être désactivé", + "data.search.functions.kibanaFilter.field.help": "Spécifier une recherche en texte libre esdsl", + "data.search.functions.kibanaFilter.help": "Créer un filtre Kibana", + "data.search.functions.kibanaFilter.negate.help": "Si le filtre doit être inversé", + "data.search.functions.kql.help": "Créer une requête KQL Kibana", + "data.search.functions.kql.q.help": "Spécifier une recherche en texte libre KQL Kibana", + "data.search.functions.lucene.help": "Créer une requête Lucene Kibana", + "data.search.functions.lucene.q.help": "Spécifier une recherche en texte libre Lucene", + "data.search.functions.numericalRange.from.help": "Spécifier la valeur de début", + "data.search.functions.numericalRange.help": "Créer une plage numérique", + "data.search.functions.numericalRange.label.help": "Spécifier l'étiquette de la plage", + "data.search.functions.numericalRange.to.help": "Spécifier la valeur de fin", + "data.search.functions.phraseFilter.field.help": "Spécifiez le champ que vous souhaitez filtrer. Utilisez la fonction ''field''.", + "data.search.functions.phraseFilter.help": "Créer un filtre d’expression Kibana", + "data.search.functions.phraseFilter.negate.help": "Si le filtre doit être inversé", + "data.search.functions.phraseFilter.phrase.help": "Spécifier l'expression", + "data.search.functions.queryFilter.help": "Créer un filtre de requête", + "data.search.functions.queryFilter.input.help": "Spécifier le filtre de requête", + "data.search.functions.queryFilter.label.help": "Spécifier l'étiquette du filtre", + "data.search.functions.range.gt.help": "Supérieur à", + "data.search.functions.range.gte.help": "Supérieur ou égal à", + "data.search.functions.range.help": "Créer un filtre de plage Kibana", + "data.search.functions.range.lt.help": "Inférieur à", + "data.search.functions.range.lte.help": "Inférieur ou égal à", + "data.search.functions.rangeFilter.field.help": "Spécifiez le champ que vous souhaitez filtrer. Utilisez la fonction ''field''.", + "data.search.functions.rangeFilter.help": "Créer un filtre de plage Kibana", + "data.search.functions.rangeFilter.negate.help": "Si le filtre doit être inversé", + "data.search.functions.rangeFilter.range.help": "Spécifiez la plage à l’aide de la fonction ''range''.", + "data.search.functions.timerange.from.help": "Spécifier la date de début", + "data.search.functions.timerange.help": "Créer une plage temporelle Kibana", + "data.search.functions.timerange.mode.help": "Spécifier le mode (absolu ou relatif)", + "data.search.functions.timerange.to.help": "Spécifier la date de fin", + "data.search.httpErrorTitle": "Impossible d’extraire vos données", + "data.search.searchBar.savedQueryDescriptionLabelText": "Description", + "data.search.searchBar.savedQueryDescriptionText": "Enregistrez le texte et les filtres de la requête que vous souhaitez réutiliser.", + "data.search.searchBar.savedQueryForm.titleConflictText": "Ce nom est en conflit avec une requête enregistrée existante.", + "data.search.searchBar.savedQueryFormCancelButtonText": "Annuler", + "data.search.searchBar.savedQueryFormSaveButtonText": "Enregistrer", + "data.search.searchBar.savedQueryFormTitle": "Enregistrer la requête", + "data.search.searchBar.savedQueryIncludeFiltersLabelText": "Inclure les filtres", + "data.search.searchBar.savedQueryIncludeTimeFilterLabelText": "Inclure le filtre temporel", + "data.search.searchBar.savedQueryNameHelpText": "Un nom est requis. Le nom ne peut pas contenir d'espace vide au début ou à la fin. Le nom doit être unique.", + "data.search.searchBar.savedQueryNameLabelText": "Nom", + "data.search.searchBar.savedQueryNoSavedQueriesText": "Aucune requête enregistrée.", + "data.search.searchBar.savedQueryPopoverButtonText": "Voir les requêtes enregistrées", + "data.search.searchBar.savedQueryPopoverClearButtonAriaLabel": "Effacer la requête enregistrée en cours", + "data.search.searchBar.savedQueryPopoverClearButtonText": "Effacer", + "data.search.searchBar.savedQueryPopoverConfirmDeletionCancelButtonText": "Annuler", + "data.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "Supprimer", + "data.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "Supprimer \"{savedQueryName}\" ?", + "data.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "Supprimer la requête enregistrée {savedQueryName}", + "data.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "Enregistrer en tant que nouvelle requête enregistrée", + "data.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "Enregistrer en tant que nouvelle", + "data.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "Enregistrer une nouvelle requête enregistrée", + "data.search.searchBar.savedQueryPopoverSaveButtonText": "Enregistrer la requête en cours", + "data.search.searchBar.savedQueryPopoverSaveChangesButtonAriaLabel": "Enregistrer les modifications apportées à {title}", + "data.search.searchBar.savedQueryPopoverSaveChangesButtonText": "Enregistrer les modifications", + "data.search.searchBar.savedQueryPopoverSavedQueryListItemButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName}", + "data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "Description de {savedQueryName}", + "data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName} sélectionné. Appuyez pour effacer les modifications.", + "data.search.searchBar.savedQueryPopoverTitleText": "Requêtes enregistrées", + "data.search.searchSource.fetch.requestTimedOutNotificationMessage": "Les données peuvent être incomplètes parce que votre requête est arrivée à échéance.", + "data.search.searchSource.fetch.shardsFailedModal.close": "Fermer", + "data.search.searchSource.fetch.shardsFailedModal.copyToClipboard": "Copier la réponse dans le presse-papiers", + "data.search.searchSource.fetch.shardsFailedModal.failureHeader": "{failureName} à {failureDetails}", + "data.search.searchSource.fetch.shardsFailedModal.showDetails": "Afficher les détails", + "data.search.searchSource.fetch.shardsFailedModal.tabHeaderRequest": "Requête", + "data.search.searchSource.fetch.shardsFailedModal.tabHeaderResponse": "Réponse", + "data.search.searchSource.fetch.shardsFailedModal.tabHeaderShardFailures": "Échecs de partition", + "data.search.searchSource.fetch.shardsFailedModal.tableColIndex": "Index", + "data.search.searchSource.fetch.shardsFailedModal.tableColNode": "Nœud", + "data.search.searchSource.fetch.shardsFailedModal.tableColReason": "Raison", + "data.search.searchSource.fetch.shardsFailedModal.tableColShard": "Partition", + "data.search.searchSource.fetch.shardsFailedModal.tableRowCollapse": "Réduire {rowDescription}", + "data.search.searchSource.fetch.shardsFailedModal.tableRowExpand": "Développer {rowDescription}", + "data.search.searchSource.fetch.shardsFailedNotificationDescription": "Les données que vous consultez peuvent être incomplètes ou erronées.", + "data.search.searchSource.fetch.shardsFailedNotificationMessage": "Échec de {shardsFailed} partitions sur {shardsTotal}", + "data.search.searchSource.hitsDescription": "Le nombre de documents renvoyés par la requête.", + "data.search.searchSource.hitsLabel": "Résultats", + "data.search.searchSource.hitsTotalDescription": "Le nombre de documents correspondant à la requête.", + "data.search.searchSource.hitsTotalLabel": "Résultats (total)", + "data.search.searchSource.indexPatternIdDescription": "L'ID dans l'index {kibanaIndexPattern}.", + "data.search.searchSource.queryTimeDescription": "Le temps qu'il a fallu pour traiter la requête. Ne comprend pas le temps nécessaire pour envoyer la requête ni l'analyser dans le navigateur.", + "data.search.searchSource.queryTimeLabel": "Durée de la requête", + "data.search.searchSource.queryTimeValue": "{queryTime}ms", + "data.search.searchSource.requestTimeDescription": "Durée de la requête depuis le navigateur jusqu’à Elasticsearch et retour. N’inclut pas le temps d’attente de la requête dans la file.", + "data.search.searchSource.requestTimeLabel": "Durée de la requête", + "data.search.searchSource.requestTimeValue": "{requestTime}ms", + "data.search.timeBuckets.dayLabel": "{amount, plural, one {un jour} other {# jours}}", + "data.search.timeBuckets.hourLabel": "{amount, plural, one {une heure} other {# heures}}", + "data.search.timeBuckets.infinityLabel": "Plus d'une année", + "data.search.timeBuckets.millisecondLabel": "{amount, plural, one {une milliseconde} other {# millisecondes}}", + "data.search.timeBuckets.minuteLabel": "{amount, plural, one {une minute} other {# minutes}}", + "data.search.timeBuckets.monthLabel": "un mois", + "data.search.timeBuckets.secondLabel": "{amount, plural, one {une seconde} other {# secondes}}", + "data.search.timeBuckets.yearLabel": "une année", + "data.search.timeoutContactAdmin": "Votre requête a expiré. Contactez l'administrateur système pour accroître le temps d'exécution.", + "data.search.timeoutIncreaseSetting": "Votre requête a expiré. Augmentez le temps d'exécution en utilisant le paramètre avancé de délai d'expiration de la recherche.", + "data.search.timeoutIncreaseSettingActionText": "Modifier le paramètre", + "data.search.unableToGetSavedQueryToastTitle": "Impossible de charger la requête enregistrée {savedQueryId}", + "data.searchSession.warning.readDocs": "En savoir plus", + "data.searchSessionIndicator.noCapability": "Vous n'êtes pas autorisé à créer des sessions de recherche.", + "data.searchSessions.sessionService.sessionEditNameError": "Échec de modification du nom de la session de recherche", + "data.searchSessions.sessionService.sessionObjectFetchError": "Échec de récupération des informations de la session de recherche", + "data.triggers.applyFilterDescription": "Lorsque le filtre Kibana est appliqué. Peut être un filtre simple ou un filtre de plage.", + "data.triggers.applyFilterTitle": "Appliquer le filtre", + "devTools.badge.readOnly.text": "Lecture seule", + "devTools.badge.readOnly.tooltip": "Enregistrement impossible", + "devTools.devToolsTitle": "Outils de développement", + "discover.advancedSettings.context.defaultSizeText": "Le nombre d'entrées connexes à afficher dans la vue contextuelle", + "discover.advancedSettings.context.defaultSizeTitle": "Taille de contexte", + "discover.advancedSettings.context.sizeStepText": "L’incrément duquel augmenter ou diminuer la taille de contexte", + "discover.advancedSettings.context.sizeStepTitle": "Incrément de taille de contexte", + "discover.advancedSettings.context.tieBreakerFieldsText": "Une liste de champs séparés par des virgules à utiliser pour départager les documents présentant la même valeur d'horodatage. Le premier champ de cette liste qui est à la fois présent et triable dans le modèle d'indexation en cours est utilisé.", + "discover.advancedSettings.context.tieBreakerFieldsTitle": "Champs de départage", + "discover.advancedSettings.defaultColumnsText": "Les colonnes affichées par défaut dans l'onglet Discover", + "discover.advancedSettings.defaultColumnsTitle": "Colonnes par défaut", + "discover.advancedSettings.discover.modifyColumnsOnSwitchText": "Supprimez les colonnes qui ne sont pas disponibles dans le nouveau modèle d'indexation.", + "discover.advancedSettings.discover.modifyColumnsOnSwitchTitle": "Modifier les colonnes en cas de changement des modèles d'indexation", + "discover.advancedSettings.discover.multiFieldsLinkText": "champs multiples", + "discover.advancedSettings.discover.readFieldsFromSource": "Lire les champs depuis _source", + "discover.advancedSettings.discover.readFieldsFromSourceDescription": "Lorsque cette option est activée, les documents sont chargés directement depuis ''_source''. Elle sera bientôt déclassée. Lorsqu'elle est désactivée, les champs sont extraits via la nouvelle API de champ du service de recherche de haut niveau.", + "discover.advancedSettings.discover.showMultifields": "Afficher les champs multiples", + "discover.advancedSettings.discover.showMultifieldsDescription": "Détermine si les {multiFields} doivent s'afficher dans la fenêtre de document étendue. Dans la plupart des cas, les champs multiples sont les mêmes que les champs d'origine. Cette option est uniquement disponible lorsque le paramètre ''searchFieldsFromSource'' est désactivé.", + "discover.advancedSettings.docTableHideTimeColumnText": "Permet de masquer la colonne ''Time'' dans Discover et dans toutes les recherches enregistrées des tableaux de bord.", + "discover.advancedSettings.docTableHideTimeColumnTitle": "Masquer la colonne ''Time''", + "discover.advancedSettings.fieldsPopularLimitText": "Les N champs les plus populaires à afficher", + "discover.advancedSettings.fieldsPopularLimitTitle": "Limite de champs populaires", + "discover.advancedSettings.maxDocFieldsDisplayedText": "Le nombre maximal de champs renvoyés dans la colonne de document", + "discover.advancedSettings.maxDocFieldsDisplayedTitle": "Nombre maximal de champs de document affichés", + "discover.advancedSettings.sampleSizeText": "Le nombre de lignes à afficher dans le tableau", + "discover.advancedSettings.sampleSizeTitle": "Nombre de lignes", + "discover.advancedSettings.searchOnPageLoadText": "Détermine si une recherche est exécutée lors du premier chargement de Discover. Ce paramètre n'a pas d'effet lors du chargement d’une recherche enregistrée.", + "discover.advancedSettings.searchOnPageLoadTitle": "Recherche au chargement de la page", + "discover.advancedSettings.sortDefaultOrderText": "Détermine le sens de tri par défaut pour les modèles d'indexation temporelle dans l’application Discover.", + "discover.advancedSettings.sortDefaultOrderTitle": "Sens de tri par défaut", + "discover.advancedSettings.sortOrderAsc": "Croissant", + "discover.advancedSettings.sortOrderDesc": "Décroissant", + "discover.backToTopLinkText": "Revenir en haut de la page.", + "discover.badge.readOnly.text": "Lecture seule", + "discover.badge.readOnly.tooltip": "Impossible d’enregistrer les recherches", + "discover.bucketIntervalTooltip": "Cet intervalle crée {bucketsDescription} pour permettre l’affichage dans la plage temporelle sélectionnée, il a donc été redimensionné vers {bucketIntervalDescription}.", + "discover.bucketIntervalTooltip.tooLargeBucketsText": "des compartiments trop volumineux", + "discover.bucketIntervalTooltip.tooManyBucketsText": "un trop grand nombre de compartiments", + "discover.clearSelection": "Effacer la sélection", + "discover.context.breadcrumb": "Documents relatifs", + "discover.context.contextOfTitle": "Les documents relatifs à #{anchorId}", + "discover.context.failedToLoadAnchorDocumentDescription": "Échec de chargement du document ancré", + "discover.context.failedToLoadAnchorDocumentErrorDescription": "Le document ancré n’a pas pu être chargé.", + "discover.context.invalidTieBreakerFiledSetting": "Paramètre de champ de départage non valide", + "discover.context.loadButtonLabel": "Charger", + "discover.context.loadingDescription": "Chargement...", + "discover.context.newerDocumentsAriaLabel": "Nombre de documents plus récents", + "discover.context.newerDocumentsDescription": "documents plus récents", + "discover.context.newerDocumentsWarning": "Seuls {docCount} documents plus récents que le document ancré ont été trouvés.", + "discover.context.newerDocumentsWarningZero": "Aucun document plus récent que le document ancré n'a été trouvé.", + "discover.context.olderDocumentsAriaLabel": "Nombre de documents plus anciens", + "discover.context.olderDocumentsDescription": "documents plus anciens", + "discover.context.olderDocumentsWarning": "Seuls {docCount} documents plus anciens que le document ancré ont été trouvés.", + "discover.context.olderDocumentsWarningZero": "Aucun document plus ancien que le document ancré n'a été trouvé.", + "discover.context.reloadPageDescription.reloadOrVisitTextMessage": "Veuillez recharger le document ou revenir à la liste pour sélectionner un document ancré valide.", + "discover.context.unableToLoadAnchorDocumentDescription": "Impossible de charger le document ancré", + "discover.context.unableToLoadDocumentDescription": "Impossible de charger les documents", + "discover.controlColumnHeader": "Colonne de commande", + "discover.copyToClipboardJSON": "Copier les documents dans le presse-papiers (JSON)", + "discover.discoverBreadcrumbTitle": "Discover", + "discover.discoverDefaultSearchSessionName": "Discover", + "discover.discoverDescription": "Explorez vos données de manière interactive en interrogeant et en filtrant des documents bruts.", + "discover.discoverSubtitle": "Recherchez et obtenez des informations.", + "discover.discoverTitle": "Discover", + "discover.doc.couldNotFindDocumentsDescription": "Aucun document ne correspond à cet ID.", + "discover.doc.failedToExecuteQueryDescription": "Impossible d'exécuter la recherche", + "discover.doc.failedToLocateDocumentDescription": "Document introuvable", + "discover.doc.loadingDescription": "Chargement…", + "discover.doc.somethingWentWrongDescription": "Index {indexName} manquant.", + "discover.doc.somethingWentWrongDescriptionAddon": "Veuillez vérifier que cet index existe.", + "discover.docTable.documentsNavigation": "Navigation dans les documents", + "discover.docTable.limitedSearchResultLabel": "Limité à {resultCount} résultats. Veuillez affiner votre recherche.", + "discover.docTable.noResultsTitle": "Aucun résultat trouvé.", + "discover.docTable.rows": "lignes", + "discover.docTable.rowsPerPage": "Lignes par page : {pageSize}", + "discover.docTable.tableHeader.documentHeader": "Document", + "discover.docTable.tableHeader.moveColumnLeftButtonAriaLabel": "Déplacer la colonne {columnName} vers la gauche", + "discover.docTable.tableHeader.moveColumnLeftButtonTooltip": "Déplacer la colonne vers la gauche", + "discover.docTable.tableHeader.moveColumnRightButtonAriaLabel": "Déplacer la colonne {columnName} vers la droite", + "discover.docTable.tableHeader.moveColumnRightButtonTooltip": "Déplacer la colonne vers la droite", + "discover.docTable.tableHeader.removeColumnButtonAriaLabel": "Supprimer la colonne {columnName}", + "discover.docTable.tableHeader.removeColumnButtonTooltip": "Supprimer la colonne", + "discover.docTable.tableHeader.sortByColumnAscendingAriaLabel": "Trier la colonne {columnName} par ordre croissant", + "discover.docTable.tableHeader.sortByColumnDescendingAriaLabel": "Trier la colonne {columnName} par ordre décroissant", + "discover.docTable.tableHeader.sortByColumnUnsortedAriaLabel": "Arrêter de trier la colonne {columnName}", + "discover.docTable.tableRow.detailHeading": "Document développé", + "discover.docTable.tableRow.filterForValueButtonAriaLabel": "Filtrer sur la valeur", + "discover.docTable.tableRow.filterForValueButtonTooltip": "Filtrer sur la valeur", + "discover.docTable.tableRow.filterOutValueButtonAriaLabel": "Exclure la valeur", + "discover.docTable.tableRow.filterOutValueButtonTooltip": "Exclure la valeur", + "discover.docTable.tableRow.toggleRowDetailsButtonAriaLabel": "Afficher/Masquer les détails de la ligne", + "discover.docTable.tableRow.viewSingleDocumentLinkText": "Afficher un seul document", + "discover.docTable.tableRow.viewSurroundingDocumentsLinkText": "Afficher les documents alentour", + "discover.docTable.totalDocuments": "{totalDocuments} documents", + "discover.documentsAriaLabel": "Documents", + "discover.docViews.json.jsonTitle": "JSON", + "discover.docViews.table.filterForFieldPresentButtonAriaLabel": "Filtrer sur le champ", + "discover.docViews.table.filterForFieldPresentButtonTooltip": "Filtrer sur le champ", + "discover.docViews.table.filterForValueButtonAriaLabel": "Filtrer sur la valeur", + "discover.docViews.table.filterForValueButtonTooltip": "Filtrer sur la valeur", + "discover.docViews.table.filterOutValueButtonAriaLabel": "Exclure la valeur", + "discover.docViews.table.filterOutValueButtonTooltip": "Exclure la valeur", + "discover.docViews.table.scoreSortWarningTooltip": "Filtrez sur _score pour pouvoir récupérer les valeurs correspondantes.", + "discover.docViews.table.tableTitle": "Tableau", + "discover.docViews.table.toggleColumnInTableButtonAriaLabel": "Afficher/Masquer la colonne dans le tableau", + "discover.docViews.table.toggleColumnInTableButtonTooltip": "Afficher/Masquer la colonne dans le tableau", + "discover.docViews.table.toggleFieldDetails": "Afficher/Masquer les détails du champ", + "discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "Impossible de filtrer sur les champs méta", + "discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "Impossible de filtrer sur les champs scriptés", + "discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "Il est impossible d’effectuer une recherche sur des champs non indexés.", + "discover.embeddable.inspectorRequestDataTitle": "Données", + "discover.embeddable.inspectorRequestDescription": "Cette requête interroge Elasticsearch afin de récupérer les données pour la recherche.", + "discover.embeddable.search.displayName": "recherche", + "discover.field.mappingConflict": "Ce champ est défini avec plusieurs types (chaîne, entier, etc.) dans les différents index qui correspondent à ce modèle. Vous pouvez toujours utiliser ce champ conflictuel, mais il sera indisponible pour les fonctions qui nécessitent que Kibana en connaisse le type. Pour corriger ce problème, vous devrez réindexer vos données.", + "discover.field.mappingConflict.title": "Conflit de mapping", + "discover.field.title": "{fieldName} ({fieldDisplayName})", + "discover.fieldChooser.detailViews.emptyStringText": "Chaîne vide", + "discover.fieldChooser.detailViews.existsInRecordsText": "Existe dans {value} / {totalValue} enregistrements", + "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "Exclure le {field} : \"{value}\"", + "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "Filtrer sur le {field} : \"{value}\"", + "discover.fieldChooser.detailViews.valueOfRecordsText": "{value}/{totalValue} enregistrements", + "discover.fieldChooser.discoverField.actions": "Actions", + "discover.fieldChooser.discoverField.addButtonAriaLabel": "Ajouter {field} au tableau", + "discover.fieldChooser.discoverField.addFieldTooltip": "Ajouter le champ en tant que colonne", + "discover.fieldChooser.discoverField.deleteFieldLabel": "Supprimer le champ du modèle d'indexation", + "discover.fieldChooser.discoverField.editFieldLabel": "Modifier le champ du modèle d'indexation", + "discover.fieldChooser.discoverField.fieldTopValuesLabel": "Top 5 des valeurs", + "discover.fieldChooser.discoverField.multiField": "champ multiple", + "discover.fieldChooser.discoverField.multiFields": "Champs multiples", + "discover.fieldChooser.discoverField.multiFieldTooltipContent": "Les champs multiples peuvent avoir plusieurs valeurs.", + "discover.fieldChooser.discoverField.name": "Champ", + "discover.fieldChooser.discoverField.removeButtonAriaLabel": "Supprimer {field} du tableau", + "discover.fieldChooser.discoverField.removeFieldTooltip": "Supprimer le champ du tableau", + "discover.fieldChooser.discoverField.value": "Valeur", + "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage": "L'analyse n'est pas disponible pour les champs géométriques.", + "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage": "L'analyse n'est pas disponible pour les champs d'objet.", + "discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage": "Ce champ est présent dans votre mapping Elasticsearch, mais pas dans les {hitsLength} documents affichés dans le tableau des documents. Cependant, vous pouvez toujours le consulter ou effectuer une recherche dessus.", + "discover.fieldChooser.fieldFilterButtonLabel": "Filtrer par type", + "discover.fieldChooser.fieldsMobileButtonLabel": "Champs", + "discover.fieldChooser.filter.aggregatableLabel": "Regroupable", + "discover.fieldChooser.filter.availableFieldsTitle": "Champs disponibles", + "discover.fieldChooser.filter.fieldSelectorLabel": "Sélection des options du filtre {id}", + "discover.fieldChooser.filter.filterByTypeLabel": "Filtrer par type", + "discover.fieldChooser.filter.indexAndFieldsSectionAriaLabel": "Index et champs", + "discover.fieldChooser.filter.popularTitle": "Populaire", + "discover.fieldChooser.filter.searchableLabel": "Interrogeable", + "discover.fieldChooser.filter.selectedFieldsTitle": "Champs sélectionnés", + "discover.fieldChooser.filter.toggleButton.any": "tout", + "discover.fieldChooser.filter.toggleButton.no": "non", + "discover.fieldChooser.filter.toggleButton.yes": "oui", + "discover.fieldChooser.filter.typeLabel": "Type", + "discover.fieldChooser.indexPatterns.actionsPopoverLabel": "Paramètres du modèle d'indexation", + "discover.fieldChooser.indexPatterns.addFieldButton": "Ajouter un champ au modèle d'indexation", + "discover.fieldChooser.indexPatterns.manageFieldButton": "Gérer les champs du modèle d'indexation", + "discover.fieldChooser.searchPlaceHolder": "Rechercher les noms de champs", + "discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel": "Masquer les paramètres de filtre de champs", + "discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel": "Afficher les paramètres de filtre de champs", + "discover.fieldChooser.visualizeButton.label": "Visualiser", + "discover.fieldList.flyoutBackIcon": "Retour", + "discover.fieldList.flyoutHeading": "Liste des champs", + "discover.fieldNameIcons.booleanAriaLabel": "Champ booléen", + "discover.fieldNameIcons.conflictFieldAriaLabel": "Champ conflictuel", + "discover.fieldNameIcons.dateFieldAriaLabel": "Champ de date", + "discover.fieldNameIcons.geoPointFieldAriaLabel": "Champ de point géographique", + "discover.fieldNameIcons.geoShapeFieldAriaLabel": "Champ de forme géométrique", + "discover.fieldNameIcons.ipAddressFieldAriaLabel": "Champ d'adresse IP", + "discover.fieldNameIcons.murmur3FieldAriaLabel": "Champ Murmur3", + "discover.fieldNameIcons.nestedFieldAriaLabel": "Champ imbriqué", + "discover.fieldNameIcons.numberFieldAriaLabel": "Champ numérique", + "discover.fieldNameIcons.sourceFieldAriaLabel": "Champ source", + "discover.fieldNameIcons.stringFieldAriaLabel": "Champ de chaîne", + "discover.fieldNameIcons.unknownFieldAriaLabel": "Champ inconnu", + "discover.grid.documentHeader": "Document", + "discover.grid.filterFor": "Filtrer sur", + "discover.grid.filterForAria": "Filtrer sur cette {value}", + "discover.grid.filterOut": "Exclure", + "discover.grid.filterOutAria": "Exclure cette {value}", + "discover.grid.flyout.documentNavigation": "Navigation dans le document", + "discover.grid.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.", + "discover.grid.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.", + "discover.grid.flyout.toastFilterAdded": "Le filtre a été ajouté.", + "discover.grid.tableRow.detailHeading": "Document développé", + "discover.grid.tableRow.viewSingleDocumentLinkTextSimple": "Document unique", + "discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple": "Documents relatifs", + "discover.grid.tableRow.viewText": "Afficher :", + "discover.grid.viewDoc": "Afficher/Masquer les détails de la boîte de dialogue", + "discover.helpMenu.appName": "Discover", + "discover.hideChart": "Masquer le graphique", + "discover.histogramOfFoundDocumentsAriaLabel": "Histogramme des documents détectés", + "discover.hitCountSpinnerAriaLabel": "Nombre final de résultats toujours en chargement", + "discover.hitsPluralTitle": "{formattedHits} {hits, plural, one {résultat} other {résultats}}", + "discover.howToSeeOtherMatchingDocumentsDescription": "Voici les {sampleSize} premiers documents correspondant à votre recherche. Veuillez affiner celle-ci pour en voir plus.", + "discover.howToSeeOtherMatchingDocumentsDescriptionGrid": "Voici les {sampleSize} premiers documents correspondant à votre recherche. Veuillez affiner celle-ci pour en voir plus.", + "discover.inspectorRequestDataTitleChart": "Données du graphique", + "discover.inspectorRequestDataTitleDocuments": "Documents", + "discover.inspectorRequestDataTitleTotalHits": "Nombre total de résultats", + "discover.inspectorRequestDescriptionChart": "Cette requête interroge Elasticsearch afin de récupérer les données d'agrégation pour le graphique.", + "discover.inspectorRequestDescriptionDocument": "Cette requête interroge Elasticsearch afin de récupérer les documents.", + "discover.inspectorRequestDescriptionTotalHits": "Cette requête interroge Elasticsearch afin de récupérer le nombre total de résultats.", + "discover.json.codeEditorAriaLabel": "Affichage JSON en lecture seule d’un document Elasticsearch", + "discover.json.copyToClipboardLabel": "Copier dans le presse-papiers", + "discover.loadingChartResults": "Chargement du graphique", + "discover.loadingDocuments": "Chargement des documents", + "discover.loadingJSON": "Chargement de JSON", + "discover.loadingResults": "Chargement des résultats", + "discover.localMenu.inspectTitle": "Inspecter", + "discover.localMenu.localMenu.newSearchTitle": "Nouveau", + "discover.localMenu.localMenu.optionsTitle": "Options", + "discover.localMenu.newSearchDescription": "Nouvelle recherche", + "discover.localMenu.openInspectorForSearchDescription": "Ouvrir l'inspecteur de recherche", + "discover.localMenu.openSavedSearchDescription": "Ouvrir une recherche enregistrée", + "discover.localMenu.openTitle": "Ouvrir", + "discover.localMenu.optionsDescription": "Options", + "discover.localMenu.saveSaveSearchObjectType": "recherche", + "discover.localMenu.saveSearchDescription": "Enregistrer la recherche", + "discover.localMenu.saveTitle": "Enregistrer", + "discover.localMenu.shareSearchDescription": "Partager la recherche", + "discover.localMenu.shareTitle": "Partager", + "discover.noResults.adjustFilters": "Modifiez les filtres.", + "discover.noResults.adjustSearch": "Modifiez la requête.", + "discover.noResults.expandYourTimeRangeTitle": "Étendre la plage temporelle", + "discover.noResults.queryMayNotMatchTitle": "Essayez de rechercher sur une période plus longue.", + "discover.noResults.searchExamples.noResultsBecauseOfError": "Une erreur s’est produite lors de la récupération des résultats de recherche.", + "discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle": "Aucun résultat ne correspond à vos critères de recherche.", + "discover.noResultsFound": "Aucun résultat trouvé.", + "discover.notifications.invalidTimeRangeText": "La plage temporelle spécifiée n'est pas valide (de : \"{from}\" à \"{to}\").", + "discover.notifications.invalidTimeRangeTitle": "Plage temporelle non valide", + "discover.notifications.notSavedSearchTitle": "La recherche \"{savedSearchTitle}\" n'a pas été enregistrée.", + "discover.notifications.savedSearchTitle": "La recherche \"{savedSearchTitle}\" a été enregistrée.", + "discover.partialHits": "≥ {formattedHits} {hits, plural, one {résultat} other {résultats}}", + "discover.reloadSavedSearchButton": "Réinitialiser la recherche", + "discover.removeColumnLabel": "Supprimer la colonne", + "discover.rootBreadcrumb": "Discover", + "discover.savedSearch.savedObjectName": "Recherche enregistrée", + "discover.searchGenerationWithDescription": "Tableau généré par la recherche {searchTitle}", + "discover.searchGenerationWithDescriptionGrid": "Tableau généré par la recherche {searchTitle} ({searchDescription})", + "discover.searchingTitle": "Recherche", + "discover.selectColumnHeader": "Sélectionner la colonne", + "discover.selectedDocumentsNumber": "{nr} documents sélectionnés", + "discover.showAllDocuments": "Afficher tous les documents", + "discover.showChart": "Afficher le graphique", + "discover.showErrorMessageAgain": "Afficher le message d'erreur", + "discover.showSelectedDocumentsOnly": "Afficher uniquement les documents sélectionnés", + "discover.skipToBottomButtonLabel": "Atteindre la fin du tableau", + "discover.sourceViewer.errorMessage": "Impossible de récupérer les données pour le moment. Actualisez l'onglet et réessayez.", + "discover.sourceViewer.errorMessageTitle": "Une erreur s'est produite.", + "discover.sourceViewer.refresh": "Actualiser", + "discover.toggleSidebarAriaLabel": "Afficher/Masquer la barre latérale", + "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "Gérer les recherches", + "discover.topNav.openSearchPanel.noSearchesFoundDescription": "Aucune recherche correspondante trouvée.", + "discover.topNav.openSearchPanel.openSearchTitle": "Ouvrir une recherche", + "discover.topNav.optionsPopover.currentViewMode": "{viewModeLabel} : {currentViewMode}", + "discover.uninitializedRefreshButtonText": "Actualiser les données", + "discover.uninitializedText": "Saisissez une requête, ajoutez quelques filtres, ou cliquez simplement sur Actualiser afin d’extraire les résultats pour la requête en cours.", + "discover.uninitializedTitle": "Commencer la recherche", + "embeddableApi.addPanel.createNewDefaultOption": "Créer", + "embeddableApi.addPanel.displayName": "Ajouter un panneau", + "embeddableApi.addPanel.noMatchingObjectsMessage": "Aucun objet correspondant trouvé.", + "embeddableApi.addPanel.savedObjectAddedToContainerSuccessMessageTitle": "{savedObjectName} a été ajouté.", + "embeddableApi.addPanel.Title": "Ajouter depuis la bibliothèque", + "embeddableApi.attributeService.saveToLibraryError": "Une erreur s'est produite lors de l'enregistrement. Erreur : {errorMessage}", + "embeddableApi.contextMenuTrigger.description": "Un menu contextuel cliquable dans l’angle supérieur droit du panneau.", + "embeddableApi.contextMenuTrigger.title": "Menu contextuel", + "embeddableApi.customizePanel.action.displayName": "Modifier le titre du panneau", + "embeddableApi.customizePanel.modal.cancel": "Annuler", + "embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleFormRowLabel": "Titre du panneau", + "embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleInputAriaLabel": "Entrez un titre personnalisé pour le panneau.", + "embeddableApi.customizePanel.modal.optionsMenuForm.resetCustomDashboardButtonLabel": "Réinitialiser", + "embeddableApi.customizePanel.modal.saveButtonTitle": "Enregistrer", + "embeddableApi.customizePanel.modal.showTitle": "Afficher le titre du panneau", + "embeddableApi.customizeTitle.optionsMenuForm.panelTitleFormRowLabel": "Titre du panneau", + "embeddableApi.customizeTitle.optionsMenuForm.panelTitleInputAriaLabel": "Les modifications apportées à cette entrée sont appliquées immédiatement. Appuyez sur Entrée pour quitter.", + "embeddableApi.customizeTitle.optionsMenuForm.resetCustomDashboardButtonLabel": "Réinitialiser le titre", + "embeddableApi.errors.embeddableFactoryNotFound": "Impossible de charger {type}. Veuillez effectuer une mise à niveau vers la distribution par défaut d'Elasticsearch et de Kibana avec la licence appropriée.", + "embeddableApi.errors.paneldoesNotExist": "Panneau introuvable", + "embeddableApi.helloworld.displayName": "bonjour", + "embeddableApi.panel.dashboardPanelAriaLabel": "Panneau du tableau de bord", + "embeddableApi.panel.editPanel.displayName": "Modifier {value}", + "embeddableApi.panel.editTitleAriaLabel": "Cliquez pour modifier le titre : {title}", + "embeddableApi.panel.enhancedDashboardPanelAriaLabel": "Panneau du tableau de bord : {title}", + "embeddableApi.panel.inspectPanel.displayName": "Inspecter", + "embeddableApi.panel.inspectPanel.untitledEmbeddableFilename": "sans titre", + "embeddableApi.panel.labelAborted": "Annulé", + "embeddableApi.panel.labelError": "Erreur", + "embeddableApi.panel.optionsMenu.panelOptionsButtonAriaLabel": "Options de panneau", + "embeddableApi.panel.optionsMenu.panelOptionsButtonEnhancedAriaLabel": "Options de panneau pour {title}", + "embeddableApi.panel.placeholderTitle": "[Aucun titre]", + "embeddableApi.panel.removePanel.displayName": "Supprimer du tableau de bord", + "embeddableApi.panelBadgeTrigger.description": "Des actions apparaissent dans la barre de titre lorsqu'un élément pouvant être intégré est chargé dans un panneau.", + "embeddableApi.panelBadgeTrigger.title": "Badges du panneau", + "embeddableApi.panelNotificationTrigger.description": "Les actions apparaissent dans l’angle supérieur droit des panneaux.", + "embeddableApi.panelNotificationTrigger.title": "Notifications du panneau", + "embeddableApi.samples.contactCard.displayName": "carte de visite", + "embeddableApi.samples.filterableContainer.displayName": "tableau de bord filtrable", + "embeddableApi.samples.filterableEmbeddable.displayName": "filtrable", + "embeddableApi.selectRangeTrigger.description": "Une plage de valeurs sur la visualisation", + "embeddableApi.selectRangeTrigger.title": "Sélection de la plage", + "embeddableApi.valueClickTrigger.description": "Un point de données cliquable sur la visualisation", + "embeddableApi.valueClickTrigger.title": "Clic unique", + "esQuery.kql.errors.endOfInputText": "fin de l'entrée", + "esQuery.kql.errors.fieldNameText": "nom du champ", + "esQuery.kql.errors.literalText": "littéral", + "esQuery.kql.errors.syntaxError": "{expectedList} attendu, mais {foundInput} détecté.", + "esQuery.kql.errors.valueText": "valeur", + "esQuery.kql.errors.whitespaceText": "whitespace", + "esUi.cronEditor.cronDaily.fieldHour.textAtLabel": "À", + "esUi.cronEditor.cronDaily.fieldTimeLabel": "Heure", + "esUi.cronEditor.cronDaily.hourSelectLabel": "Heure", + "esUi.cronEditor.cronDaily.minuteSelectLabel": "Minute", + "esUi.cronEditor.cronHourly.fieldMinute.textAtLabel": "À", + "esUi.cronEditor.cronHourly.fieldTimeLabel": "Minute", + "esUi.cronEditor.cronMonthly.fieldDateLabel": "Date", + "esUi.cronEditor.cronMonthly.fieldHour.textAtLabel": "À", + "esUi.cronEditor.cronMonthly.fieldTimeLabel": "Heure", + "esUi.cronEditor.cronMonthly.hourSelectLabel": "Heure", + "esUi.cronEditor.cronMonthly.minuteSelectLabel": "Minute", + "esUi.cronEditor.cronMonthly.textOnTheLabel": "Le", + "esUi.cronEditor.cronWeekly.fieldDateLabel": "Jour", + "esUi.cronEditor.cronWeekly.fieldHour.textAtLabel": "À", + "esUi.cronEditor.cronWeekly.fieldTimeLabel": "Heure", + "esUi.cronEditor.cronWeekly.hourSelectLabel": "Heure", + "esUi.cronEditor.cronWeekly.minuteSelectLabel": "Minute", + "esUi.cronEditor.cronWeekly.textOnLabel": "Le", + "esUi.cronEditor.cronYearly.fieldDate.textOnTheLabel": "Le", + "esUi.cronEditor.cronYearly.fieldDateLabel": "Date", + "esUi.cronEditor.cronYearly.fieldHour.textAtLabel": "À", + "esUi.cronEditor.cronYearly.fieldMonth.textInLabel": "En", + "esUi.cronEditor.cronYearly.fieldMonthLabel": "Mois", + "esUi.cronEditor.cronYearly.fieldTimeLabel": "Heure", + "esUi.cronEditor.cronYearly.hourSelectLabel": "Heure", + "esUi.cronEditor.cronYearly.minuteSelectLabel": "Minute", + "esUi.cronEditor.day.friday": "vendredi", + "esUi.cronEditor.day.monday": "lundi", + "esUi.cronEditor.day.saturday": "samedi", + "esUi.cronEditor.day.sunday": "dimanche", + "esUi.cronEditor.day.thursday": "jeudi", + "esUi.cronEditor.day.tuesday": "mardi", + "esUi.cronEditor.day.wednesday": "mercredi", + "esUi.cronEditor.fieldFrequencyLabel": "Fréquence", + "esUi.cronEditor.month.april": "avril", + "esUi.cronEditor.month.august": "août", + "esUi.cronEditor.month.december": "décembre", + "esUi.cronEditor.month.february": "février", + "esUi.cronEditor.month.january": "janvier", + "esUi.cronEditor.month.july": "juillet", + "esUi.cronEditor.month.june": "juin", + "esUi.cronEditor.month.march": "mars", + "esUi.cronEditor.month.may": "mai", + "esUi.cronEditor.month.november": "novembre", + "esUi.cronEditor.month.october": "octobre", + "esUi.cronEditor.month.september": "septembre", + "esUi.cronEditor.textEveryLabel": "Chaque", + "esUi.forms.comboBoxField.placeHolderText": "Saisir, puis appuyer sur \"ENTRÉE\"", + "esUi.forms.fieldValidation.indexNameInvalidCharactersError": "Le nom de l'index contient {characterListLength, plural, one {le caractère non valide} other {les caractères non valides}} {characterList}.", + "esUi.forms.fieldValidation.indexNameSpacesError": "Le nom de l'index ne peut pas contenir d'espaces.", + "esUi.forms.fieldValidation.indexNameStartsWithDotError": "Le nom de l'index ne peut pas commencer par un point (.).", + "esUi.forms.fieldValidation.indexPatternInvalidCharactersError": "Le modèle d'indexation contient {characterListLength, plural, one {le caractère non valide} other {les caractères non valides}} {characterList}.", + "esUi.forms.fieldValidation.indexPatternSpacesError": "Le modèle d'indexation ne peut pas contenir d'espaces.", + "esUi.formWizard.backButtonLabel": "Retour", + "esUi.formWizard.nextButtonLabel": "Suivant", + "esUi.formWizard.saveButtonLabel": "Enregistrer", + "esUi.formWizard.savingButtonLabel": "Enregistrement en cours...", + "esUi.validation.string.invalidJSONError": "JSON non valide", + "expressionError.errorComponent.description": "Échec de l'expression avec le message :", + "expressionError.errorComponent.title": "Oups ! Échec de l'expression", + "expressionError.renderer.debug.displayName": "Débogage", + "expressionError.renderer.debug.helpDescription": "Présenter une sortie de débogage formatée {JSON}", + "expressionError.renderer.error.displayName": "Informations sur l'erreur", + "expressionError.renderer.error.helpDescription": "Présenter les données de l'erreur d'une manière utile pour les utilisateurs", + "expressionImage.functions.image.args.dataurlHelpText": "L'{URL} {https} ou l'{URL} de données {BASE64} d'une image.", + "expressionImage.functions.image.args.modeHelpText": "{contain} affiche l'image entière, mise à l’échelle. {cover} remplit le conteneur avec l'image, en rognant les côtés ou le bas si besoin. {stretch} redimensionne la hauteur et la largeur de l'image pour correspondre à 100 % du conteneur.", + "expressionImage.functions.image.invalidImageModeErrorMessage": "\"mode\" doit être défini sur \"{contain}\", \"{cover}\" ou \"{stretch}\".", + "expressionImage.functions.imageHelpText": "Affiche une image. Spécifiez une ressource d'image sous la forme d'une {URL} de données {BASE64}, ou saisissez une sous-expression.", + "expressionImage.renderer.image.displayName": "Image", + "expressionImage.renderer.image.helpDescription": "Présenter une image", + "expressionMetric.functions.metric.args.labelFontHelpText": "Les propriétés de la police {CSS} pour l'étiquette. Par exemple, {FONT_FAMILY} ou {FONT_WEIGHT}.", + "expressionMetric.functions.metric.args.labelHelpText": "Le texte décrivant l'indicateur.", + "expressionMetric.functions.metric.args.metricFontHelpText": "Les propriétés de la police {CSS} pour l'indicateur. Par exemple, {FONT_FAMILY} ou {FONT_WEIGHT}.", + "expressionMetric.functions.metric.args.metricFormatHelpText": "Une chaîne de format {NUMERALJS}. Par exemple, {example1} ou {example2}.", + "expressionMetric.functions.metricHelpText": "Affiche un nombre sur une étiquette.", + "expressionMetric.renderer.metric.displayName": "Indicateur", + "expressionMetric.renderer.metric.helpDescription": "Présenter un nombre sur une étiquette", + "expressionRepeatImage.error.repeatImage.missingMaxArgument": "{maxArgument} doit être défini si un {emptyImageArgument} est fourni.", + "expressionRepeatImage.functions.repeatImage.args.emptyImageHelpText": "Comble la différence entre les paramètres {CONTEXT} et {maxArg} pour l'élément avec cette image. Spécifiez une ressource d'image sous la forme d'une {URL} de données {BASE64}, ou saisissez une sous-expression.", + "expressionRepeatImage.functions.repeatImage.args.imageHelpText": "L'image à répéter. Spécifiez une ressource d'image sous la forme d'une {URL} de données {BASE64}, ou saisissez une sous-expression.", + "expressionRepeatImage.functions.repeatImage.args.maxHelpText": "Le nombre maximal de fois que l'image peut être répétée.", + "expressionRepeatImage.functions.repeatImage.args.sizeHelpText": "La hauteur ou largeur maximale de l'image, en pixels. Lorsque l'image est plus haute que large, cette fonction limite la hauteur.", + "expressionRepeatImage.functions.repeatImageHelpText": "Configure un élément de répétition d’image.", + "expressionRepeatImage.renderer.repeatImage.displayName": "Répétition d’image", + "expressionRepeatImage.renderer.repeatImage.helpDescription": "Présenter une répétition d’image basique", + "expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "Une image d'arrière-plan facultative à révéler. Spécifiez une ressource d'image sous la forme d’une {URL} de données \"{BASE64}\", ou saisissez une sous-expression.", + "expressionRevealImage.functions.revealImage.args.imageHelpText": "L'image à révéler. Spécifiez une ressource d'image sous la forme d'une {URL} de données {BASE64}, ou saisissez une sous-expression.", + "expressionRevealImage.functions.revealImage.args.originHelpText": "La position à laquelle démarrer le remplissage de l'image. Par exemple, {list} ou {end}.", + "expressionRevealImage.functions.revealImage.invalidImageUrl": "URL d'image non valide : \"{imageUrl}\".", + "expressionRevealImage.functions.revealImage.invalidPercentErrorMessage": "Valeur non valide : \"{percent}\". Le pourcentage doit être compris entre 0 et 1.", + "expressionRevealImage.functions.revealImageHelpText": "Configure un élément de révélation d'image.", + "expressionRevealImage.renderer.revealImage.displayName": "Révélation d'image", + "expressionRevealImage.renderer.revealImage.helpDescription": "Révèle un pourcentage d'une image pour concevoir un graphique à jauge personnalisé.", + "expressions.defaultErrorRenderer.errorTitle": "Erreur dans la visualisation", + "expressions.execution.functionDisabled": "Fonction {fnName} désactivée.", + "expressions.execution.functionNotFound": "Fonction {fnName} introuvable.", + "expressions.functions.createTable.args.idsHelpText": "ID de colonne à générer dans l'ordre de position. L'ID représente la clé dans la ligne.", + "expressions.functions.createTable.args.nameHelpText": "Noms de colonne à générer dans l'ordre de position. Ces noms n'ont pas besoin d'être uniques et, en l’absence de noms, les ID sont utilisés par défaut.", + "expressions.functions.createTable.args.rowCountText": "Le nombre de lignes vides à ajouter au tableau, pour y attribuer une valeur plus tard", + "expressions.functions.createTableHelpText": "Crée une table de données avec une liste de colonnes, et une ou plusieurs lignes vides. Pour générer les lignes, utilisez {mapColumnFn} ou {mathColumnFn}.", + "expressions.functions.cumulativeSum.args.byHelpText": "Colonne par laquelle diviser le calcul de la somme cumulée", + "expressions.functions.cumulativeSum.args.inputColumnIdHelpText": "Colonne pour laquelle calculer la somme cumulée", + "expressions.functions.cumulativeSum.args.outputColumnIdHelpText": "Colonne dans laquelle stocker le résultat de la somme cumulée", + "expressions.functions.cumulativeSum.args.outputColumnNameHelpText": "Nom de la colonne dans laquelle stocker le résultat de la somme cumulée", + "expressions.functions.cumulativeSum.help": "Calcule la somme cumulée d'une colonne dans un tableau de données.", + "expressions.functions.derivative.args.byHelpText": "Colonne par laquelle diviser le calcul de la dérivée", + "expressions.functions.derivative.args.inputColumnIdHelpText": "Colonne pour laquelle calculer la dérivée", + "expressions.functions.derivative.args.outputColumnIdHelpText": "Colonne dans laquelle stocker le résultat de la dérivée", + "expressions.functions.derivative.args.outputColumnNameHelpText": "Nom de la colonne dans laquelle stocker le résultat de la dérivée", + "expressions.functions.derivative.help": "Calcule la dérivée d'une colonne dans un tableau de données.", + "expressions.functions.font.args.alignHelpText": "L'alignement horizontal du texte.", + "expressions.functions.font.args.colorHelpText": "La couleur du texte.", + "expressions.functions.font.args.familyHelpText": "Une chaîne de police Internet {css} acceptable", + "expressions.functions.font.args.italicHelpText": "Mettre le texte en italique ?", + "expressions.functions.font.args.lHeightHelpText": "La hauteur de la ligne en pixels", + "expressions.functions.font.args.sizeHelpText": "La taille de la police en pixels", + "expressions.functions.font.args.underlineHelpText": "Souligner le texte ?", + "expressions.functions.font.args.weightHelpText": "L’épaisseur de la police. Par exemple, {list} ou {end}.", + "expressions.functions.font.invalidFontWeightErrorMessage": "Épaisseur de police non valide : \"{weight}\"", + "expressions.functions.font.invalidTextAlignmentErrorMessage": "Alignement du texte non valide : \"{align}\"", + "expressions.functions.fontHelpText": "Créez un style de police.", + "expressions.functions.mapColumn.args.copyMetaFromHelpText": "Si défini, l'objet méta de l'ID de colonne spécifié est copié dans la colonne cible spécifiée. Si la colonne n'existe pas, un échec silencieux se produit.", + "expressions.functions.mapColumn.args.expressionHelpText": "Une expression qui est exécutée sur chaque ligne, fournie avec un contexte {DATATABLE} de ligne unique et retournant la valeur de la cellule.", + "expressions.functions.mapColumn.args.idHelpText": "Un ID facultatif de la colonne de résultat. Si aucun ID n'est fourni, l'ID est récupéré de la colonne existante par l'argument de nom fourni. S'il n'existe pas encore de colonne à ce nom, une nouvelle colonne avec ce nom et un ID identique est ajoutée au tableau.", + "expressions.functions.mapColumn.args.nameHelpText": "Le nom de la colonne produite. Les noms n'ont pas besoin d'être uniques.", + "expressions.functions.mapColumnHelpText": "Ajoute une colonne calculée comme le résultat d'autres colonnes. Des modifications ne sont apportées que si des arguments sont fournis. Voir également {alterColumnFn} et {staticColumnFn}.", + "expressions.functions.math.args.expressionHelpText": "Une expression {TINYMATH} évaluée. Voir {TINYMATH_URL}.", + "expressions.functions.math.args.onErrorHelpText": "Si l’évaluation {TINYMATH} échoue ou renvoie NaN, la valeur de retour est spécifiée par onError. Lors de la ''génération'', une exception est levée, terminant l'exécution de l'expression (par défaut).", + "expressions.functions.math.emptyDatatableErrorMessage": "Table de données vide", + "expressions.functions.math.emptyExpressionErrorMessage": "Expression vide", + "expressions.functions.math.executionFailedErrorMessage": "Échec d'exécution de l'expression mathématique. Vérifiez les noms des colonnes.", + "expressions.functions.math.tooManyResultsErrorMessage": "Les expressions doivent retourner un nombre unique. Essayez d'englober votre expression dans {mean} ou {sum}.", + "expressions.functions.mathColumn.args.copyMetaFromHelpText": "Si défini, l'objet méta de l'ID de colonne spécifié est copié dans la colonne cible spécifiée. Si la colonne n'existe pas, un échec silencieux se produit.", + "expressions.functions.mathColumn.args.idHelpText": "ID de la colonne produite. Doit être unique.", + "expressions.functions.mathColumn.args.nameHelpText": "Le nom de la colonne produite. Les noms n'ont pas besoin d'être uniques.", + "expressions.functions.mathColumn.arrayValueError": "Impossible de réaliser le calcul sur les valeurs du tableau à {name}", + "expressions.functions.mathColumn.uniqueIdError": "L'ID doit être unique.", + "expressions.functions.mathHelpText": "Interprète une expression mathématique {TINYMATH} à l'aide d'un {TYPE_NUMBER} ou d'une {DATATABLE} en tant que {CONTEXT}. Les colonnes {DATATABLE} peuvent être recherchées d’après leur nom. Si {CONTEXT} est un nombre, il est disponible en tant que {value}.", + "expressions.functions.movingAverage.args.byHelpText": "Colonne par laquelle diviser le calcul de la moyenne mobile", + "expressions.functions.movingAverage.args.inputColumnIdHelpText": "Colonne pour laquelle calculer la moyenne mobile", + "expressions.functions.movingAverage.args.outputColumnIdHelpText": "Colonne dans laquelle stocker le résultat de la moyenne mobile", + "expressions.functions.movingAverage.args.outputColumnNameHelpText": "Nom de la colonne dans laquelle stocker le résultat de la moyenne mobile", + "expressions.functions.movingAverage.args.windowHelpText": "La taille de la fenêtre à \"faire glisser\" le long de l'histogramme.", + "expressions.functions.movingAverage.help": "Calcule la moyenne mobile d'une colonne dans un tableau de données.", + "expressions.functions.overallMetric.args.byHelpText": "Colonne par laquelle diviser le calcul général", + "expressions.functions.overallMetric.args.inputColumnIdHelpText": "Colonne pour laquelle calculer l’indicateur général", + "expressions.functions.overallMetric.args.outputColumnIdHelpText": "Colonne dans laquelle stocker le résultat de l'indicateur général", + "expressions.functions.overallMetric.args.outputColumnNameHelpText": "Nom de la colonne dans laquelle stocker le résultat de l’indicateur général", + "expressions.functions.overallMetric.help": "Calcule la somme, le minimum, le maximum ou la moyenne générale d'une colonne dans un tableau de données.", + "expressions.functions.overallMetric.metricHelpText": "Indicateur à calculer", + "expressions.functions.seriesCalculations.columnConflictMessage": "L'ID de colonne de sortie {columnId} existe déjà. Veuillez choisir un autre ID de colonne.", + "expressions.functions.theme.args.defaultHelpText": "La valeur par défaut lorsqu’aucune information de thème n’est disponible.", + "expressions.functions.theme.args.variableHelpText": "Nom de la variable de thème à lire.", + "expressions.functions.themeHelpText": "Lit un paramètre de thème.", + "expressions.functions.uiSetting.args.default": "La valeur par défaut utilisée lorsque le paramètre n’est pas défini.", + "expressions.functions.uiSetting.args.parameter": "Le nom du paramètre.", + "expressions.functions.uiSetting.error.kibanaRequest": "Une requête Kibana est nécessaire pour obtenir les paramètres de l'interface utilisateur sur le serveur. Veuillez fournir un objet de requête pour les paramètres d'exécution de l'expression.", + "expressions.functions.uiSetting.error.parameter": "Paramètre \"{parameter}\" non valide.", + "expressions.functions.uiSetting.help": "Renvoie une valeur de paramètre de l'interface utilisateur.", + "expressions.functions.var.help": "Met à jour le contexte général de Kibana.", + "expressions.functions.var.name.help": "Spécifiez le nom de la variable.", + "expressions.functions.varset.help": "Met à jour le contexte général de Kibana.", + "expressions.functions.varset.name.help": "Spécifiez le nom de la variable.", + "expressions.functions.varset.val.help": "Spécifiez la valeur de la variable. Sinon, le contexte d'entrée est utilisé.", + "expressions.types.number.fromStringConversionErrorMessage": "Impossible de cataloguer la chaîne \"{string}\" en nombre", + "expressionShape.functions.progress.args.barColorHelpText": "La couleur de la barre d'arrière-plan.", + "expressionShape.functions.progress.args.barWeightHelpText": "L'épaisseur de la barre d'arrière-plan.", + "expressionShape.functions.progress.args.fontHelpText": "Les propriétés de la police {CSS} pour l'étiquette. Par exemple, {FONT_FAMILY} ou {FONT_WEIGHT}.", + "expressionShape.functions.progress.args.labelHelpText": "Pour afficher ou masquer l'étiquette, utilisez {BOOLEAN_TRUE} ou {BOOLEAN_FALSE}. Vous pouvez également spécifier une chaîne à afficher en tant qu'étiquette.", + "expressionShape.functions.progress.args.maxHelpText": "La valeur maximale de l'élément de progression.", + "expressionShape.functions.progress.args.shapeHelpText": "Sélectionnez {list} ou {end}.", + "expressionShape.functions.progress.args.valueColorHelpText": "La couleur de la barre de progression.", + "expressionShape.functions.progress.args.valueWeightHelpText": "L'épaisseur de la barre de progression.", + "expressionShape.functions.progress.invalidMaxValueErrorMessage": "Valeur {arg} non valide : \"{max, number}\" ; \"{arg}\" doit être supérieur à 0.", + "expressionShape.functions.progress.invalidValueErrorMessage": "Valeur non valide : \"{value, number}\". La valeur doit être comprise entre 0 et {max, number}.", + "expressionShape.functions.progressHelpText": "Configure un élément de progression.", + "expressionShape.functions.shape.args.borderHelpText": "Une couleur {SVG} pour la bordure de la forme.", + "expressionShape.functions.shape.args.borderWidthHelpText": "L'épaisseur de la bordure.", + "expressionShape.functions.shape.args.fillHelpText": "Une couleur {SVG} de remplissage de la forme.", + "expressionShape.functions.shape.args.maintainAspectHelpText": "Conserver le rapport d'origine de la forme ?", + "expressionShape.functions.shape.args.shapeHelpText": "Choisissez une forme.", + "expressionShape.functions.shape.invalidShapeErrorMessage": "Valeur non valide : \"{shape}\". Cette forme n'existe pas.", + "expressionShape.functions.shapeHelpText": "Crée une forme.", + "expressionShape.renderer.progress.displayName": "Progression", + "expressionShape.renderer.progress.helpDescription": "Présenter une progression basique", + "expressionShape.renderer.shape.displayName": "Forme", + "expressionShape.renderer.shape.helpDescription": "Présenter une forme basique", + "fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "Format numérique", + "fieldFormats.advancedSettings.format.bytesFormatText": "{numeralFormatLink} par défaut pour le format \"octets\"", + "fieldFormats.advancedSettings.format.bytesFormatTitle": "Format octets", + "fieldFormats.advancedSettings.format.currencyFormat.numeralFormatLinkText": "Format numérique", + "fieldFormats.advancedSettings.format.currencyFormatText": "{numeralFormatLink} par défaut pour le format \"devise\"", + "fieldFormats.advancedSettings.format.currencyFormatTitle": "Format devise", + "fieldFormats.advancedSettings.format.defaultTypeMapText": "Mapping du nom du format à utiliser par défaut pour chaque type de champ. Le format {defaultFormat} est utilisé lorsque le type de champ n'est pas mentionné explicitement.", + "fieldFormats.advancedSettings.format.defaultTypeMapTitle": "Nom du format du type de champ", + "fieldFormats.advancedSettings.format.formattingLocale.numeralLanguageLinkText": "Langage numérique", + "fieldFormats.advancedSettings.format.formattingLocaleText": "Paramètre régional {numeralLanguageLink}", + "fieldFormats.advancedSettings.format.formattingLocaleTitle": "Paramètre régional de format", + "fieldFormats.advancedSettings.format.numberFormat.numeralFormatLinkText": "Format numérique", + "fieldFormats.advancedSettings.format.numberFormatText": "{numeralFormatLink} par défaut pour le format \"nombre\"", + "fieldFormats.advancedSettings.format.numberFormatTitle": "Format nombre", + "fieldFormats.advancedSettings.format.percentFormat.numeralFormatLinkText": "Format numérique", + "fieldFormats.advancedSettings.format.percentFormatText": "{numeralFormatLink} par défaut pour le format \"pourcentage\"", + "fieldFormats.advancedSettings.format.percentFormatTitle": "Format pourcentage", + "fieldFormats.advancedSettings.shortenFieldsText": "Raccourcir les champs longs, par exemple f.b.baz plutôt que foo.bar.baz", + "fieldFormats.advancedSettings.shortenFieldsTitle": "Raccourcir les champs", + "fieldFormats.boolean.title": "Booléen", + "fieldFormats.bytes.title": "Octets", + "fieldFormats.color.title": "Couleur", + "fieldFormats.date_nanos.title": "Date nanos", + "fieldFormats.date.title": "Date", + "fieldFormats.duration.inputFormats.days": "Jours", + "fieldFormats.duration.inputFormats.hours": "Heures", + "fieldFormats.duration.inputFormats.microseconds": "Microsecondes", + "fieldFormats.duration.inputFormats.milliseconds": "Millisecondes", + "fieldFormats.duration.inputFormats.minutes": "Minutes", + "fieldFormats.duration.inputFormats.months": "Mois", + "fieldFormats.duration.inputFormats.nanoseconds": "Nanosecondes", + "fieldFormats.duration.inputFormats.picoseconds": "Picosecondes", + "fieldFormats.duration.inputFormats.seconds": "Secondes", + "fieldFormats.duration.inputFormats.weeks": "Semaines", + "fieldFormats.duration.inputFormats.years": "Années", + "fieldFormats.duration.negativeLabel": "moins", + "fieldFormats.duration.outputFormats.asDays": "Jours", + "fieldFormats.duration.outputFormats.asDays.short": "j", + "fieldFormats.duration.outputFormats.asHours": "Heures", + "fieldFormats.duration.outputFormats.asHours.short": "h", + "fieldFormats.duration.outputFormats.asMilliseconds": "Millisecondes", + "fieldFormats.duration.outputFormats.asMilliseconds.short": "ms", + "fieldFormats.duration.outputFormats.asMinutes": "Minutes", + "fieldFormats.duration.outputFormats.asMinutes.short": "min", + "fieldFormats.duration.outputFormats.asMonths": "Mois", + "fieldFormats.duration.outputFormats.asMonths.short": "mois", + "fieldFormats.duration.outputFormats.asSeconds": "Secondes", + "fieldFormats.duration.outputFormats.asSeconds.short": "s", + "fieldFormats.duration.outputFormats.asWeeks": "Semaines", + "fieldFormats.duration.outputFormats.asWeeks.short": "w", + "fieldFormats.duration.outputFormats.asYears": "Années", + "fieldFormats.duration.outputFormats.asYears.short": "y", + "fieldFormats.duration.outputFormats.humanize.approximate": "Lisible par l'humain (approximatif)", + "fieldFormats.duration.outputFormats.humanize.precise": "Lisible par l'humain (précis)", + "fieldFormats.duration.title": "Durée", + "fieldFormats.histogram.title": "Histogramme", + "fieldFormats.ip.title": "Adresse IP", + "fieldFormats.number.title": "Nombre", + "fieldFormats.percent.title": "Pourcentage", + "fieldFormats.relative_date.title": "Date relative", + "fieldFormats.static_lookup.title": "Recherche statique", + "fieldFormats.string.emptyLabel": "(vide)", + "fieldFormats.string.title": "Chaîne", + "fieldFormats.string.transformOptions.base64": "Décodage Base64", + "fieldFormats.string.transformOptions.lower": "Minuscule", + "fieldFormats.string.transformOptions.none": "- Aucune -", + "fieldFormats.string.transformOptions.short": "Points courts", + "fieldFormats.string.transformOptions.title": "Initiale majuscule", + "fieldFormats.string.transformOptions.upper": "Majuscule", + "fieldFormats.string.transformOptions.url": "Décodage paramètre URL", + "fieldFormats.truncated_string.title": "Chaîne tronquée", + "fieldFormats.url.title": "Url", + "fieldFormats.url.types.audio": "Audio", + "fieldFormats.url.types.img": "Image", + "fieldFormats.url.types.link": "Lien", + "flot.pie.unableToDrawLabelsInsideCanvasErrorMessage": "Impossible de dessiner un graphique avec les étiquettes contenues dans la toile", + "flot.time.aprLabel": "Avr", + "flot.time.augLabel": "Août", + "flot.time.decLabel": "Déc", + "flot.time.febLabel": "Févr", + "flot.time.friLabel": "Ven", + "flot.time.janLabel": "Jan", + "flot.time.julLabel": "Juil", + "flot.time.junLabel": "Juin", + "flot.time.marLabel": "Mars", + "flot.time.mayLabel": "Mai", + "flot.time.monLabel": "Lun", + "flot.time.novLabel": "Nov", + "flot.time.octLabel": "Oct", + "flot.time.satLabel": "Sam", + "flot.time.sepLabel": "Sept", + "flot.time.sunLabel": "Dim", + "flot.time.thuLabel": "Jeu", + "flot.time.tueLabel": "Mar", + "flot.time.wedLabel": "Mer", + "home.addData.addDataButtonLabel": "Ajouter vos données", + "home.addData.sampleDataButtonLabel": "Utiliser un exemple de données", + "home.addData.sectionTitle": "Ajoutez vos données pour commencer", + "home.addData.text": "Vous avez plusieurs options pour commencer à exploiter vos données. Vous pouvez collecter des données à partir d'une application ou d'un service, ou bien charger un fichier. Et si vous n'êtes pas encore prêt à utiliser vos propres données, utilisez notre exemple d’ensemble de données.", + "home.breadcrumbs.homeTitle": "Accueil", + "home.dataManagementDisableCollection": " Pour mettre fin à la collecte, ", + "home.dataManagementDisableCollectionLink": "désactivez les données d'utilisation ici.", + "home.dataManagementDisclaimerPrivacy": "Pour en savoir plus sur la manière dont les données d'utilisation nous aident à gérer et à améliorer nos produits et nos services, consultez notre ", + "home.dataManagementDisclaimerPrivacyLink": "Déclaration de confidentialité.", + "home.dataManagementEnableCollection": " Pour démarrer la collecte, ", + "home.dataManagementEnableCollectionLink": "activez les données d'utilisation ici.", + "home.exploreButtonLabel": "Explorer par moi-même", + "home.exploreYourDataDescription": "Une fois toutes les étapes terminées, vous êtes prêt à explorer vos données.", + "home.header.title": "Bienvenue chez vous", + "home.letsStartDescription": "Ajoutez des données à votre cluster depuis n’importe quelle source, puis analysez-les et visualisez-les en temps réel. Utilisez nos solutions pour définir des recherches, observer votre écosystème et vous protéger contre les menaces de sécurité.", + "home.letsStartTitle": "Commencez par ajouter vos données", + "home.loadTutorials.requestFailedErrorMessage": "Échec de la requête avec le code de statut : {status}", + "home.loadTutorials.unableToLoadErrorMessage": "Impossible de charger les tutoriels", + "home.manageData.devToolsButtonLabel": "Outils de développement", + "home.manageData.sectionTitle": "Gestion", + "home.manageData.stackManagementButtonLabel": "Gestion de la suite", + "home.pageTitle": "Accueil", + "home.recentlyAccessed.recentlyViewedTitle": "Récemment consulté", + "home.sampleData.ecommerceSpec.ordersTitle": "[e-commerce] Commandes", + "home.sampleData.ecommerceSpec.promotionTrackingTitle": "[e-commerce] Suivi des promotions", + "home.sampleData.ecommerceSpec.revenueDashboardDescription": "Analyser des commandes et revenus e-commerce", + "home.sampleData.ecommerceSpec.revenueDashboardTitle": "[e-commerce] Tableau de bord des revenus", + "home.sampleData.ecommerceSpec.soldProductsPerDayTitle": "[e-commerce] Produits vendus par jour", + "home.sampleData.ecommerceSpecDescription": "Exemple de données, visualisations et tableaux de bord pour le suivi des commandes d’e-commerce.", + "home.sampleData.ecommerceSpecTitle": "Exemple de commandes d’e-commerce", + "home.sampleData.flightsSpec.airportConnectionsTitle": "[Vols] Connexions aéroportuaires (passage au-dessus d'un aéroport)", + "home.sampleData.flightsSpec.delayBucketsTitle": "[Vols] Compartiments retard", + "home.sampleData.flightsSpec.delaysAndCancellationsTitle": "[Vols] Retards et annulations", + "home.sampleData.flightsSpec.departuresCountMapTitle": "[Vols] Mappage du nombre de départs", + "home.sampleData.flightsSpec.destinationWeatherTitle": "[Vols] Météo à la destination", + "home.sampleData.flightsSpec.flightLogTitle": "[Vols] Journal de vol", + "home.sampleData.flightsSpec.globalFlightDashboardDescription": "Analyser des données aéroportuaires factices pour ES-Air, Logstash Airways, Kibana Airlines et JetBeats", + "home.sampleData.flightsSpec.globalFlightDashboardTitle": "[Vols] Tableau de bord des vols internationaux", + "home.sampleData.flightsSpecDescription": "Exemple de données, de visualisations et de tableaux de bord pour le monitoring des itinéraires de vol.", + "home.sampleData.flightsSpecTitle": "Exemple de données aéroportuaires", + "home.sampleData.logsSpec.bytesDistributionTitle": "[Logs] Distribution des octets", + "home.sampleData.logsSpec.discoverTitle": "[Logs] Visites", + "home.sampleData.logsSpec.goalsTitle": "[Logs] Objectifs", + "home.sampleData.logsSpec.heatmapTitle": "[Logs] Carte thermique des visiteurs uniques", + "home.sampleData.logsSpec.hostVisitsBytesTableTitle": "[Logs] Tableau des hôtes, visites et octets", + "home.sampleData.logsSpec.responseCodesOverTimeTitle": "[Logs] Codes de réponse sur la durée + annotations", + "home.sampleData.logsSpec.sourceAndDestinationSankeyChartTitle": "[Logs] Diagramme de Sankey source-destination", + "home.sampleData.logsSpec.visitorsMapTitle": "[Logs] Mappage des visiteurs", + "home.sampleData.logsSpec.webTrafficDescription": "Analyser des données de log factices relatives au trafic Internet du site d'Elastic", + "home.sampleData.logsSpec.webTrafficTitle": "[Logs] Trafic Internet", + "home.sampleData.logsSpecDescription": "Exemple de données, de visualisations et de tableaux de bord pour le monitoring des logs Internet.", + "home.sampleData.logsSpecTitle": "Exemple de logs Internet", + "home.sampleDataSet.installedLabel": "{name} installé", + "home.sampleDataSet.unableToInstallErrorMessage": "Impossible d'installer l'exemple d’ensemble de données : {name}.", + "home.sampleDataSet.unableToLoadListErrorMessage": "Impossible de charger la liste des exemples d’ensemble de données", + "home.sampleDataSet.unableToUninstallErrorMessage": "Impossible de désinstaller l'exemple d’ensemble de données : {name}.", + "home.sampleDataSet.uninstalledLabel": "{name} désinstallé", + "home.sampleDataSetCard.addButtonAriaLabel": "Ajouter {datasetName}", + "home.sampleDataSetCard.addButtonLabel": "Ajouter des données", + "home.sampleDataSetCard.addingButtonAriaLabel": "Ajout de {datasetName}", + "home.sampleDataSetCard.addingButtonLabel": "Ajout", + "home.sampleDataSetCard.dashboardLinkLabel": "Tableau de bord", + "home.sampleDataSetCard.default.addButtonAriaLabel": "Ajouter {datasetName}", + "home.sampleDataSetCard.default.addButtonLabel": "Ajouter des données", + "home.sampleDataSetCard.default.unableToVerifyErrorMessage": "Impossible de vérifier le statut de l'ensemble de données. Erreur : {statusMsg}.", + "home.sampleDataSetCard.removeButtonAriaLabel": "Supprimer {datasetName}", + "home.sampleDataSetCard.removeButtonLabel": "Supprimer", + "home.sampleDataSetCard.removingButtonAriaLabel": "Suppression de {datasetName}", + "home.sampleDataSetCard.removingButtonLabel": "Suppression", + "home.sampleDataSetCard.viewDataButtonAriaLabel": "Consulter {datasetName}", + "home.sampleDataSetCard.viewDataButtonLabel": "Consulter les données", + "home.solutionsSection.sectionTitle": "Choisir votre solution", + "home.tryButtonLabel": "Ajouter des données", + "home.tutorial.addDataToKibanaTitle": "Ajouter des données", + "home.tutorial.card.sampleDataDescription": "Commencez votre exploration de Kibana avec ces ensembles de données \"en un clic\".", + "home.tutorial.card.sampleDataTitle": "Exemple de données", + "home.tutorial.elasticCloudButtonLabel": "Elastic Cloud", + "home.tutorial.instruction_variant.fleet": "Elastic APM (bêta) dans Fleet", + "home.tutorial.instructionSet.checkStatusButtonLabel": "Vérifier le statut", + "home.tutorial.instructionSet.customizeLabel": "Personnaliser les extraits de code", + "home.tutorial.instructionSet.noDataLabel": "Aucune donnée trouvée", + "home.tutorial.instructionSet.statusCheckTitle": "Vérification du statut", + "home.tutorial.instructionSet.successLabel": "Réussite", + "home.tutorial.introduction.betaLabel": "Version bêta", + "home.tutorial.introduction.imageAltDescription": "Capture d'écran du tableau de bord principal.", + "home.tutorial.introduction.viewButtonLabel": "Consulter les champs exportés", + "home.tutorial.noTutorialLabel": "Tutoriel {tutorialId} introuvable", + "home.tutorial.savedObject.addedLabel": "Les objets enregistrés {savedObjectsLength} ont bien été ajoutés.", + "home.tutorial.savedObject.confirmButtonLabel": "Confirmer l'écrasement", + "home.tutorial.savedObject.defaultButtonLabel": "Charger des objets Kibana", + "home.tutorial.savedObject.installLabel": "Importe un modèle d'indexation, des visualisations et des tableaux de bord prédéfinis.", + "home.tutorial.savedObject.installStatusLabel": "{overwriteErrorsLength} sur {savedObjectsLength} objets existent déjà. Cliquez sur \"Confirmer l'écrasement\" pour importer et écraser les objets existants. Toute modification apportée aux objets sera perdue.", + "home.tutorial.savedObject.loadTitle": "Charger des objets Kibana", + "home.tutorial.savedObject.requestFailedErrorMessage": "Échec de la requête. Erreur : {message}.", + "home.tutorial.savedObject.unableToAddErrorMessage": "Impossible d'ajouter {errorsLength} sur {savedObjectsLength} objets Kibana. Erreur : {errorMessage}.", + "home.tutorial.selectionLegend": "Type de déploiement", + "home.tutorial.selfManagedButtonLabel": "Autogéré", + "home.tutorial.tabs.sampleDataTitle": "Exemple de données", + "home.tutorial.unexpectedStatusCheckStateErrorDescription": "État de vérification du statut {statusCheckState} inattendu", + "home.tutorial.unhandledInstructionTypeErrorDescription": "Type d'instructions {visibleInstructions} non pris en charge", + "home.tutorialDirectory.featureCatalogueDescription": "Importez des données à partir d'applications et de services populaires.", + "home.tutorialDirectory.featureCatalogueTitle": "Ajouter des données", + "home.tutorials.activemqLogs.artifacts.dashboards.linkLabel": "Événements d'audit ActiveMQ", + "home.tutorials.activemqLogs.longDescription": "Collectez les logs ActiveMQ avec Filebeat. [En savoir plus]({learnMoreLink}).", + "home.tutorials.activemqLogs.nameTitle": "Logs ActiveMQ", + "home.tutorials.activemqLogs.shortDescription": "Collectez les logs ActiveMQ avec Filebeat.", + "home.tutorials.activemqMetrics.artifacts.application.label": "Discover", + "home.tutorials.activemqMetrics.longDescription": "Le module Metricbeat ''activemq'' récupère les indicateurs de monitoring depuis les instances ActiveMQ. [En savoir plus]({learnMoreLink}).", + "home.tutorials.activemqMetrics.nameTitle": "Indicateurs ActiveMQ", + "home.tutorials.activemqMetrics.shortDescription": "Récupérez les indicateurs de monitoring depuis les instances ActiveMQ.", + "home.tutorials.aerospikeMetrics.artifacts.application.label": "Discover", + "home.tutorials.aerospikeMetrics.longDescription": "Le module Metricbeat ''aerospike'' récupère les indicateurs internes d’Aerospike. [En savoir plus]({learnMoreLink}).", + "home.tutorials.aerospikeMetrics.nameTitle": "Indicateurs Aerospike", + "home.tutorials.aerospikeMetrics.shortDescription": "Récupérez les indicateurs internes depuis le serveur Aerospike.", + "home.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs Apache", + "home.tutorials.apacheLogs.longDescription": "Le module Filebeat ''apache'' analyse les logs d'accès et d'erreurs créés par le serveur HTTP Apache. [En savoir plus]({learnMoreLink}).", + "home.tutorials.apacheLogs.nameTitle": "Logs Apache", + "home.tutorials.apacheLogs.shortDescription": "Collectez et analysez les logs d'accès et d'erreurs créés par le serveur HTTP Apache.", + "home.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Apache", + "home.tutorials.apacheMetrics.longDescription": "Le module Metricbeat ''apache'' récupère les indicateurs internes depuis le serveur HTTP Apache 2. [En savoir plus]({learnMoreLink}).", + "home.tutorials.apacheMetrics.nameTitle": "Indicateurs Apache", + "home.tutorials.apacheMetrics.shortDescription": "Récupérez les indicateurs internes depuis le serveur HTTP Apache 2.", + "home.tutorials.auditbeat.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.auditbeat.longDescription": "Utilisez Auditbeat pour collecter les données d'audit de vos hôtes. Ces données incluent les processus, utilisateurs, connexions, informations de socket, accès aux fichiers et bien plus encore. [En savoir plus]({learnMoreLink}).", + "home.tutorials.auditbeat.nameTitle": "Auditbeat", + "home.tutorials.auditbeat.shortDescription": "Collectez des données d'audit de vos hôtes.", + "home.tutorials.auditdLogs.artifacts.dashboards.linkLabel": "Événements d'audit", + "home.tutorials.auditdLogs.longDescription": "Le module collecte et analyse les logs du démon d'audit (''auditd'') [En savoir plus]({learnMoreLink}).", + "home.tutorials.auditdLogs.nameTitle": "Logs auditd", + "home.tutorials.auditdLogs.shortDescription": "Collectez les logs du démon Linux auditd.", + "home.tutorials.awsLogs.artifacts.dashboards.linkLabel": "Tableau de bord du log d'accès au serveur AWS S3", + "home.tutorials.awsLogs.longDescription": "Collectez des logs AWS en les exportant vers un compartiment S3 configuré avec la notification SQS [En savoir plus]({learnMoreLink}).", + "home.tutorials.awsLogs.nameTitle": "Logs AWS S3", + "home.tutorials.awsLogs.shortDescription": "Collectez des logs AWS à partir du compartiment S3 avec Filebeat.", + "home.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs AWS", + "home.tutorials.awsMetrics.longDescription": "Le module Metricbeat ''aws'' récupère les indicateurs de monitoring depuis les API AWS et Cloudwatch. [En savoir plus]({learnMoreLink}).", + "home.tutorials.awsMetrics.nameTitle": "Indicateurs AWS", + "home.tutorials.awsMetrics.shortDescription": "Récupérez les indicateurs de monitoring pour les instances EC2 depuis les API AWS et Cloudwatch.", + "home.tutorials.azureLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs Azure", + "home.tutorials.azureLogs.longDescription": "Le module Filebeat ''azure'' collecte les logs d’activité et d’audit Azure. [Learn more]({learnMoreLink}).", + "home.tutorials.azureLogs.nameTitle": "Logs Azure", + "home.tutorials.azureLogs.shortDescription": "Collectez les logs d’activité et d’audit Azure.", + "home.tutorials.azureMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Azure", + "home.tutorials.azureMetrics.longDescription": "Le module Metricbeat ''azure'' récupère les indicateurs de monitoring Azure. [En savoir plus]({learnMoreLink}).", + "home.tutorials.azureMetrics.nameTitle": "Indicateurs Azure", + "home.tutorials.azureMetrics.shortDescription": "Récupérez les indicateurs de monitoring Azure.", + "home.tutorials.barracudaLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.barracudaLogs.longDescription": "Ce module permet de recevoir les logs Barracuda Web Application Firewall par le biais de Syslog ou d’un fichier. [Learn more]({learnMoreLink}).", + "home.tutorials.barracudaLogs.nameTitle": "Logs Barracuda", + "home.tutorials.barracudaLogs.shortDescription": "Collectez les logs Barracuda Web Application Firewall par le biais de Syslog ou d’un fichier.", + "home.tutorials.bluecoatLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.bluecoatLogs.longDescription": "Ce module permet de recevoir les logs Blue Coat Director par le biais de Syslog ou d’un fichier. [Learn more]({learnMoreLink}).", + "home.tutorials.bluecoatLogs.nameTitle": "Logs Blue Coat Director", + "home.tutorials.bluecoatLogs.shortDescription": "Collectez les logs Blue Coat Director par le biais de Syslog ou d'un fichier.", + "home.tutorials.cefLogs.artifacts.dashboards.linkLabel": "Tableau de bord d'aperçu du réseau CEF", + "home.tutorials.cefLogs.longDescription": "Ce module permet de recevoir des données Common Event Format (CEF) par le biais de Syslog. Lorsque des messages sont reçus par le biais du protocole Syslog, l'entrée Syslog analyse l'en-tête et définit la valeur d'horodatage. Puis le processeur est appliqué pour analyser les données CEF. Les données décodées sont alors écrites dans un champ objet ''cef''. Enfin, tous les champs Elastic Common Schema (ECS) ayant des correspondances CEF sont renseignés. [En savoir plus]({learnMoreLink}).", + "home.tutorials.cefLogs.nameTitle": "Logs CEF", + "home.tutorials.cefLogs.shortDescription": "Collectez des logs Common Event Format (CEF) par le biais de Syslog.", + "home.tutorials.cephMetrics.artifacts.application.label": "Discover", + "home.tutorials.cephMetrics.longDescription": "Le module Metricbeat ''ceph'' récupère les indicateurs internes depuis Ceph. [En savoir plus]({learnMoreLink}).", + "home.tutorials.cephMetrics.nameTitle": "Indicateurs Ceph", + "home.tutorials.cephMetrics.shortDescription": "Récupérez les indicateurs internes depuis le serveur Ceph.", + "home.tutorials.checkpointLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.checkpointLogs.longDescription": "Il s'agit d'un module pour les logs de pare-feu Check Point. Il prend en charge les logs de l’exportateur de journaux au format Syslog. [Learn more]({learnMoreLink}).", + "home.tutorials.checkpointLogs.nameTitle": "Logs Check Point", + "home.tutorials.checkpointLogs.shortDescription": "Collectez des logs de pare-feu Check Point.", + "home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "Tableau de bord de pare-feu ASA", + "home.tutorials.ciscoLogs.longDescription": "Il s'agit d'un module pour les logs de dispositifs réseau Cisco (ASA, FTD, IOS, Nexus). Il inclut les ensembles de fichiers suivants pour la réception des logs par le biais de Syslog ou d'un ficher. [En savoir plus]({learnMoreLink}).", + "home.tutorials.ciscoLogs.nameTitle": "Logs Cisco", + "home.tutorials.ciscoLogs.shortDescription": "Collectez les logs de dispositifs réseau Cisco par le biais de Syslog ou d'un fichier.", + "home.tutorials.cloudwatchLogs.longDescription": "Collectez les logs Cloudwatch en déployant Functionbeat à des fins d'exécution en tant que fonction AWS Lambda. [En savoir plus]({learnMoreLink}).", + "home.tutorials.cloudwatchLogs.nameTitle": "Logs Cloudwatch AWS", + "home.tutorials.cloudwatchLogs.shortDescription": "Collectez les logs Cloudwatch avec Functionbeat.", + "home.tutorials.cockroachdbMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs CockroachDB", + "home.tutorials.cockroachdbMetrics.longDescription": "Le module Metricbeat ''cockroachbd'' récupère les indicateurs de monitoring depuis CockroachDB. [En savoir plus]({learnMoreLink}).", + "home.tutorials.cockroachdbMetrics.nameTitle": "Indicateurs CockroachDB", + "home.tutorials.cockroachdbMetrics.shortDescription": "Récupérez les indicateurs de monitoring depuis le serveur CockroachDB.", + "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.auditbeatInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.auditbeatInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.auditbeatInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.auditbeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.auditbeatInstructions.install.debTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({linkUrl}).", + "home.tutorials.common.auditbeatInstructions.install.debTextPre": "Vous utilisez Auditbeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.auditbeatInstructions.install.debTitle": "Télécharger et installer Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.osxTextPre": "Vous utilisez Auditbeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.auditbeatInstructions.install.osxTitle": "Télécharger et installer Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({linkUrl}).", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPre": "Vous utilisez Auditbeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.auditbeatInstructions.install.rpmTitle": "Télécharger et installer Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPost": "Modifiez les paramètres sous {propertyName} dans le fichier {auditbeatPath} afin de pointer vers votre installation Elasticsearch.", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPre": "Vous utilisez Auditbeat pour la première fois ? Consultez le [guide de démarrage rapide]({guideLinkUrl}).\n 1. Téléchargez le fichier .zip Auditbeat pour Windows via la page [Télécharger]({auditbeatLinkUrl}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Auditbeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Dans l'invite PowerShell, exécutez les commandes suivantes afin d'installer Auditbeat en tant que service Windows.", + "home.tutorials.common.auditbeatInstructions.install.windowsTitle": "Télécharger et installer Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.debTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.auditbeatInstructions.start.debTitle": "Lancer Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.osxTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.auditbeatInstructions.start.osxTitle": "Lancer Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.rpmTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.auditbeatInstructions.start.rpmTitle": "Lancer Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.windowsTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.auditbeatInstructions.start.windowsTitle": "Lancer Auditbeat", + "home.tutorials.common.auditbeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.auditbeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue.", + "home.tutorials.common.auditbeatStatusCheck.successText": "Des données ont été reçues.", + "home.tutorials.common.auditbeatStatusCheck.text": "Vérifier que des données sont reçues d'Auditbeat", + "home.tutorials.common.auditbeatStatusCheck.title": "Statut", + "home.tutorials.common.cloudInstructions.passwordAndResetLink": "Où {passwordTemplate} est le mot de passe de l'utilisateur ''elastic''.\\{#config.cloud.profileUrl\\}\n Mot de passe oublié ? [Réinitialiser dans Elastic Cloud](\\{config.cloud.baseUrl\\}\\{config.cloud.profileUrl\\}).\n \\{/config.cloud.profileUrl\\}", + "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.filebeatEnableInstructions.debTextPost": "Modifiez les paramètres dans le fichier ''/etc/filebeat/modules.d/{moduleName}.yml''.", + "home.tutorials.common.filebeatEnableInstructions.debTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.filebeatEnableInstructions.osxTextPost": "Modifiez les paramètres dans le fichier ''modules.d/{moduleName}.yml''.", + "home.tutorials.common.filebeatEnableInstructions.osxTextPre": "Dans le répertoire d'installation, exécutez la commande suivante :", + "home.tutorials.common.filebeatEnableInstructions.osxTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.filebeatEnableInstructions.rpmTextPost": "Modifiez les paramètres dans le fichier ''/etc/filebeat/modules.d/{moduleName}.yml''.", + "home.tutorials.common.filebeatEnableInstructions.rpmTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPost": "Modifiez les paramètres dans le fichier ''modules.d/{moduleName}.yml''.", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPre": "Dans le dossier {path}, exécutez la commande suivante :", + "home.tutorials.common.filebeatEnableInstructions.windowsTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.filebeatInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.filebeatInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.filebeatInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.filebeatInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.filebeatInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.filebeatInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.filebeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.filebeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.filebeatInstructions.install.debTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({linkUrl}).", + "home.tutorials.common.filebeatInstructions.install.debTextPre": "Vous utilisez Filebeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.filebeatInstructions.install.debTitle": "Télécharger et installer Filebeat", + "home.tutorials.common.filebeatInstructions.install.osxTextPre": "Vous utilisez Filebeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.filebeatInstructions.install.osxTitle": "Télécharger et installer Filebeat", + "home.tutorials.common.filebeatInstructions.install.rpmTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({linkUrl}).", + "home.tutorials.common.filebeatInstructions.install.rpmTextPre": "Vous utilisez Filebeat pour la première fois ? Consultez le [guide de démarrage rapide]({linkUrl}).", + "home.tutorials.common.filebeatInstructions.install.rpmTitle": "Télécharger et installer Filebeat", + "home.tutorials.common.filebeatInstructions.install.windowsTextPost": "Modifiez les paramètres sous {propertyName} dans le fichier {filebeatPath} afin de pointer vers votre installation Elasticsearch.", + "home.tutorials.common.filebeatInstructions.install.windowsTextPre": "Vous utilisez Filebeat pour la première fois ? Consultez le [guide de démarrage rapide]({guideLinkUrl}).\n 1. Téléchargez le fichier .zip Filebeat pour Windows via la page [Télécharger]({filebeatLinkUrl}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Filebeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Dans l'invite PowerShell, exécutez les commandes suivantes afin d'installer Filebeat en tant que service Windows.", + "home.tutorials.common.filebeatInstructions.install.windowsTitle": "Télécharger et installer Filebeat", + "home.tutorials.common.filebeatInstructions.start.debTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.filebeatInstructions.start.debTitle": "Lancer Filebeat", + "home.tutorials.common.filebeatInstructions.start.osxTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.filebeatInstructions.start.osxTitle": "Lancer Filebeat", + "home.tutorials.common.filebeatInstructions.start.rpmTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.filebeatInstructions.start.rpmTitle": "Lancer Filebeat", + "home.tutorials.common.filebeatInstructions.start.windowsTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.filebeatInstructions.start.windowsTitle": "Lancer Filebeat", + "home.tutorials.common.filebeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.filebeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue de ce module.", + "home.tutorials.common.filebeatStatusCheck.successText": "Des données ont été reçues de ce module.", + "home.tutorials.common.filebeatStatusCheck.text": "Vérifier que des données sont reçues du module Filebeat \"{moduleName}\"", + "home.tutorials.common.filebeatStatusCheck.title": "Statut du module", + "home.tutorials.common.functionbeat.cloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.functionbeat.premCloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.functionbeat.premInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.functionbeatAWSInstructions.textPost": "Où '''' et '''' sont vos informations d'identification et ''us-east-1'' est la région désirée.", + "home.tutorials.common.functionbeatAWSInstructions.textPre": "Définissez vos informations d'identification AWS dans l'environnement :", + "home.tutorials.common.functionbeatAWSInstructions.title": "Définir des informations d'identification AWS", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "Où '''' est le nom du groupe de logs à importer et '''' un nom de compartiment S3 valide pour la mise en œuvre du déploiement de Functionbeat.", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTitle": "Configurer le groupe de logs Cloudwatch", + "home.tutorials.common.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "Modifiez les paramètres dans le fichier ''functionbeat.yml''.", + "home.tutorials.common.functionbeatEnableOnPremInstructionsWindows.textPre": "Modifiez les paramètres dans le fichier {path}.", + "home.tutorials.common.functionbeatInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.functionbeatInstructions.config.osxTitle": "Configurer le cluster Elastic", + "home.tutorials.common.functionbeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.functionbeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.functionbeatInstructions.deploy.osxTextPre": "Ceci permet d'installer Functionbeat en tant que fonction Lambda. La commande ''setup'' vérifie la configuration d'Elasticsearch et charge le modèle d'indexation Kibana. L'omission de cette commande est normalement sans risque.", + "home.tutorials.common.functionbeatInstructions.deploy.osxTitle": "Déployer Functionbeat en tant que fonction AWS Lambda", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTextPre": "Ceci permet d'installer Functionbeat en tant que fonction Lambda. La commande ''setup'' vérifie la configuration d'Elasticsearch et charge le modèle d'indexation Kibana. L'omission de cette commande est normalement sans risque.", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTitle": "Déployer Functionbeat en tant que fonction AWS Lambda", + "home.tutorials.common.functionbeatInstructions.install.linuxTextPre": "Vous utilisez Functionbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.functionbeatInstructions.install.linuxTitle": "Télécharger et installer Functionbeat", + "home.tutorials.common.functionbeatInstructions.install.osxTextPre": "Vous utilisez Functionbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.functionbeatInstructions.install.osxTitle": "Télécharger et installer Functionbeat", + "home.tutorials.common.functionbeatInstructions.install.windowsTextPre": "Vous utilisez Functionbeat pour la première fois ? Consultez le [guide de démarrage rapide]({functionbeatLink}).\n 1. Téléchargez le fichier .zip Functionbeat pour Windows via la page [Télécharger]({elasticLink}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Functionbeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Depuis l'invite PowerShell, accédez au répertoire Functionbeat :", + "home.tutorials.common.functionbeatInstructions.install.windowsTitle": "Télécharger et installer Functionbeat", + "home.tutorials.common.functionbeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.functionbeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue de Functionbeat.", + "home.tutorials.common.functionbeatStatusCheck.successText": "Des données ont été reçues de Functionbeat.", + "home.tutorials.common.functionbeatStatusCheck.text": "Vérifier que des données sont reçues de Functionbeat", + "home.tutorials.common.functionbeatStatusCheck.title": "Statut de Functionbeat", + "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTextPost": "Pour plus d’informations sur comment configurer des moniteurs dans Heartbeat, consultez les [documents de configuration de Heartbeat.]({configureLink})", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTitle": "Modifier la configuration – Ajouter des moniteurs", + "home.tutorials.common.heartbeatEnableCloudInstructions.osxTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableCloudInstructions.rpmTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableCloudInstructions.windowsTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableOnPremInstructions.debTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTextPost": "Où {hostTemplate} est l’URL monitorée. Pour plus d’informations sur comment configurer des moniteurs dans Heartbeat, consultez les [documents de configuration de Heartbeat.]({configureLink})", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTitle": "Modifier la configuration – Ajouter des moniteurs", + "home.tutorials.common.heartbeatEnableOnPremInstructions.osxTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableOnPremInstructions.rpmTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatEnableOnPremInstructions.windowsTextPre": "Modifiez le paramètre ''heartbeat.monitors'' dans le fichier ''heartbeat.yml''.", + "home.tutorials.common.heartbeatInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.heartbeatInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.heartbeatInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.heartbeatInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.heartbeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.heartbeatInstructions.install.debTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({link}).", + "home.tutorials.common.heartbeatInstructions.install.debTextPre": "Vous utilisez Heartbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.heartbeatInstructions.install.debTitle": "Télécharger et installer Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.osxTextPre": "Vous utilisez Heartbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.heartbeatInstructions.install.osxTitle": "Télécharger et installer Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.rpmTextPre": "Vous utilisez Heartbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.heartbeatInstructions.install.rpmTitle": "Télécharger et installer Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.windowsTextPre": "Vous utilisez Heartbeat pour la première fois ? Consultez le [guide de démarrage rapide]({heartbeatLink}).\n 1. Téléchargez le fichier .zip Heartbeat pour Windows via la page [Télécharger]({elasticLink}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Heartbeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Dans l'invite PowerShell, exécutez les commandes suivantes afin d'installer Heartbeat en tant que service Windows.", + "home.tutorials.common.heartbeatInstructions.install.windowsTitle": "Télécharger et installer Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.debTextPre": "La commande ''setup'' charge le modèle d'indexation Kibana.", + "home.tutorials.common.heartbeatInstructions.start.debTitle": "Lancer Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.osxTextPre": "La commande ''setup'' charge le modèle d'indexation Kibana.", + "home.tutorials.common.heartbeatInstructions.start.osxTitle": "Lancer Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.rpmTextPre": "La commande ''setup'' charge le modèle d'indexation Kibana.", + "home.tutorials.common.heartbeatInstructions.start.rpmTitle": "Lancer Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.windowsTextPre": "La commande ''setup'' charge le modèle d'indexation Kibana.", + "home.tutorials.common.heartbeatInstructions.start.windowsTitle": "Lancer Heartbeat", + "home.tutorials.common.heartbeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.heartbeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue de Heartbeat.", + "home.tutorials.common.heartbeatStatusCheck.successText": "Des données ont été reçues de Heartbeat.", + "home.tutorials.common.heartbeatStatusCheck.text": "Vérifier que des données sont reçues de Heartbeat", + "home.tutorials.common.heartbeatStatusCheck.title": "Statut de Heartbeat", + "home.tutorials.common.logstashInstructions.install.java.osxTextPre": "Suivez les instructions d'installation [ici]({link}).", + "home.tutorials.common.logstashInstructions.install.java.osxTitle": "Télécharger et installer l'environnement d'exécution Java", + "home.tutorials.common.logstashInstructions.install.java.windowsTextPre": "Suivez les instructions d'installation [ici]({link}).", + "home.tutorials.common.logstashInstructions.install.java.windowsTitle": "Télécharger et installer l'environnement d'exécution Java", + "home.tutorials.common.logstashInstructions.install.logstash.osxTextPre": "Vous utilisez Logstash pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.logstashInstructions.install.logstash.osxTitle": "Télécharger et installer Logstash", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTextPre": "Vous utilisez Logstash pour la première fois ? Consultez le [guide de démarrage rapide]({logstashLink}).\n 1. [Téléchargez]({elasticLink}) le fichier .zip Logstash pour Windows.\n 2. Extrayez le contenu du fichier compressé.", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTitle": "Télécharger et installer Logstash", + "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "Commencer", + "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "Modifiez les paramètres dans le fichier ''/etc/metricbeat/modules.d/{moduleName}.yml''.", + "home.tutorials.common.metricbeatEnableInstructions.debTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPost": "Modifiez les paramètres dans le fichier ''modules.d/{moduleName}.yml''.", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPre": "Dans le répertoire d'installation, exécutez la commande suivante :", + "home.tutorials.common.metricbeatEnableInstructions.osxTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.metricbeatEnableInstructions.rpmTextPost": "Modifiez les paramètres dans le fichier ''/etc/metricbeat/modules.d/{moduleName}.yml''.", + "home.tutorials.common.metricbeatEnableInstructions.rpmTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPost": "Modifiez les paramètres dans le fichier ''modules.d/{moduleName}.yml''.", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPre": "Dans le dossier {path}, exécutez la commande suivante :", + "home.tutorials.common.metricbeatEnableInstructions.windowsTitle": "Activer et configurer le module {moduleName}", + "home.tutorials.common.metricbeatInstructions.config.debTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.metricbeatInstructions.config.debTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatInstructions.config.osxTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.metricbeatInstructions.config.osxTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatInstructions.config.rpmTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.metricbeatInstructions.config.rpmTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.metricbeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.metricbeatInstructions.install.debTextPost": "Vous cherchez les packages 32 bits ? Consultez la [page de téléchargement]({link}).", + "home.tutorials.common.metricbeatInstructions.install.debTextPre": "Vous utilisez Metricbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.metricbeatInstructions.install.debTitle": "Télécharger et installer Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.osxTextPre": "Vous utilisez Metricbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.metricbeatInstructions.install.osxTitle": "Télécharger et installer Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.rpmTextPre": "Vous utilisez Metricbeat pour la première fois ? Consultez le [guide de démarrage rapide]({link}).", + "home.tutorials.common.metricbeatInstructions.install.rpmTitle": "Télécharger et installer Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPost": "Modifiez les paramètres sous ''output.elasticsearch'' dans le fichier {path} afin de pointer vers votre installation Elasticsearch.", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPre": "Vous utilisez Metricbeat pour la première fois ? Consultez le [guide de démarrage rapide]({metricbeatLink}).\n 1. Téléchargez le fichier .zip Metricbeat pour Windows via la page [Télécharger]({elasticLink}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Metricbeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Dans l'invite PowerShell, exécutez les commandes suivantes afin d'installer Metricbeat en tant que service Windows.", + "home.tutorials.common.metricbeatInstructions.install.windowsTitle": "Télécharger et installer Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.debTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.metricbeatInstructions.start.debTitle": "Lancer Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.osxTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.metricbeatInstructions.start.osxTitle": "Lancer Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.rpmTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.metricbeatInstructions.start.rpmTitle": "Lancer Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.windowsTextPre": "La commande ''setup'' charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.metricbeatInstructions.start.windowsTitle": "Lancer Metricbeat", + "home.tutorials.common.metricbeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.metricbeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue de ce module.", + "home.tutorials.common.metricbeatStatusCheck.successText": "Des données ont été reçues de ce module.", + "home.tutorials.common.metricbeatStatusCheck.text": "Vérifier que des données sont reçues du module Metricbeat \"{moduleName}\"", + "home.tutorials.common.metricbeatStatusCheck.title": "Statut du module", + "home.tutorials.common.premCloudInstructions.option1.textPre": "Rendez-vous sur [Elastic Cloud]({link}). Enregistrez-vous si vous n'avez pas encore de compte. Un essai gratuit de 14 jours est disponible.\n\nConnectez-vous à la console Elastic Cloud.\n\nPour créer un cluster, dans la console Elastic Cloud :\n 1. Sélectionnez **Créer un déploiement** et spécifiez le **Nom du déploiement**.\n 2. Modifiez les autres options de déploiement selon les besoins (sinon, les valeurs par défaut sont très bien pour commencer).\n 3. Cliquer sur **Créer un déploiement**\n 4. Attendre la fin de la création du déploiement\n 5. Accéder à la nouvelle instance cloud Kibana et suivre les instructions de la page d'accueil de Kibana", + "home.tutorials.common.premCloudInstructions.option1.title": "Option 1 : essayer dans Elastic Cloud", + "home.tutorials.common.premCloudInstructions.option2.textPre": "Si vous exécutez cette instance Kibana sur une instance Elasticsearch hébergée, passez à la configuration manuelle.\n\nEnregistrez le point de terminaison **Elasticsearch** en tant que {urlTemplate} et le cluster **Mot de passe** en tant que {passwordTemplate} pour les conserver.", + "home.tutorials.common.premCloudInstructions.option2.title": "Option 2 : connecter un Kibana local à une instance cloud", + "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "Premiers pas", + "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "Premiers pas", + "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "Premiers pas", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion pour Elastic Cloud :", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.winlogbeatInstructions.config.windowsTextPre": "Modifiez {path} afin de définir les informations de connexion :", + "home.tutorials.common.winlogbeatInstructions.config.windowsTitle": "Modifier la configuration", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPost": "Modifiez les paramètres sous \"output.elasticsearch\" dans le fichier {path} afin de pointer vers votre installation Elasticsearch.", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPre": "Vous utilisez Winlogbeat pour la première fois ? Consultez le [guide de démarrage rapide]({winlogbeatLink}).\n 1. Téléchargez le fichier .zip Winlogbeat pour Windows via la page [Télécharger]({elasticLink}).\n 2. Extrayez le contenu du fichier compressé sous {folderPath}.\n 3. Renommez le répertoire \"{directoryName}\" en \"Winlogbeat\".\n 4. Ouvrez une invite PowerShell en tant qu'administrateur (faites un clic droit sur l'icône PowerShell et sélectionnez **Exécuter en tant qu'administrateur**). Si vous exécutez Windows XP, vous devrez peut-être télécharger et installer PowerShell.\n 5. Dans l'invite PowerShell, exécutez les commandes suivantes afin d'installer Winlogbeat en tant que service Windows.", + "home.tutorials.common.winlogbeatInstructions.install.windowsTitle": "Télécharger et installer Winlogbeat", + "home.tutorials.common.winlogbeatInstructions.start.windowsTextPre": "La commande \"setup\" charge les tableaux de bord Kibana. Si les tableaux de bord sont déjà configurés, omettez cette commande.", + "home.tutorials.common.winlogbeatInstructions.start.windowsTitle": "Lancer Winlogbeat", + "home.tutorials.common.winlogbeatStatusCheck.buttonLabel": "Vérifier les données", + "home.tutorials.common.winlogbeatStatusCheck.errorText": "Aucune donnée n'a encore été reçue.", + "home.tutorials.common.winlogbeatStatusCheck.successText": "Des données ont été reçues.", + "home.tutorials.common.winlogbeatStatusCheck.text": "Vérifier que des données sont reçues de Winlogbeat", + "home.tutorials.common.winlogbeatStatusCheck.title": "Statut du module", + "home.tutorials.consulMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Consul", + "home.tutorials.consulMetrics.longDescription": "Le module Metricbeat \"consul\" récupère des indicateurs de monitoring depuis Consul. [En savoir plus]({learnMoreLink}).", + "home.tutorials.consulMetrics.nameTitle": "Indicateurs Consul", + "home.tutorials.consulMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur Consul.", + "home.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "Aperçu de [Filebeat CoreDNS]", + "home.tutorials.corednsLogs.longDescription": "Il s'agit d'un module Filebeat pour CoreDNS. Celui-ci prend en charge les déploiements CoreDNS autonomes et les déploiements CoreDNS dans Kubernetes. [En savoir plus]({learnMoreLink}).", + "home.tutorials.corednsLogs.nameTitle": "Logs CoreDNS", + "home.tutorials.corednsLogs.shortDescription": "Collectez les logs CoreDNS.", + "home.tutorials.corednsMetrics.artifacts.application.label": "Discover", + "home.tutorials.corednsMetrics.longDescription": "Le module Metricbeat \"coredns\" récupère des indicateurs de monitoring depuis CoreDNS. [En savoir plus]({learnMoreLink}).", + "home.tutorials.corednsMetrics.nameTitle": "Indicateurs CoreDNS", + "home.tutorials.corednsMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur CoreDNS.", + "home.tutorials.couchbaseMetrics.artifacts.application.label": "Discover", + "home.tutorials.couchbaseMetrics.longDescription": "Le module Metricbeat \"couchbase\" récupère des indicateurs internes depuis Couchbase. [En savoir plus]({learnMoreLink}).", + "home.tutorials.couchbaseMetrics.nameTitle": "Indicateurs Couchbase", + "home.tutorials.couchbaseMetrics.shortDescription": "Récupérez des indicateurs internes depuis Couchbase.", + "home.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs CouchDB", + "home.tutorials.couchdbMetrics.longDescription": "Le module Metricbeat \"couchdb\" récupère des indicateurs de monitoring depuis CouchDB. [En savoir plus]({learnMoreLink}).", + "home.tutorials.couchdbMetrics.nameTitle": "Indicateurs CouchDB", + "home.tutorials.couchdbMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur CouchdB.", + "home.tutorials.crowdstrikeLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.crowdstrikeLogs.longDescription": "Il s'agit du module Filebeat pour CrowdStrike Falcon utilisant le [connecteur SIEM](https://www.crowdstrike.com/blog/tech-center/integrate-with-your-siem) Falcon. Ce module collecte ces données, les convertit en ECS et les ingère pour les afficher dans le SIEM. Par défaut, le connecteur SIEM Falcon génère les données d'événement de l'API de streaming Falcon au format JSON. [En savoir plus]({learnMoreLink}).", + "home.tutorials.crowdstrikeLogs.nameTitle": "Logs CrowdStrike", + "home.tutorials.crowdstrikeLogs.shortDescription": "Collectez des logs CrowdStrike Falcon à l'aide du connecteur SIEM Falcon.", + "home.tutorials.cylanceLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.cylanceLogs.longDescription": "Ce module permet de recevoir des logs CylancePROTECT par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.cylanceLogs.nameTitle": "Logs CylancePROTECT", + "home.tutorials.cylanceLogs.shortDescription": "Collectez des logs CylancePROTECT par le biais de Syslog ou d’un fichier.", + "home.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Docker", + "home.tutorials.dockerMetrics.longDescription": "Le module Metricbeat \"docker\" récupère des indicateurs depuis le serveur Docker. [En savoir plus]({learnMoreLink}).", + "home.tutorials.dockerMetrics.nameTitle": "Indicateurs Docker", + "home.tutorials.dockerMetrics.shortDescription": "Récupérez des indicateurs concernant vos conteneurs Docker.", + "home.tutorials.dropwizardMetrics.artifacts.application.label": "Discover", + "home.tutorials.dropwizardMetrics.longDescription": "Le module Metricbeat \"dropwizard\" récupère des indicateurs internes depuis l'application Java Dropwizard. [En savoir plus]({learnMoreLink}).", + "home.tutorials.dropwizardMetrics.nameTitle": "Indicateurs Dropwizard", + "home.tutorials.dropwizardMetrics.shortDescription": "Récupérez des indicateurs internes depuis l'application Java Dropwizard.", + "home.tutorials.elasticsearchLogs.artifacts.application.label": "Discover", + "home.tutorials.elasticsearchLogs.longDescription": "Le module Filebeat \"elasticsearch\" analyse les logs créés par Elasticsearch. [En savoir plus]({learnMoreLink}).", + "home.tutorials.elasticsearchLogs.nameTitle": "Logs Elasticsearch", + "home.tutorials.elasticsearchLogs.shortDescription": "Collectez et analysez les logs créés par Elasticsearch.", + "home.tutorials.elasticsearchMetrics.artifacts.application.label": "Discover", + "home.tutorials.elasticsearchMetrics.longDescription": "Le module Metricbeat \"elasticsearch\" récupère des indicateurs internes depuis Elasticsearch. [En savoir plus]({learnMoreLink}).", + "home.tutorials.elasticsearchMetrics.nameTitle": "Indicateurs Elasticsearch", + "home.tutorials.elasticsearchMetrics.shortDescription": "Récupérez des indicateurs internes depuis Elasticsearch.", + "home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "Aperçu d'Envoy Proxy", + "home.tutorials.envoyproxyLogs.longDescription": "Il s'agit d'un module Filebeat pour le log d'accès à Envoy Proxy (https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log). Celui-ci prend en charge les déploiements autonomes et les déploiements Envoy Proxy dans Kubernetes. [Learn more]({learnMoreLink}).", + "home.tutorials.envoyproxyLogs.nameTitle": "Logs Envoy Proxy", + "home.tutorials.envoyproxyLogs.shortDescription": "Collectez des logs Envoy Proxy.", + "home.tutorials.envoyproxyMetrics.longDescription": "Le module Metricbeat \"envoyproxy\" récupère des indicateurs de monitoring depuis Envoy Proxy. [En savoir plus]({learnMoreLink}).", + "home.tutorials.envoyproxyMetrics.nameTitle": "Indicateurs Envoy Proxy", + "home.tutorials.envoyproxyMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis Envoy Proxy.", + "home.tutorials.etcdMetrics.artifacts.application.label": "Discover", + "home.tutorials.etcdMetrics.longDescription": "Le module Metricbeat \"etcd\" récupère des indicateurs internes depuis Etcd. [En savoir plus]({learnMoreLink}).", + "home.tutorials.etcdMetrics.nameTitle": "Indicateurs Etcd", + "home.tutorials.etcdMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur Etcd.", + "home.tutorials.f5Logs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.f5Logs.longDescription": "Ce module permet de recevoir des logs Big-IP Access Policy Manager par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.f5Logs.nameTitle": "Logs F5", + "home.tutorials.f5Logs.shortDescription": "Collectez des logs F5 Big-IP Access Policy Manager par le biais de Syslog ou d’un fichier.", + "home.tutorials.fortinetLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.fortinetLogs.longDescription": "Il s'agit d'un module pour les logs Fortinet FortiOS envoyés au format Syslog. [En savoir plus]({learnMoreLink}).", + "home.tutorials.fortinetLogs.nameTitle": "Logs Fortinet", + "home.tutorials.fortinetLogs.shortDescription": "Collectez des logs Fortinet FortiOS par le biais de Syslog.", + "home.tutorials.gcpLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs d'audit", + "home.tutorials.gcpLogs.longDescription": "Il s'agit d'un module pour les logs Google Cloud. Il prend en charge la lecture des logs d'audit, de flux VPC et de pare-feu qui ont été exportés depuis Stackdriver dans un récepteur de rubriques Google Pub/Sub. [En savoir plus]({learnMoreLink}).", + "home.tutorials.gcpLogs.nameTitle": "Logs Google Cloud", + "home.tutorials.gcpLogs.shortDescription": "Collectez des logs d'audit, de pare-feu et de flux VPC Google Cloud.", + "home.tutorials.gcpMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Google Cloud", + "home.tutorials.gcpMetrics.longDescription": "Le module Metricbeat \"gcp\" récupère des indicateurs de monitoring depuis Google Cloud Platform à l'aide de l'API de monitoring Stackdriver. [En savoir plus]({learnMoreLink}).", + "home.tutorials.gcpMetrics.nameTitle": "Indicateurs Google Cloud", + "home.tutorials.gcpMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis Google Cloud Platform à l'aide de l'API de monitoring Stackdriver.", + "home.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Golang", + "home.tutorials.golangMetrics.longDescription": "Le module Metricbeat \"{moduleName}\" récupère des indicateurs internes depuis une application Golang. [En savoir plus]({learnMoreLink}).", + "home.tutorials.golangMetrics.nameTitle": "Indicateurs Golang", + "home.tutorials.golangMetrics.shortDescription": "Récupérez des indicateurs internes depuis une application Golang.", + "home.tutorials.gsuiteLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.gsuiteLogs.longDescription": "Il s'agit d'un module pour l'ingestion de données depuis les différentes API de rapports d'audit GSuite. [En savoir plus]({learnMoreLink}).", + "home.tutorials.gsuiteLogs.nameTitle": "Logs GSuite", + "home.tutorials.gsuiteLogs.shortDescription": "Collectez des rapports d'activité GSuite.", + "home.tutorials.haproxyLogs.artifacts.dashboards.linkLabel": "Aperçu de HAProxy", + "home.tutorials.haproxyLogs.longDescription": "Le module collecte et analyse les logs d'un processus (\"haproxy\") [En savoir plus]({learnMoreLink}).", + "home.tutorials.haproxyLogs.nameTitle": "Logs HAProxy", + "home.tutorials.haproxyLogs.shortDescription": "Collectez des logs HAProxy.", + "home.tutorials.haproxyMetrics.artifacts.application.label": "Discover", + "home.tutorials.haproxyMetrics.longDescription": "Le module Metricbeat \"haproxy\" récupère des indicateurs internes depuis HAProxy. [En savoir plus]({learnMoreLink}).", + "home.tutorials.haproxyMetrics.nameTitle": "Indicateurs HAProxy", + "home.tutorials.haproxyMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur HAProxy.", + "home.tutorials.ibmmqLogs.artifacts.dashboards.linkLabel": "Événements IBM MQ", + "home.tutorials.ibmmqLogs.longDescription": "Collectez des logs IBM MQ avec Filebeat. [En savoir plus]({learnMoreLink}).", + "home.tutorials.ibmmqLogs.nameTitle": "Logs IBM MQ", + "home.tutorials.ibmmqLogs.shortDescription": "Collectez des logs IBM MQ avec Filebeat.", + "home.tutorials.ibmmqMetrics.artifacts.application.label": "Discover", + "home.tutorials.ibmmqMetrics.longDescription": "Le module Metricbeat \"ibmmq\" récupère des indicateurs de monitoring depuis les instances IBM MQ. [En savoir plus]({learnMoreLink}).", + "home.tutorials.ibmmqMetrics.nameTitle": "Indicateurs IBM MQ", + "home.tutorials.ibmmqMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis les instances IBM MQ.", + "home.tutorials.icingaLogs.artifacts.dashboards.linkLabel": "Log principal Icinga", + "home.tutorials.icingaLogs.longDescription": "Le module analyse le log principal et les logs de débogage et de démarrage d'[Icinga](https://www.icinga.com/products/icinga-2/). [En savoir plus]({learnMoreLink}).", + "home.tutorials.icingaLogs.nameTitle": "Logs Icinga", + "home.tutorials.icingaLogs.shortDescription": "Collectez le log principal et les logs de débogage et de démarrage d'Icinga.", + "home.tutorials.iisLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs IIS", + "home.tutorials.iisLogs.longDescription": "Le module Filebeat \"iis\" analyse les logs d'accès et d'erreurs créés par le serveur HTTP IIS. [En savoir plus]({learnMoreLink}).", + "home.tutorials.iisLogs.nameTitle": "Logs IIS", + "home.tutorials.iisLogs.shortDescription": "Collectez et analysez les logs d'accès et d'erreurs créés par le serveur HTTP IIS.", + "home.tutorials.iisMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs IIS", + "home.tutorials.iisMetrics.longDescription": "Le module Metricbeat \"iis\" collecte les indicateurs du serveur IIS ainsi que des sites web et des pools d'applications en cours d'exécution. [En savoir plus]({learnMoreLink}).", + "home.tutorials.iisMetrics.nameTitle": "Indicateurs IIS", + "home.tutorials.iisMetrics.shortDescription": "Collectez les indicateurs en lien avec le serveur IIS.", + "home.tutorials.impervaLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.impervaLogs.longDescription": "Ce module permet de recevoir des logs Imperva SecureSphere par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.impervaLogs.nameTitle": "Logs Imperva", + "home.tutorials.impervaLogs.shortDescription": "Collectez des logs Imperva SecureSphere par le biais de Syslog ou d’un fichier.", + "home.tutorials.infobloxLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.infobloxLogs.longDescription": "Ce module permet de recevoir des logs Infoblox NIOS par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.infobloxLogs.nameTitle": "Logs Infoblox", + "home.tutorials.infobloxLogs.shortDescription": "Collectez des logs Infoblox NIOS par le biais de Syslog ou d’un fichier.", + "home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "Aperçu d'Iptables", + "home.tutorials.iptablesLogs.longDescription": "Il s'agit d'un module pour les logs iptables et ip6tables. Il analyse les logs reçus via le réseau par le biais de Syslog ou d’un fichier. En outre, il comprend le préfixe ajouté par certains pare-feux Ubiquiti qui contient le nom de l'ensemble de règles, le numéro de règle et l'action effectuée sur le trafic (autoriser/refuser). [En savoir plus]({learnMoreLink}).", + "home.tutorials.iptablesLogs.nameTitle": "Logs Iptables", + "home.tutorials.iptablesLogs.shortDescription": "Collectez des logs iptables et ip6tables.", + "home.tutorials.juniperLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.juniperLogs.longDescription": "Ce module permet de recevoir des logs Juniper JUNOS par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.juniperLogs.nameTitle": "Logs Juniper", + "home.tutorials.juniperLogs.shortDescription": "Collectez des logs Juniper JUNOS par le biais de Syslog ou d’un fichier.", + "home.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs Kafka", + "home.tutorials.kafkaLogs.longDescription": "Le module Filebeat \"kafka\" analyse les logs créés par Kafka. [En savoir plus]({learnMoreLink}).", + "home.tutorials.kafkaLogs.nameTitle": "Logs Kafka", + "home.tutorials.kafkaLogs.shortDescription": "Collectez et analysez les logs créés par Kafka.", + "home.tutorials.kafkaMetrics.artifacts.application.label": "Discover", + "home.tutorials.kafkaMetrics.longDescription": "Le module Metricbeat \"kafka\" récupère des indicateurs internes depuis Kafka. [En savoir plus]({learnMoreLink}).", + "home.tutorials.kafkaMetrics.nameTitle": "Indicateurs Kafka", + "home.tutorials.kafkaMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur Kafka.", + "home.tutorials.kibanaLogs.artifacts.application.label": "Discover", + "home.tutorials.kibanaLogs.longDescription": "Il s'agit du module Kibana. [En savoir plus]({learnMoreLink}).", + "home.tutorials.kibanaLogs.nameTitle": "Logs Kibana", + "home.tutorials.kibanaLogs.shortDescription": "Collectez des logs Kibana.", + "home.tutorials.kibanaMetrics.artifacts.application.label": "Discover", + "home.tutorials.kibanaMetrics.longDescription": "Le module Metricbeat \"kibana\" récupère des indicateurs internes depuis Kibana. [En savoir plus]({learnMoreLink}).", + "home.tutorials.kibanaMetrics.nameTitle": "Indicateurs Kibana", + "home.tutorials.kibanaMetrics.shortDescription": "Récupérez des indicateurs internes depuis Kibana.", + "home.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Kubernetes", + "home.tutorials.kubernetesMetrics.longDescription": "Le module Metricbeat \"kubernetes\" récupère des indicateurs depuis les API Kubernetes. [En savoir plus]({learnMoreLink}).", + "home.tutorials.kubernetesMetrics.nameTitle": "Indicateurs Kubernetes", + "home.tutorials.kubernetesMetrics.shortDescription": "Récupérez des indicateurs depuis votre installation Kubernetes.", + "home.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logs Logstash", + "home.tutorials.logstashLogs.longDescription": "Le module analyse les logs standard et le log de requêtes lentes Logstash. Il prend en charge les formats texte brut et JSON. [En savoir plus]({learnMoreLink}).", + "home.tutorials.logstashLogs.nameTitle": "Logs Logstash", + "home.tutorials.logstashLogs.shortDescription": "Collectez le log principal et le log de requêtes lentes Logstash.", + "home.tutorials.logstashMetrics.artifacts.application.label": "Discover", + "home.tutorials.logstashMetrics.longDescription": "Le module Metricbeat \"{moduleName}\" récupère des indicateurs internes depuis un serveur Logstash. [En savoir plus]({learnMoreLink}).", + "home.tutorials.logstashMetrics.nameTitle": "Indicateurs Logstash", + "home.tutorials.logstashMetrics.shortDescription": "Récupérez des indicateurs internes depuis un serveur Logstash.", + "home.tutorials.memcachedMetrics.artifacts.application.label": "Discover", + "home.tutorials.memcachedMetrics.longDescription": "Le module Metricbeat \"memcached\" récupère des indicateurs internes depuis Memcached. [En savoir plus]({learnMoreLink}).", + "home.tutorials.memcachedMetrics.nameTitle": "Indicateurs Memcached", + "home.tutorials.memcachedMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur Memcached.", + "home.tutorials.microsoftLogs.artifacts.dashboards.linkLabel": "Aperçu de Microsoft ATP", + "home.tutorials.microsoftLogs.longDescription": "Collectez des alertes Microsoft Defender ATP pour les utiliser avec Elastic Security [En savoir plus]({learnMoreLink}).", + "home.tutorials.microsoftLogs.nameTitle": "Logs Microsoft Defender ATP", + "home.tutorials.microsoftLogs.shortDescription": "Collectez des alertes Microsoft Defender ATP.", + "home.tutorials.mispLogs.artifacts.dashboards.linkLabel": "Aperçu de MISP", + "home.tutorials.mispLogs.longDescription": "Il s'agit d'un module Filebeat pour la lecture des informations de Threat Intelligence depuis la plateforme MISP (https://www.circl.lu/doc/misp/). Il utilise l'entrée httpjson pour accéder à l'interface d'API REST MISP. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mispLogs.nameTitle": "Logs de Threat Intelligence MISP", + "home.tutorials.mispLogs.shortDescription": "Collectez des données de Threat Intelligence MISP avec Filebeat.", + "home.tutorials.mongodbLogs.artifacts.dashboards.linkLabel": "Aperçu de MongoDB", + "home.tutorials.mongodbLogs.longDescription": "Le module collecte et analyse les logs créés par [MongoDB](https://www.mongodb.com/). [En savoir plus]({learnMoreLink}).", + "home.tutorials.mongodbLogs.nameTitle": "Logs MongoDB", + "home.tutorials.mongodbLogs.shortDescription": "Collectez des logs MongoDB.", + "home.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs MongoDB", + "home.tutorials.mongodbMetrics.longDescription": "Le module Metricbeat \"mongodb\" récupère des indicateurs internes depuis le serveur MongoDB. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mongodbMetrics.nameTitle": "Indicateurs MongoDB", + "home.tutorials.mongodbMetrics.shortDescription": "Récupérez des indicateurs internes depuis MongoDB.", + "home.tutorials.mssqlLogs.artifacts.application.label": "Discover", + "home.tutorials.mssqlLogs.longDescription": "Le module analyse les logs d'erreurs créés par MSSQL. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mssqlLogs.nameTitle": "Logs MSSQL", + "home.tutorials.mssqlLogs.shortDescription": "Collectez des logs MSSQL.", + "home.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Microsoft SQL Server", + "home.tutorials.mssqlMetrics.longDescription": "Le module Metricbeat \"mssql\" récupère des indicateurs de monitoring, de logs et de performances depuis une instance Microsoft SQL Server. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mssqlMetrics.nameTitle": "Indicateurs Microsoft SQL Server", + "home.tutorials.mssqlMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis une instance Microsoft SQL Server.", + "home.tutorials.muninMetrics.artifacts.application.label": "Discover", + "home.tutorials.muninMetrics.longDescription": "Le module Metricbeat \"munin\" récupère des indicateurs internes depuis Munin. [En savoir plus]({learnMoreLink}).", + "home.tutorials.muninMetrics.nameTitle": "Indicateurs Munin", + "home.tutorials.muninMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur Munin.", + "home.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs MySQL", + "home.tutorials.mysqlLogs.longDescription": "Le module Filebeat \"mysql\" analyse les logs d'erreurs et de requêtes lentes créés par MySQL. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mysqlLogs.nameTitle": "Logs MySQL", + "home.tutorials.mysqlLogs.shortDescription": "Collectez et analysez les logs d'erreurs et de requêtes lentes créés par MySQL.", + "home.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs MySQL", + "home.tutorials.mysqlMetrics.longDescription": "Le module Metricbeat \"mysql\" récupère des indicateurs internes depuis le serveur MySQL. [En savoir plus]({learnMoreLink}).", + "home.tutorials.mysqlMetrics.nameTitle": "Indicateurs MySQL", + "home.tutorials.mysqlMetrics.shortDescription": "Récupérez des indicateurs internes depuis MySQL.", + "home.tutorials.natsLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs NATS", + "home.tutorials.natsLogs.longDescription": "Le module Filebeat \"nats\" analyse les logs créés par NATS. [En savoir plus]({learnMoreLink}).", + "home.tutorials.natsLogs.nameTitle": "Logs NATS", + "home.tutorials.natsLogs.shortDescription": "Collectez et analysez les logs créés par NATS.", + "home.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs NATS", + "home.tutorials.natsMetrics.longDescription": "Le module Metricbeat \"nats\" récupère des indicateurs de monitoring depuis NATS. [En savoir plus]({learnMoreLink}).", + "home.tutorials.natsMetrics.nameTitle": "Indicateurs NATS", + "home.tutorials.natsMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur NATS.", + "home.tutorials.netflowLogs.artifacts.dashboards.linkLabel": "Aperçu de Netflow", + "home.tutorials.netflowLogs.longDescription": "Ce module permet de recevoir des enregistrements de flux NetFlow et IPFIX via UDP. Cette entrée prend en charge les versions 1, 5, 6, 7, 8 et 9 de NetFlow ainsi qu'IPFIX. Pour les versions de NetFlow antérieures à la version 9, les champs sont automatiquement mappés vers NetFlow v9. [En savoir plus]({learnMoreLink})", + "home.tutorials.netflowLogs.nameTitle": "Collecteur IPFIX/NetFlow", + "home.tutorials.netflowLogs.shortDescription": "Collectez des enregistrements de flux NetFlow et IPFIX.", + "home.tutorials.netscoutLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.netscoutLogs.longDescription": "Ce module permet de recevoir des logs Arbor Peakflow SP par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.netscoutLogs.nameTitle": "Logs Arbor Peakflow", + "home.tutorials.netscoutLogs.shortDescription": "Collectez des logs Netscout Arbor Peakflow SP par le biais de Syslog ou d’un fichier.", + "home.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs Nginx", + "home.tutorials.nginxLogs.longDescription": "Le module Filebeat \"nginx\" analyse les logs d'accès et d'erreurs créés par le serveur HTTP Nginx. [En savoir plus]({learnMoreLink}).", + "home.tutorials.nginxLogs.nameTitle": "Logs Nginx", + "home.tutorials.nginxLogs.shortDescription": "Collectez et analysez les logs d'accès et d'erreurs créés par le serveur HTTP Nginx.", + "home.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Nginx", + "home.tutorials.nginxMetrics.longDescription": "Le module Metricbeat \"nginx\" récupère des indicateurs internes depuis le serveur HTTP Nginx. Le module récupère les données de statut du serveur depuis la page web générée par {statusModuleLink}, qui doit être activé dans votre installation Nginx. [En savoir plus]({learnMoreLink}).", + "home.tutorials.nginxMetrics.nameTitle": "Indicateurs Nginx", + "home.tutorials.nginxMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur HTTP Nginx.", + "home.tutorials.o365Logs.artifacts.dashboards.linkLabel": "Tableau de bord des audits O365", + "home.tutorials.o365Logs.longDescription": "Il s'agit d'un module pour les logs Office 365 reçus via l'un des points de terminaison d'API Office 365. Actuellement, il prend en charge les actions et les événements utilisateur, administrateur, système et de politique depuis les logs d’activité Office 365 et Azure AD exposés par l'API d’activité de gestion Office 365. [En savoir plus]({learnMoreLink}).", + "home.tutorials.o365Logs.nameTitle": "Logs Office 365", + "home.tutorials.o365Logs.shortDescription": "Collectez les logs d'activité Office 365 via l'API Office 365.", + "home.tutorials.oktaLogs.artifacts.dashboards.linkLabel": "Aperçu d'Okta", + "home.tutorials.oktaLogs.longDescription": "Le module Okta collecte les événements de l'[API Okta](https://developer.okta.com/docs/reference/). Plus précisément, il prend en charge la lecture depuis l'[API de log système Okta](https://developer.okta.com/docs/reference/api/system-log/). [En savoir plus]({learnMoreLink}).", + "home.tutorials.oktaLogs.nameTitle": "Logs Okta", + "home.tutorials.oktaLogs.shortDescription": "Collectez le log système Okta via l'API Okta.", + "home.tutorials.openmetricsMetrics.longDescription": "Le module Metricbeat \"openmetrics\" récupère des indicateurs depuis un point de terminaison fournissant des indicateurs au format OpenMetrics. [En savoir plus]({learnMoreLink}).", + "home.tutorials.openmetricsMetrics.nameTitle": "Indicateurs OpenMetrics", + "home.tutorials.openmetricsMetrics.shortDescription": "Récupérez des indicateurs depuis un point de terminaison fournissant des indicateurs au format OpenMetrics.", + "home.tutorials.oracleMetrics.artifacts.application.label": "Discover", + "home.tutorials.oracleMetrics.longDescription": "Le module Metricbeat \"{moduleName}\" récupère des indicateurs internes depuis un serveur Oracle. [En savoir plus]({learnMoreLink}).", + "home.tutorials.oracleMetrics.nameTitle": "Indicateurs Oracle", + "home.tutorials.oracleMetrics.shortDescription": "Récupérez des indicateurs internes depuis un serveur Oracle.", + "home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Pack de conformité osquery", + "home.tutorials.osqueryLogs.longDescription": "Le module collecte et décode les logs de résultats écrits par [osqueryd](https://osquery.readthedocs.io/en/latest/introduction/using-osqueryd/) au format JSON. Pour configurer \"osqueryd\", suivez les instructions d'installation d'osquery pour votre système d'exploitation et configurez le pilote de logging \"filesystem\" (celui par défaut). Assurez-vous que les horodatages UTC sont activés. [En savoir plus]({learnMoreLink}).", + "home.tutorials.osqueryLogs.nameTitle": "Logs osquery", + "home.tutorials.osqueryLogs.shortDescription": "Collectez des logs osquery au format JSON.", + "home.tutorials.panwLogs.artifacts.dashboards.linkLabel": "Flux de réseau PANW", + "home.tutorials.panwLogs.longDescription": "Il s'agit d'un module pour les logs de monitoring des pare-feux Palo Alto Networks PAN-OS reçus par le biais de Syslog ou lus depuis un fichier. Actuellement, il prend en charge les messages de type Trafic et Menaces. [En savoir plus]({learnMoreLink}).", + "home.tutorials.panwLogs.nameTitle": "Logs Palo Alto Networks PAN-OS", + "home.tutorials.panwLogs.shortDescription": "Collectez des logs Palo Alto Networks PAN-OS relatifs aux menaces et au trafic par le biais de Syslog ou d’un fichier log.", + "home.tutorials.phpFpmMetrics.longDescription": "Le module Metricbeat \"php_fpm\" récupère des indicateurs internes depuis le serveur PHP-FPM. [En savoir plus]({learnMoreLink}).", + "home.tutorials.phpFpmMetrics.nameTitle": "Indicateurs PHP-FPM", + "home.tutorials.phpFpmMetrics.shortDescription": "Récupérez des indicateurs internes depuis PHP-FPM.", + "home.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs PostgreSQL", + "home.tutorials.postgresqlLogs.longDescription": "Le module Filebeat \"postgresql\" analyse les logs d'erreurs et de requêtes lentes créés par PostgreSQL. [En savoir plus]({learnMoreLink}).", + "home.tutorials.postgresqlLogs.nameTitle": "Logs PostgreSQL", + "home.tutorials.postgresqlLogs.shortDescription": "Collectez et analysez les logs d'erreurs et de requêtes lentes créés par PostgreSQL.", + "home.tutorials.postgresqlMetrics.longDescription": "Le module Metricbeat \"postgresql\" récupère des indicateurs internes depuis le serveur PostgreSQL. [En savoir plus]({learnMoreLink}).", + "home.tutorials.postgresqlMetrics.nameTitle": "Indicateurs PostgreSQL", + "home.tutorials.postgresqlMetrics.shortDescription": "Récupérez des indicateurs internes depuis PostgreSQL.", + "home.tutorials.prometheusMetrics.artifacts.application.label": "Discover", + "home.tutorials.prometheusMetrics.longDescription": "Le module Metricbeat \"{moduleName}\" récupère des indicateurs depuis le point de terminaison Prometheus. [En savoir plus]({learnMoreLink}).", + "home.tutorials.prometheusMetrics.nameTitle": "Indicateurs Prometheus", + "home.tutorials.prometheusMetrics.shortDescription": "Récupérez des indicateurs depuis un exportateur Prometheus.", + "home.tutorials.rabbitmqLogs.artifacts.application.label": "Discover", + "home.tutorials.rabbitmqLogs.longDescription": "Ce module permet d'analyser les [fichiers log RabbitMQ](https://www.rabbitmq.com/logging.html). [En savoir plus]({learnMoreLink}).", + "home.tutorials.rabbitmqLogs.nameTitle": "Logs RabbitMQ", + "home.tutorials.rabbitmqLogs.shortDescription": "Collectez des logs RabbitMQ.", + "home.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs RabbitMQ", + "home.tutorials.rabbitmqMetrics.longDescription": "Le module Metricbeat \"rabbitmq\" récupère des indicateurs internes depuis le serveur RabbitMQ. [En savoir plus]({learnMoreLink}).", + "home.tutorials.rabbitmqMetrics.nameTitle": "Indicateurs RabbitMQ", + "home.tutorials.rabbitmqMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur RabbitMQ.", + "home.tutorials.radwareLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.radwareLogs.longDescription": "Ce module permet de recevoir des logs Radware DefensePro par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.radwareLogs.nameTitle": "Logs Radware DefensePro", + "home.tutorials.radwareLogs.shortDescription": "Collectez des logs Radware DefensePro par le biais de Syslog ou d’un fichier.", + "home.tutorials.redisenterpriseMetrics.artifacts.application.label": "Discover", + "home.tutorials.redisenterpriseMetrics.longDescription": "Le module Metricbeat \"redisenterprise\" récupère des indicateurs de monitoring depuis le serveur Redis Enterprise. [En savoir plus]({learnMoreLink}).", + "home.tutorials.redisenterpriseMetrics.nameTitle": "Indicateurs Redis Enterprise", + "home.tutorials.redisenterpriseMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur Redis Enterprise.", + "home.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Tableau de bord des logs Redis", + "home.tutorials.redisLogs.longDescription": "Le module Filebeat \"redis\" analyse les logs d'erreurs et de requêtes lentes créés par Redis. Pour que Redis écrive des logs d'erreurs, assurez-vous que l'option \"logfile\" est définie sur \"redis-server.log\" dans le fichier de configuration Redis. Les logs de requêtes lentes sont lus directement depuis Redis via la commande \"SLOWLOG\". Pour que Redis enregistre des logs de requêtes lentes, assurez-vous que l'option \"slowlog-log-slower-than\" est activée. Notez que l'ensemble de fichiers \"slowlog\" est expérimental. [En savoir plus]({learnMoreLink}).", + "home.tutorials.redisLogs.nameTitle": "Logs Redis", + "home.tutorials.redisLogs.shortDescription": "Collectez et analysez les logs d'erreurs et de requêtes lentes créés par Redis.", + "home.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Redis", + "home.tutorials.redisMetrics.longDescription": "Le module Metricbeat \"redis\" récupère des indicateurs internes depuis le serveur Redis. [En savoir plus]({learnMoreLink}).", + "home.tutorials.redisMetrics.nameTitle": "Indicateurs Redis", + "home.tutorials.redisMetrics.shortDescription": "Récupérez des indicateurs internes depuis Redis.", + "home.tutorials.santaLogs.artifacts.dashboards.linkLabel": "Aperçu de Santa", + "home.tutorials.santaLogs.longDescription": "Le module collecte et analyse les logs de [Google Santa](https://github.com/google/santa), un outil de sécurité pour macOS qui monitore les exécutions de processus et est capable de mettre en liste noire/blanche des fichiers binaires. [En savoir plus]({learnMoreLink}).", + "home.tutorials.santaLogs.nameTitle": "Logs Google Santa", + "home.tutorials.santaLogs.shortDescription": "Collectez des logs Google Santa relatifs aux exécutions de processus sur MacOS.", + "home.tutorials.sonicwallLogs.longDescription": "Ce module permet de recevoir des logs Sonicwall FW par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.sonicwallLogs.nameTitle": "Logs Sonicwall FW", + "home.tutorials.sonicwallLogs.shortDescription": "Collectez des logs Sonicwall FW par le biais de Syslog ou d’un fichier.", + "home.tutorials.sophosLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.sophosLogs.longDescription": "Il s'agit d'un module pour les produits Sophos. Actuellement, il prend en charge les logs XG SFOS envoyés au format Syslog. [En savoir plus]({learnMoreLink}).", + "home.tutorials.sophosLogs.nameTitle": "Logs Sophos", + "home.tutorials.sophosLogs.shortDescription": "Collectez des logs Sophos XG SFOS par le biais de Syslog.", + "home.tutorials.squidLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.squidLogs.longDescription": "Ce module permet de recevoir des logs Squid par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.squidLogs.nameTitle": "Logs Squid", + "home.tutorials.squidLogs.shortDescription": "Collectez des logs Squid par le biais de Syslog ou d’un fichier.", + "home.tutorials.stanMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs Stan", + "home.tutorials.stanMetrics.longDescription": "Le module Metricbeat \"stan\" récupère des indicateurs de monitoring depuis STAN. [En savoir plus]({learnMoreLink}).", + "home.tutorials.stanMetrics.nameTitle": "Indicateurs STAN", + "home.tutorials.stanMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis le serveur STAN.", + "home.tutorials.statsdMetrics.longDescription": "Le module Metricbeat \"statsd\" récupère des indicateurs de monitoring depuis statsd. [En savoir plus]({learnMoreLink}).", + "home.tutorials.statsdMetrics.nameTitle": "Indicateurs statsd", + "home.tutorials.statsdMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis statsd.", + "home.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Aperçu des événements Suricata", + "home.tutorials.suricataLogs.longDescription": "Il s'agit d'un module pour le log IDS/IPS/NSM Suricata. Il analyse les logs qui sont au [format JSON Suricata Eve](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html). [En savoir plus]({learnMoreLink}).", + "home.tutorials.suricataLogs.nameTitle": "Logs Suricata", + "home.tutorials.suricataLogs.shortDescription": "Collectez des logs IDS/IPS/NSM Suricata.", + "home.tutorials.systemLogs.artifacts.dashboards.linkLabel": "Tableau de bord Syslog système", + "home.tutorials.systemLogs.longDescription": "Le module collecte et analyse les logs créés par le service de logging système des distributions basées sur Unix/Linux communes. [En savoir plus]({learnMoreLink}).", + "home.tutorials.systemLogs.nameTitle": "Logs système", + "home.tutorials.systemLogs.shortDescription": "Collectez des logs système des distributions basées sur Unix/Linux communes.", + "home.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs système", + "home.tutorials.systemMetrics.longDescription": "Le module Metricbeat \"system\" collecte des statistiques relatives au CPU, à la mémoire, au réseau et au disque depuis l'hôte. Il collecte des statistiques au niveau du système et des statistiques par processus et système de fichiers. [En savoir plus]({learnMoreLink}).", + "home.tutorials.systemMetrics.nameTitle": "Indicateurs système", + "home.tutorials.systemMetrics.shortDescription": "Collectez des statistiques relatives au CPU, à la mémoire, au réseau et au disque depuis l'hôte.", + "home.tutorials.tomcatLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.tomcatLogs.longDescription": "Ce module permet de recevoir des logs Apache Tomcat par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.tomcatLogs.nameTitle": "Logs Tomcat", + "home.tutorials.tomcatLogs.shortDescription": "Collectez des logs Apache Tomcat par le biais de Syslog ou d’un fichier.", + "home.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Logs d'accès Traefik", + "home.tutorials.traefikLogs.longDescription": "Le module analyse les logs d'accès créés par [Traefik](https://traefik.io/). [En savoir plus]({learnMoreLink}).", + "home.tutorials.traefikLogs.nameTitle": "Logs Traefik", + "home.tutorials.traefikLogs.shortDescription": "Collectez des logs d'accès Traefik.", + "home.tutorials.traefikMetrics.longDescription": "Le module Metricbeat \"traefik\" récupère des indicateurs de monitoring depuis Traefik. [En savoir plus]({learnMoreLink}).", + "home.tutorials.traefikMetrics.nameTitle": "Indicateurs Traefik", + "home.tutorials.traefikMetrics.shortDescription": "Récupérez des indicateurs de monitoring depuis Traefik.", + "home.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "Application Uptime", + "home.tutorials.uptimeMonitors.longDescription": "Monitorez la disponibilité des services grâce à une détection active. À partir d'une liste d'URL, Heartbeat pose cette question toute simple : Êtes-vous actif ? [En savoir plus]({learnMoreLink}).", + "home.tutorials.uptimeMonitors.nameTitle": "Monitorings Uptime", + "home.tutorials.uptimeMonitors.shortDescription": "Monitorer la disponibilité des services", + "home.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "Tableau de bord des indicateurs uWSGI", + "home.tutorials.uwsgiMetrics.longDescription": "Le module Metricbeat \"uwsgi\" récupère des indicateurs internes depuis le serveur uWSGI. [En savoir plus]({learnMoreLink}).", + "home.tutorials.uwsgiMetrics.nameTitle": "Indicateurs uWSGI", + "home.tutorials.uwsgiMetrics.shortDescription": "Récupérez des indicateurs internes depuis le serveur uWSGI.", + "home.tutorials.vsphereMetrics.artifacts.application.label": "Discover", + "home.tutorials.vsphereMetrics.longDescription": "Le module Metricbeat \"vsphere\" récupère des indicateurs internes depuis un cluster vSphere. [En savoir plus]({learnMoreLink}).", + "home.tutorials.vsphereMetrics.nameTitle": "Indicateurs vSphere", + "home.tutorials.vsphereMetrics.shortDescription": "Récupérez des indicateurs internes depuis vSphere.", + "home.tutorials.windowsEventLogs.artifacts.application.label": "Application SIEM", + "home.tutorials.windowsEventLogs.longDescription": "Utilisez Winlogbeat pour collecter des logs depuis le log des événements Windows. [En savoir plus]({learnMoreLink}).", + "home.tutorials.windowsEventLogs.nameTitle": "Log des événements Windows", + "home.tutorials.windowsEventLogs.shortDescription": "Récupérez des logs depuis le log des événements Windows.", + "home.tutorials.windowsMetrics.artifacts.application.label": "Discover", + "home.tutorials.windowsMetrics.longDescription": "Le module Metricbeat \"windows\" récupère des indicateurs internes depuis Windows. [En savoir plus]({learnMoreLink}).", + "home.tutorials.windowsMetrics.nameTitle": "Indicateurs Windows", + "home.tutorials.windowsMetrics.shortDescription": "Récupérez des indicateurs internes depuis Windows.", + "home.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Aperçu de Zeek", + "home.tutorials.zeekLogs.longDescription": "Il s'agit d'un module pour Zeek, anciennement appelé Bro. Il analyse les logs qui sont au [format JSON Zeek](https://www.zeek.org/manual/release/logs/index.html). [En savoir plus]({learnMoreLink}).", + "home.tutorials.zeekLogs.nameTitle": "Logs Zeek", + "home.tutorials.zeekLogs.shortDescription": "Collectez les logs de monitoring de la sécurité réseau Zeek.", + "home.tutorials.zookeeperMetrics.artifacts.application.label": "Discover", + "home.tutorials.zookeeperMetrics.longDescription": "Le module Metricbeat \"{moduleName}\" récupère des indicateurs internes depuis un serveur Zookeeper. [En savoir plus]({learnMoreLink}).", + "home.tutorials.zookeeperMetrics.nameTitle": "Indicateurs Zookeeper", + "home.tutorials.zookeeperMetrics.shortDescription": "Récupérez des indicateurs internes depuis un serveur Zookeeper.", + "home.tutorials.zscalerLogs.artifacts.dashboards.linkLabel": "Application Security", + "home.tutorials.zscalerLogs.longDescription": "Ce module permet de recevoir des logs Zscaler NSS par le biais de Syslog ou d'un fichier. [En savoir plus]({learnMoreLink}).", + "home.tutorials.zscalerLogs.nameTitle": "Logs Zscaler", + "home.tutorials.zscalerLogs.shortDescription": "Ce module permet de recevoir des logs Zscaler NSS par le biais de Syslog ou d'un fichier.", + "home.welcomeTitle": "Bienvenue dans Elastic", + "indexPatternEditor.aliasLabel": "Alias", + "indexPatternEditor.createIndex.noMatch": "Le nom doit correspondre à au moins un flux de données, index ou alias d'index.", + "indexPatternEditor.createIndexPattern.emptyState.checkDataButton": "Rechercher de nouvelles données", + "indexPatternEditor.createIndexPattern.emptyState.haveData": "Vous pensez avoir déjà des données ?", + "indexPatternEditor.createIndexPattern.emptyState.integrationCardDescription": "Ajoutez des données depuis une variété de sources.", + "indexPatternEditor.createIndexPattern.emptyState.integrationCardTitle": "Ajouter une intégration", + "indexPatternEditor.createIndexPattern.emptyState.learnMore": "Envie d'en savoir plus ?", + "indexPatternEditor.createIndexPattern.emptyState.noDataTitle": "Vous êtes prêt à essayer Kibana ? Tout d'abord, vous avez besoin de données.", + "indexPatternEditor.createIndexPattern.emptyState.readDocs": "Lire la documentation", + "indexPatternEditor.createIndexPattern.emptyState.sampleDataCardDescription": "Chargez un ensemble de données et un tableau de bord Kibana.", + "indexPatternEditor.createIndexPattern.emptyState.sampleDataCardTitle": "Ajouter un exemple de données", + "indexPatternEditor.createIndexPattern.emptyState.uploadCardDescription": "Importez un fichier CSV, NDJSON ou log.", + "indexPatternEditor.createIndexPattern.emptyState.uploadCardTitle": "Charger un fichier", + "indexPatternEditor.createIndexPattern.stepTime.noTimeFieldOptionLabel": "--- Je ne souhaite pas utiliser le filtre temporel ---", + "indexPatternEditor.dataStreamLabel": "Flux de données", + "indexPatternEditor.editor.emptyPrompt.flyoutCloseButtonLabel": "Fermer", + "indexPatternEditor.editor.flyoutCloseButtonLabel": "Fermer", + "indexPatternEditor.editor.flyoutSaveButtonLabel": "Créer un modèle d'indexation", + "indexPatternEditor.editor.form.advancedSettings.hideButtonLabel": "Masquer les paramètres avancés", + "indexPatternEditor.editor.form.advancedSettings.showButtonLabel": "Afficher les paramètres avancés", + "indexPatternEditor.editor.form.allowHiddenLabel": "Autoriser les index masqués et système", + "indexPatternEditor.editor.form.customIdHelp": "Kibana fournit un identifiant unique pour chaque modèle d'indexation, ou vous pouvez en créer un vous-même.", + "indexPatternEditor.editor.form.customIdLabel": "ID de modèle d'indexation personnalisé", + "indexPatternEditor.editor.form.noTimeFieldsLabel": "Aucun flux de données, index ni alias d'index correspondant ne dispose d'un champ d'horodatage.", + "indexPatternEditor.editor.form.runtimeType.placeholderLabel": "Sélectionner un champ d'horodatage", + "indexPatternEditor.editor.form.timeFieldHelp": "Sélectionnez le champ d'horodatage à utiliser avec le filtre temporel global.", + "indexPatternEditor.editor.form.timeFieldLabel": "Champ d'horodatage", + "indexPatternEditor.editor.form.timestampFieldHelp": "Sélectionnez le champ d'horodatage à utiliser avec le filtre temporel global.", + "indexPatternEditor.editor.form.timestampSelectAriaLabel": "Champ d'horodatage", + "indexPatternEditor.editor.form.titleLabel": "Nom", + "indexPatternEditor.editor.form.TypeLabel": "Type de modèle d'indexation", + "indexPatternEditor.editor.form.typeSelectAriaLabel": "Champ Type", + "indexPatternEditor.emptyIndexPatternPrompt.documentation": "Lire la documentation", + "indexPatternEditor.emptyIndexPatternPrompt.learnMore": "Envie d'en savoir plus ?", + "indexPatternEditor.emptyIndexPatternPrompt.youHaveData": "Vous avez des données dans Elasticsearch.", + "indexPatternEditor.form.allowHiddenAriaLabel": "Autoriser les index masqués et système", + "indexPatternEditor.form.customIndexPatternIdLabel": "ID de modèle d'indexation personnalisé", + "indexPatternEditor.form.titleAriaLabel": "Champ de titre", + "indexPatternEditor.frozenLabel": "Gelé", + "indexPatternEditor.indexLabel": "Index", + "indexPatternEditor.loadingHeader": "Recherche d'index correspondants…", + "indexPatternEditor.pagingLabel": "Lignes par page : {perPage}", + "indexPatternEditor.requireTimestampOption.ValidationErrorMessage": "Sélectionnez un champ d'horodatage.", + "indexPatternEditor.rollup.uncaughtError": "Erreur de modèle d'indexation de cumul : {error}", + "indexPatternEditor.rollupIndexPattern.warning.title": "Fonctionnalité bêta", + "indexPatternEditor.rollupLabel": "Cumul", + "indexPatternEditor.saved": "\"{indexPatternTitle}\" enregistré", + "indexPatternEditor.status.matchAnyLabel.matchAnyDetail": "Votre modèle d'indexation peut correspondre à {sourceCount, plural, one {# source} other {# sources} }.", + "indexPatternEditor.status.noSystemIndicesLabel": "Aucun flux de données, index ni alias d'index ne correspond à votre modèle d'indexation.", + "indexPatternEditor.status.noSystemIndicesWithPromptLabel": "Aucun flux de données, index ni alias d'index ne correspond à votre modèle d'indexation.", + "indexPatternEditor.status.notMatchLabel.allIndicesLabel": "{indicesLength, plural, one {# source} other {# sources} }", + "indexPatternEditor.status.notMatchLabel.notMatchDetail": "Le modèle d'indexation spécifié ne correspond à aucun flux de données, index ni alias d'index. Vous pouvez faire correspondre {strongIndices}.", + "indexPatternEditor.status.notMatchLabel.notMatchNoIndicesDetail": "Le modèle d'indexation spécifié ne correspond à aucun flux de données, index ni alias d'index.", + "indexPatternEditor.status.partialMatchLabel.partialMatchDetail": "Votre modèle d'indexation ne correspond à aucun flux de données, index ni alias d'index, mais {strongIndices} {matchedIndicesLength, plural, one {est semblable} other {sont semblables} }.", + "indexPatternEditor.status.partialMatchLabel.strongIndicesLabel": "{matchedIndicesLength, plural, one {source} other {# sources} }", + "indexPatternEditor.status.successLabel.successDetail": "Votre modèle d'indexation correspond à {sourceCount} {sourceCount, plural, one {source} other {sources} }.", + "indexPatternEditor.title": "Créer un modèle d'indexation", + "indexPatternEditor.typeSelect.betaLabel": "Bêta", + "indexPatternEditor.typeSelect.rollup": "Cumul", + "indexPatternEditor.typeSelect.rollupDescription": "Effectuer des agrégations limitées à partir de données résumées", + "indexPatternEditor.typeSelect.rollupTitle": "Modèle d'indexation de cumul", + "indexPatternEditor.typeSelect.standard": "Standard", + "indexPatternEditor.typeSelect.standardDescription": "Effectuer des agrégations complètes à partir de n'importe quelles données", + "indexPatternEditor.typeSelect.standardTitle": "Modèle d'indexation standard", + "indexPatternEditor.validations.titleHelpText": "Utilisez un astérisque (*) pour faire correspondre plusieurs caractères. Les espaces et les caractères , /, ?, \", <, >, | ne sont pas autorisés.", + "indexPatternEditor.validations.titleIsRequiredErrorMessage": "Nom obligatoire.", + "indexPatternFieldEditor.cancelField.confirmationModal.cancelButtonLabel": "Annuler", + "indexPatternFieldEditor.cancelField.confirmationModal.description": "Les modifications apportées à votre champ seront ignorées. Voulez-vous vraiment continuer ?", + "indexPatternFieldEditor.cancelField.confirmationModal.title": "Ignorer les modifications", + "indexPatternFieldEditor.color.actions": "Actions", + "indexPatternFieldEditor.color.addColorButton": "Ajouter une couleur", + "indexPatternFieldEditor.color.backgroundLabel": "Couleur d'arrière-plan", + "indexPatternFieldEditor.color.deleteAria": "Supprimer", + "indexPatternFieldEditor.color.deleteTitle": "Supprimer le format de couleur", + "indexPatternFieldEditor.color.exampleLabel": "Exemple", + "indexPatternFieldEditor.color.patternLabel": "Modèle (expression régulière)", + "indexPatternFieldEditor.color.rangeLabel": "Plage (min:max)", + "indexPatternFieldEditor.color.textColorLabel": "Couleur du texte", + "indexPatternFieldEditor.createField.flyoutAriaLabel": "Créer un champ", + "indexPatternFieldEditor.date.documentationLabel": "Documentation", + "indexPatternFieldEditor.date.momentLabel": "Modèle de format Moment.js (par défaut : {defaultPattern})", + "indexPatternFieldEditor.defaultErrorMessage": "Une erreur s'est produite lors de l'utilisation de cette configuration de format : {message}.", + "indexPatternFieldEditor.defaultFormatDropDown": "- Par défaut -", + "indexPatternFieldEditor.defaultFormatHeader": "Format (par défaut : {defaultFormat})", + "indexPatternFieldEditor.deleteField.savedHeader": "\"{fieldName}\" enregistré", + "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.cancelButtonLabel": "Annuler", + "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeButtonLabel": "Supprimer le champ", + "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeMultipleButtonLabel": "Supprimer les champs", + "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.saveButtonLabel": "Enregistrer les modifications", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteMultipleTitle": "Supprimer {count} champs", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteSingleTitle": "Supprimer le champ \"{name}\"", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.multipleDeletionDescription": "Vous êtes sur le point de supprimer les champs d'exécution suivants :", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.typeConfirm": "Saisissez REMOVE pour confirmer.", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.warningChangingFields": "Modifier le nom ou le type peut affecter les recherches et les visualisations utilisant ce champ.", + "indexPatternFieldEditor.deleteRuntimeField.confirmModal.warningRemovingFields": "Supprimer un champ peut affecter les recherches et les visualisations utilisant ce champ.", + "indexPatternFieldEditor.duration.decimalPlacesLabel": "Décimales", + "indexPatternFieldEditor.duration.includeSpace": "Inclure un espace entre le suffixe et la valeur", + "indexPatternFieldEditor.duration.inputFormatLabel": "Format d'entrée", + "indexPatternFieldEditor.duration.outputFormatLabel": "Format de sortie", + "indexPatternFieldEditor.duration.showSuffixLabel": "Afficher le suffixe", + "indexPatternFieldEditor.duration.showSuffixLabel.short": "Utiliser un suffixe court", + "indexPatternFieldEditor.durationErrorMessage": "Le nombre de décimales doit être compris entre 0 et 20.", + "indexPatternFieldEditor.editField.flyoutAriaLabel": "Modifier le champ {fieldName}", + "indexPatternFieldEditor.editor.flyoutCancelButtonLabel": "Annuler", + "indexPatternFieldEditor.editor.flyoutDefaultTitle": "Créer un champ", + "indexPatternFieldEditor.editor.flyoutEditFieldSubtitle": "Modèle d'indexation : {patternName}", + "indexPatternFieldEditor.editor.flyoutEditFieldTitle": "Modifier le champ \"{fieldName}\"", + "indexPatternFieldEditor.editor.flyoutSaveButtonLabel": "Enregistrer", + "indexPatternFieldEditor.editor.form.advancedSettings.hideButtonLabel": "Masquer les paramètres avancés", + "indexPatternFieldEditor.editor.form.advancedSettings.showButtonLabel": "Afficher les paramètres avancés", + "indexPatternFieldEditor.editor.form.changeWarning": "Modifier le nom ou le type peut affecter les recherches et les visualisations utilisant ce champ.", + "indexPatternFieldEditor.editor.form.customLabelDescription": "Créez une étiquette à afficher à la place du nom du champ dans Discover, Maps et Visualize. Utile pour raccourcir un nom de champ long. Les requêtes et les filtres utilisent le nom de champ d'origine.", + "indexPatternFieldEditor.editor.form.customLabelLabel": "Étiquette personnalisée", + "indexPatternFieldEditor.editor.form.customLabelTitle": "Définir une étiquette personnalisée", + "indexPatternFieldEditor.editor.form.defineFieldLabel": "Définir un script", + "indexPatternFieldEditor.editor.form.fieldShadowingCalloutDescription": "Ce champ partage le nom d'un champ mappé. Les valeurs de ce champ seront renvoyées dans les résultats de recherche.", + "indexPatternFieldEditor.editor.form.fieldShadowingCalloutTitle": "Masquage de champ", + "indexPatternFieldEditor.editor.form.formatDescription": "Définissez votre format de prédilection pour l'affichage de la valeur. Changer le format peut avoir un impact sur la valeur et empêcher la mise en surbrillance dans Discover.", + "indexPatternFieldEditor.editor.form.formatTitle": "Définir le format", + "indexPatternFieldEditor.editor.form.nameAriaLabel": "Champ Nom", + "indexPatternFieldEditor.editor.form.nameLabel": "Nom", + "indexPatternFieldEditor.editor.form.popularityDescription": "Définissez la popularité pour que le champ apparaisse plus haut ou plus bas dans la liste des champs. Par défaut, Discover classe les champs du plus souvent sélectionné au moins souvent sélectionné.", + "indexPatternFieldEditor.editor.form.popularityLabel": "Popularité", + "indexPatternFieldEditor.editor.form.popularityTitle": "Définir la popularité", + "indexPatternFieldEditor.editor.form.runtimeType.placeholderLabel": "Sélectionner un type", + "indexPatternFieldEditor.editor.form.runtimeTypeLabel": "Type", + "indexPatternFieldEditor.editor.form.script.learnMoreLinkText": "En savoir plus sur la syntaxe de script.", + "indexPatternFieldEditor.editor.form.scriptEditor.compileErrorMessage": "Erreur lors de la compilation du script Painless", + "indexPatternFieldEditor.editor.form.scriptEditorAriaLabel": "Éditeur de script", + "indexPatternFieldEditor.editor.form.source.scriptFieldHelpText": "Les champs d'exécution sans script récupèrent les valeurs de {source}. Si un champ n'existe pas dans _source, la recherche ne renvoie pas de valeur. {learnMoreLink}", + "indexPatternFieldEditor.editor.form.typeSelectAriaLabel": "Sélection du type", + "indexPatternFieldEditor.editor.form.validations.customLabelIsRequiredErrorMessage": "Spécifiez une étiquette pour le champ.", + "indexPatternFieldEditor.editor.form.validations.nameIsRequiredErrorMessage": "Nom obligatoire.", + "indexPatternFieldEditor.editor.form.validations.popularityGreaterThan0ErrorMessage": "La popularité doit être définie sur 0 ou plus.", + "indexPatternFieldEditor.editor.form.validations.popularityIsRequiredErrorMessage": "Spécifiez la popularité du champ.", + "indexPatternFieldEditor.editor.form.validations.scriptIsRequiredErrorMessage": "Un script est obligatoire pour définir la valeur du champ.", + "indexPatternFieldEditor.editor.form.valueDescription": "Définissez une valeur pour le champ au lieu de la récupérer à partir du champ portant le même nom dans {source}.", + "indexPatternFieldEditor.editor.form.valueTitle": "Définir la valeur", + "indexPatternFieldEditor.editor.runtimeFieldsEditor.existRuntimeFieldNamesValidationErrorMessage": "Un champ portant ce nom existe déjà.", + "indexPatternFieldEditor.fieldPreview.documentIdField.label": "ID du document", + "indexPatternFieldEditor.fieldPreview.documentIdField.loadDocumentsFromCluster": "Charger des documents depuis le cluster", + "indexPatternFieldEditor.fieldPreview.documentNav.nextArialabel": "Document suivant", + "indexPatternFieldEditor.fieldPreview.documentNav.previousArialabel": "Document précédent", + "indexPatternFieldEditor.fieldPreview.emptyPromptDescription": "Saisissez le nom d'un champ existant ou définissez un script pour afficher un aperçu de la sortie calculée.", + "indexPatternFieldEditor.fieldPreview.emptyPromptTitle": "Aperçu", + "indexPatternFieldEditor.fieldPreview.error.documentNotFoundDescription": "ID du document introuvable", + "indexPatternFieldEditor.fieldPreview.errorCallout.title": "Erreur d'aperçu", + "indexPatternFieldEditor.fieldPreview.errorTitle": "Échec du chargement de l'aperçu du champ", + "indexPatternFieldEditor.fieldPreview.filterFieldsPlaceholder": "Champs de filtre", + "indexPatternFieldEditor.fieldPreview.pinFieldButtonLabel": "Épingler le champ", + "indexPatternFieldEditor.fieldPreview.searchResult.emptyPrompt.clearSearchButtonLabel": "Effacer la recherche", + "indexPatternFieldEditor.fieldPreview.searchResult.emptyPromptTitle": "Aucun champ correspondant dans ce modèle d'indexation", + "indexPatternFieldEditor.fieldPreview.showLessFieldsButtonLabel": "Afficher moins", + "indexPatternFieldEditor.fieldPreview.showMoreFieldsButtonLabel": "Afficher plus", + "indexPatternFieldEditor.fieldPreview.subTitle": "Depuis : {from}", + "indexPatternFieldEditor.fieldPreview.subTitle.customData": "Données personnalisées", + "indexPatternFieldEditor.fieldPreview.title": "Aperçu", + "indexPatternFieldEditor.fieldPreview.updatingPreviewLabel": "Mise à jour en cours...", + "indexPatternFieldEditor.fieldPreview.viewImageButtonLabel": "Afficher l'image", + "indexPatternFieldEditor.formatHeader": "Format", + "indexPatternFieldEditor.histogram.histogramAsNumberLabel": "Format de nombre agrégé", + "indexPatternFieldEditor.histogram.numeralLabel": "Modèle de format numérique (facultatif)", + "indexPatternFieldEditor.histogram.subFormat.bytes": "Octets", + "indexPatternFieldEditor.histogram.subFormat.number": "Nombre", + "indexPatternFieldEditor.histogram.subFormat.percent": "Pourcentage", + "indexPatternFieldEditor.noSuchFieldName": "Champ \"{fieldName}\" introuvable dans le modèle d'indexation", + "indexPatternFieldEditor.number.documentationLabel": "Documentation", + "indexPatternFieldEditor.number.numeralLabel": "Modèle de format Numeral.js (par défaut : {defaultPattern})", + "indexPatternFieldEditor.samples.inputHeader": "Entrée", + "indexPatternFieldEditor.samples.outputHeader": "Sortie", + "indexPatternFieldEditor.samplesHeader": "Exemples", + "indexPatternFieldEditor.save.deleteErrorTitle": "Impossible d'enregistrer la suppression du champ", + "indexPatternFieldEditor.save.errorTitle": "Impossible d'enregistrer la modification du champ", + "indexPatternFieldEditor.saveRuntimeField.confirmationModal.cancelButtonLabel": "Annuler", + "indexPatternFieldEditor.saveRuntimeField.confirmModal.title": "Enregistrer les modifications apportées à \"{name}\"", + "indexPatternFieldEditor.saveRuntimeField.confirmModal.typeConfirm": "Saisissez CHANGE pour continuer.", + "indexPatternFieldEditor.staticLookup.actions": "actions", + "indexPatternFieldEditor.staticLookup.addEntryButton": "Ajouter une entrée", + "indexPatternFieldEditor.staticLookup.deleteAria": "Supprimer", + "indexPatternFieldEditor.staticLookup.deleteTitle": "Supprimer l’entrée", + "indexPatternFieldEditor.staticLookup.keyLabel": "Clé", + "indexPatternFieldEditor.staticLookup.leaveBlankPlaceholder": "Laisser vide pour conserver la valeur telle quelle", + "indexPatternFieldEditor.staticLookup.unknownKeyLabel": "Valeur pour clé inconnue", + "indexPatternFieldEditor.staticLookup.valueLabel": "Valeur", + "indexPatternFieldEditor.string.transformLabel": "Transformer", + "indexPatternFieldEditor.truncate.lengthLabel": "Longueur du champ", + "indexPatternFieldEditor.url.heightLabel": "Hauteur", + "indexPatternFieldEditor.url.labelTemplateHelpText": "Aide sur le modèle d'étiquette", + "indexPatternFieldEditor.url.labelTemplateLabel": "Modèle d'étiquette", + "indexPatternFieldEditor.url.offLabel": "Off", + "indexPatternFieldEditor.url.onLabel": "On", + "indexPatternFieldEditor.url.openTabLabel": "Ouvrir dans un nouvel onglet", + "indexPatternFieldEditor.url.template.helpLinkText": "Aide sur le modèle d'URL", + "indexPatternFieldEditor.url.typeLabel": "Type", + "indexPatternFieldEditor.url.urlTemplateLabel": "Modèle d'URL", + "indexPatternFieldEditor.url.widthLabel": "Largeur", + "indexPatternManagement.actions.cancelButton": "Annuler", + "indexPatternManagement.actions.createButton": "Créer un champ", + "indexPatternManagement.actions.deleteButton": "Supprimer", + "indexPatternManagement.actions.saveButton": "Enregistrer le champ", + "indexPatternManagement.createHeader": "Créer un champ scripté", + "indexPatternManagement.customLabel": "Étiquette personnalisée", + "indexPatternManagement.defaultFormatDropDown": "- Par défaut -", + "indexPatternManagement.defaultFormatHeader": "Format (par défaut : {defaultFormat})", + "indexPatternManagement.deleteField.cancelButton": "Annuler", + "indexPatternManagement.deleteField.deleteButton": "Supprimer", + "indexPatternManagement.deleteField.deletedHeader": "\"’{fieldName}\" supprimé", + "indexPatternManagement.deleteField.savedHeader": "\"{fieldName}\" enregistré", + "indexPatternManagement.deleteFieldHeader": "Supprimer le champ \"{fieldName}\"", + "indexPatternManagement.deleteFieldLabel": "Il est impossible de récupérer un champ supprimé.{separator}Voulez-vous vraiment continuer ?", + "indexPatternManagement.disabledCallOutHeader": "Scripts désactivés", + "indexPatternManagement.disabledCallOutLabel": "Tous les scripts en ligne ont été désactivés dans Elasticsearch. Vous devez activer les scripts en ligne pour au moins un langage afin d'utiliser des champs scriptés dans Kibana.", + "indexPatternManagement.editHeader": "Modifier {fieldName}", + "indexPatternManagement.editIndexPattern.deleteButton": "Supprimer", + "indexPatternManagement.editIndexPattern.deprecation": "Les champs scriptés sont déclassés. Utilisez {runtimeDocs} à la place.", + "indexPatternManagement.editIndexPattern.fields.addFieldButtonLabel": "Ajouter un champ", + "indexPatternManagement.editIndexPattern.fields.filterAria": "Filtrer les types de champ", + "indexPatternManagement.editIndexPattern.fields.filterPlaceholder": "Rechercher", + "indexPatternManagement.editIndexPattern.fields.searchAria": "Rechercher des champs", + "indexPatternManagement.editIndexPattern.fields.table.additionalInfoAriaLabel": "Informations supplémentaires sur le champ", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableDescription": "Ces champs peuvent être utilisés dans des agrégations de visualisations.", + "indexPatternManagement.editIndexPattern.fields.table.aggregatableLabel": "Regroupable", + "indexPatternManagement.editIndexPattern.fields.table.customLabelTooltip": "Une étiquette personnalisée pour le champ.", + "indexPatternManagement.editIndexPattern.fields.table.deleteDescription": "Supprimer", + "indexPatternManagement.editIndexPattern.fields.table.deleteLabel": "Supprimer", + "indexPatternManagement.editIndexPattern.fields.table.editDescription": "Modifier", + "indexPatternManagement.editIndexPattern.fields.table.editLabel": "Modifier", + "indexPatternManagement.editIndexPattern.fields.table.excludedDescription": "Champs exclus de _source lors de la récupération", + "indexPatternManagement.editIndexPattern.fields.table.excludedLabel": "Exclu", + "indexPatternManagement.editIndexPattern.fields.table.formatHeader": "Format", + "indexPatternManagement.editIndexPattern.fields.table.isAggregatableAria": "Est regroupable", + "indexPatternManagement.editIndexPattern.fields.table.isExcludedAria": "Est exclu", + "indexPatternManagement.editIndexPattern.fields.table.isSearchableAria": "Est interrogeable", + "indexPatternManagement.editIndexPattern.fields.table.nameHeader": "Nom", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeAriaLabel": "Champ temporel principal", + "indexPatternManagement.editIndexPattern.fields.table.primaryTimeTooltip": "Ce champ représente l'heure à laquelle les événements se sont produits.", + "indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitle": "Champ d'exécution", + "indexPatternManagement.editIndexPattern.fields.table.searchableDescription": "Ces champs peuvent être utilisés dans la barre de filtre.", + "indexPatternManagement.editIndexPattern.fields.table.searchableHeader": "Interrogeable", + "indexPatternManagement.editIndexPattern.fields.table.typeHeader": "Type", + "indexPatternManagement.editIndexPattern.list.DateHistogramDelaySummary": "retard : {delay},", + "indexPatternManagement.editIndexPattern.list.dateHistogramSummary": "{aggName} (intervalle : {interval}, {delay} {time_zone})", + "indexPatternManagement.editIndexPattern.list.defaultIndexPatternListName": "Par défaut", + "indexPatternManagement.editIndexPattern.list.histogramSummary": "{aggName} (intervalle : {interval})", + "indexPatternManagement.editIndexPattern.list.rollupIndexPatternListName": "Cumul", + "indexPatternManagement.editIndexPattern.mappingConflictHeader": "Conflit de mapping", + "indexPatternManagement.editIndexPattern.mappingConflictLabel": "{conflictFieldsLength, plural, one {Un champ est défini} other {# champs sont définis}} avec plusieurs types (chaîne, entier, etc.) dans les différents index qui correspondent à ce modèle. Vous pourrez peut-être utiliser ce ou ces champs en conflit dans certaines parties de Kibana, mais ils ne seront pas disponibles pour les fonctions qui nécessitent que Kibana connaisse leur type. Pour corriger ce problème, vous devrez réindexer vos données.", + "indexPatternManagement.editIndexPattern.scripted.addFieldButton": "Ajouter un champ scripté", + "indexPatternManagement.editIndexPattern.scripted.deleteField.cancelButton": "Annuler", + "indexPatternManagement.editIndexPattern.scripted.deleteField.deleteButton": "Supprimer", + "indexPatternManagement.editIndexPattern.scripted.deleteFieldLabel": "Supprimer le champ scripté \"{fieldName}\" ?", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangHeader": "Langages déclassés en cours d'utilisation", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "Les langages déclassés suivants sont en cours d'utilisation : {deprecatedLangsInUse}. La prise en charge de ces langages sera supprimée dans la prochaine version majeure de Kibana et d'Elasticsearch. Convertissez vos champs scriptés en {link} pour éviter tout problème.", + "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "Painless", + "indexPatternManagement.editIndexPattern.scripted.newFieldPlaceholder": "Nouveau champ scripté", + "indexPatternManagement.editIndexPattern.scripted.table.deleteDescription": "Supprimer ce champ", + "indexPatternManagement.editIndexPattern.scripted.table.deleteHeader": "Supprimer", + "indexPatternManagement.editIndexPattern.scripted.table.editDescription": "Modifier ce champ", + "indexPatternManagement.editIndexPattern.scripted.table.editHeader": "Modifier", + "indexPatternManagement.editIndexPattern.scripted.table.formatDescription": "Format utilisé pour le champ", + "indexPatternManagement.editIndexPattern.scripted.table.formatHeader": "Format", + "indexPatternManagement.editIndexPattern.scripted.table.langDescription": "Langage utilisé pour le champ", + "indexPatternManagement.editIndexPattern.scripted.table.langHeader": "Lang", + "indexPatternManagement.editIndexPattern.scripted.table.nameDescription": "Nom du champ", + "indexPatternManagement.editIndexPattern.scripted.table.nameHeader": "Nom", + "indexPatternManagement.editIndexPattern.scripted.table.scriptDescription": "Script pour le champ", + "indexPatternManagement.editIndexPattern.scripted.table.scriptHeader": "Script", + "indexPatternManagement.editIndexPattern.scriptedLabel": "Les champs scriptés peuvent être utilisés dans des visualisations et affichés dans des documents. Ils ne peuvent cependant pas faire l'objet d'une recherche.", + "indexPatternManagement.editIndexPattern.source.addButtonLabel": "Ajouter", + "indexPatternManagement.editIndexPattern.source.deleteFilter.cancelButtonLabel": "Annuler", + "indexPatternManagement.editIndexPattern.source.deleteFilter.deleteButtonLabel": "Supprimer", + "indexPatternManagement.editIndexPattern.source.deleteSourceFilterLabel": "Supprimer le filtre de champ \"{value}\" ?", + "indexPatternManagement.editIndexPattern.source.noteLabel": "Notez que les champs multiples apparaîtront incorrectement comme des correspondances dans le tableau ci-dessous. Ces filtres ne s'appliquent qu'aux champs dans le document source d'origine. Par conséquent, les champs multiples ne sont pas réellement filtrés.", + "indexPatternManagement.editIndexPattern.source.table.cancelAria": "Annuler", + "indexPatternManagement.editIndexPattern.source.table.deleteAria": "Supprimer", + "indexPatternManagement.editIndexPattern.source.table.editAria": "Modifier", + "indexPatternManagement.editIndexPattern.source.table.filterDescription": "Nom du filtre", + "indexPatternManagement.editIndexPattern.source.table.filterHeader": "Filtre", + "indexPatternManagement.editIndexPattern.source.table.matchesDescription": "Langage utilisé pour le champ", + "indexPatternManagement.editIndexPattern.source.table.matchesHeader": "Correspondances", + "indexPatternManagement.editIndexPattern.source.table.notMatchedLabel": "Le filtre source ne correspond à aucun champ connu.", + "indexPatternManagement.editIndexPattern.source.table.saveAria": "Enregistrer", + "indexPatternManagement.editIndexPattern.sourceLabel": "Les filtres de champ peuvent être utilisés pour exclure un ou plusieurs champs lors de la récupération d'un document. Cela se produit lors de l'affichage d'un document dans l'application Discover ou avec un tableau affichant les résultats d'une recherche enregistrée dans l'application Dashboard. Si vous avez des documents avec des champs de grande taille ou peu importants, il pourrait être utile de filtrer ces champs à ce niveau plus bas.", + "indexPatternManagement.editIndexPattern.sourcePlaceholder": "filtre de champ, accepte les caractères génériques (par ex. \"utilisateur*\" pour filtrer les champs commençant par \"utilisateur\")", + "indexPatternManagement.editIndexPattern.tabs.fieldsHeader": "Champs", + "indexPatternManagement.editIndexPattern.tabs.scriptedHeader": "Champs scriptés", + "indexPatternManagement.editIndexPattern.tabs.sourceHeader": "Filtres de champ", + "indexPatternManagement.editIndexPattern.timeFilterHeader": "Champ temporel : \"{timeFieldName}\"", + "indexPatternManagement.editIndexPattern.timeFilterLabel.mappingAPILink": "mappings de champ", + "indexPatternManagement.editIndexPattern.timeFilterLabel.timeFilterDetail": "Affichez et modifiez les champs dans {indexPatternTitle}. Les attributs de champ tels que le type et le niveau de recherche sont basés sur {mappingAPILink} dans Elasticsearch.", + "indexPatternManagement.fieldTypeConflict": "Conflit de type de champ", + "indexPatternManagement.formatHeader": "Format", + "indexPatternManagement.formatLabel": "La mise en forme vous permet de contrôler la façon dont des valeurs spécifiques sont affichées. Cela peut également entraîner une modification complète des valeurs et empêcher la mise en surbrillance dans Discover de fonctionner.", + "indexPatternManagement.header.runtimeLink": "champs d'exécution", + "indexPatternManagement.indexNameLabel": "Nom des index", + "indexPatternManagement.indexPatterns.badge.readOnly.text": "Lecture seule", + "indexPatternManagement.indexPatterns.createFieldBreadcrumb": "Créer un champ", + "indexPatternManagement.labelHelpText": "Définissez une étiquette personnalisée à utiliser lorsque ce champ est affiché dans Discover, Maps et Visualize. Actuellement, les requêtes et les filtres ne prennent pas en charge les étiquettes personnalisées et utilisent le nom d'origine des champs.", + "indexPatternManagement.languageLabel": "Langage", + "indexPatternManagement.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} Vous avez déjà un champ nommé {fieldName}. Si vous donnez le même nom à votre champ scripté, vous ne pourrez pas interroger les deux champs en même temps.", + "indexPatternManagement.mappingConflictLabel.mappingConflictLabel": "Conflit de mapping :", + "indexPatternManagement.multiTypeLabelDesc": "Le type de ce champ varie selon les index. Il n'est pas disponible pour de nombreuses fonctions d'analyse. Les index par type sont les suivants :", + "indexPatternManagement.nameErrorMessage": "Nom obligatoire", + "indexPatternManagement.nameLabel": "Nom", + "indexPatternManagement.namePlaceholder": "Nouveau champ scripté", + "indexPatternManagement.popularityLabel": "Popularité", + "indexPatternManagement.script.accessWithLabel": "Accédez aux champs avec {code}.", + "indexPatternManagement.script.getHelpLabel": "Obtenez de l'aide pour la syntaxe et prévisualisez les résultats de votre script.", + "indexPatternManagement.scriptedFieldsDeprecatedBody": "Pour profiter de plus de flexibilité et de la prise en charge des scripts Painless, utilisez {runtimeDocs}.", + "indexPatternManagement.scriptedFieldsDeprecatedTitle": "Les champs scriptés sont déclassés.", + "indexPatternManagement.scriptingLanguages.errorFetchingToastDescription": "Erreur lors de l'obtention des langages de script disponibles à partir d'Elasticsearch", + "indexPatternManagement.scriptInvalidErrorMessage": "Script non valide. Voir l'aperçu du script pour plus de détails.", + "indexPatternManagement.scriptLabel": "Script", + "indexPatternManagement.scriptRequiredErrorMessage": "Script obligatoire", + "indexPatternManagement.syntax.default.formatLabel": "doc['some_field'].value", + "indexPatternManagement.syntax.defaultLabel.defaultDetail": "Par défaut, les champs scriptés Kibana emploient {painless}, un langage de script simple et sécurisé spécialement conçu pour Elasticsearch. Pour accéder aux valeurs du document, utilisez le format suivant :", + "indexPatternManagement.syntax.defaultLabel.painlessLink": "Painless", + "indexPatternManagement.syntax.kibanaLabel": "Kibana impose actuellement une limitation spéciale sur les scripts Painless. Ils ne peuvent pas contenir de fonctions nommées.", + "indexPatternManagement.syntax.lucene.commonLabel.commonDetail": "Vous venez d'une ancienne version de Kibana ? Les expressions {lucene} que vous connaissez et adorez sont toujours disponibles. Les expressions Lucene ressemblent beaucoup à du JavaScript, mais elles se limitent aux opérations arithmétiques de base, aux opérations au niveau du bit et aux opérations de comparaison.", + "indexPatternManagement.syntax.lucene.commonLabel.luceneLink": "Expressions Lucene", + "indexPatternManagement.syntax.lucene.limits.fieldsLabel": "Les champs stockés ne sont pas disponibles.", + "indexPatternManagement.syntax.lucene.limits.sparseLabel": "Si un champ est clairsemé (seuls certains documents contiennent une valeur), les documents où ce champ est vide auront une valeur de 0.", + "indexPatternManagement.syntax.lucene.limits.typesLabel": "Seuls les champs numériques, booléens, de date et de point géographique sont accessibles.", + "indexPatternManagement.syntax.lucene.limitsLabel": "L'utilisation d’expressions Lucene implique quelques limitations :", + "indexPatternManagement.syntax.lucene.operations.arithmeticLabel": "Opérateurs arithmétiques : {operators}", + "indexPatternManagement.syntax.lucene.operations.bitwiseLabel": "Opérateurs au niveau du bit : {operators}", + "indexPatternManagement.syntax.lucene.operations.booleanLabel": "Opérateurs booléens (y compris l'opérateur ternaire) : {operators}", + "indexPatternManagement.syntax.lucene.operations.comparisonLabel": "Opérateurs de comparaison : {operators}", + "indexPatternManagement.syntax.lucene.operations.distanceLabel": "Fonctions de distance : {operators}", + "indexPatternManagement.syntax.lucene.operations.mathLabel": "Fonctions mathématiques communes : {operators}", + "indexPatternManagement.syntax.lucene.operations.miscellaneousLabel": "Fonctions diverses : {operators}", + "indexPatternManagement.syntax.lucene.operations.trigLabel": "Fonctions de bibliothèque trigonométrique : {operators}", + "indexPatternManagement.syntax.lucene.operationsLabel": "Voici toutes les opérations disponibles pour les expressions Lucene :", + "indexPatternManagement.syntax.painlessLabel.javaAPIsLink": "API Java natives", + "indexPatternManagement.syntax.painlessLabel.painlessDetail": "Painless est un langage puissant, mais facile à utiliser. Il donne accès à de nombreuses {javaAPIs}. Lisez-en plus sur sa {syntax} et découvrez tout ce que vous devez savoir en un rien de temps !", + "indexPatternManagement.syntax.painlessLabel.syntaxLink": "syntaxe", + "indexPatternManagement.syntaxHeader": "Syntaxe", + "indexPatternManagement.testScript.errorMessage": "Votre script présente une erreur.", + "indexPatternManagement.testScript.fieldsLabel": "Champs supplémentaires", + "indexPatternManagement.testScript.fieldsPlaceholder": "Sélectionner…", + "indexPatternManagement.testScript.instructions": "Exécutez votre script pour prévisualiser les 10 premiers résultats. Vous pouvez également sélectionner des champs supplémentaires à inclure dans les résultats pour obtenir plus de contexte ou ajouter une requête pour filtrer des documents spécifiques.", + "indexPatternManagement.testScript.resultsLabel": "10 premiers résultats", + "indexPatternManagement.testScript.resultsTitle": "Prévisualiser les résultats", + "indexPatternManagement.testScript.submitButtonLabel": "Exécuter le script", + "indexPatternManagement.typeLabel": "Type", + "indexPatternManagement.warningCallOutLabel.callOutDetail": "Familiarisez-vous avec les {scripFields} et les {scriptsInAggregation} avant d'utiliser cette fonctionnalité. Les champs scriptés peuvent être utilisés pour afficher et agréger les valeurs calculées. Dès lors, ils peuvent être très lents et, s'ils ne sont pas faits correctement, ils peuvent rendre Kibana inutilisable.", + "indexPatternManagement.warningCallOutLabel.runtimeLink": "champs d'exécution", + "indexPatternManagement.warningCallOutLabel.scripFieldsLink": "champs scriptés", + "indexPatternManagement.warningCallOutLabel.scriptsInAggregationLink": "scripts en agrégations", + "indexPatternManagement.warningHeader": "Avertissement de déclassement :", + "indexPatternManagement.warningLabel.painlessLinkLabel": "Painless", + "indexPatternManagement.warningLabel.warningDetail": "{language} est déclassé et ne sera plus pris en charge dans la prochaine version majeure de Kibana et d'Elasticsearch. Nous recommandons d'utiliser {painlessLink} pour les nouveaux champs scriptés.", + "inputControl.control.noIndexPatternTooltip": "Impossible de localiser l'ID du modèle d'indexation : {indexPatternId}.", + "inputControl.control.notInitializedTooltip": "Le contrôle n'a pas été initialisé.", + "inputControl.control.noValuesDisableTooltip": "Le filtrage se produit sur le champ \"{fieldName}\", qui n'existe dans aucun document du modèle d'indexation \"{indexPatternName}\". Sélectionnez un champ différent ou des documents d'index qui contiennent des valeurs pour ce champ.", + "inputControl.editor.controlEditor.controlLabel": "Contrôler l'étiquette", + "inputControl.editor.controlEditor.moveControlDownAriaLabel": "Abaisser le contrôle", + "inputControl.editor.controlEditor.moveControlUpAriaLabel": "Remonter le contrôle", + "inputControl.editor.controlEditor.removeControlAriaLabel": "Retirer le contrôle", + "inputControl.editor.controlsTab.addButtonLabel": "Ajouter", + "inputControl.editor.controlsTab.select.addControlAriaLabel": "Ajouter un contrôle", + "inputControl.editor.controlsTab.select.controlTypeAriaLabel": "Choisir le type de contrôle", + "inputControl.editor.controlsTab.select.listDropDownOptionLabel": "Liste des options", + "inputControl.editor.controlsTab.select.rangeDropDownOptionLabel": "Curseur de plage", + "inputControl.editor.fieldSelect.fieldLabel": "Champ", + "inputControl.editor.fieldSelect.selectFieldPlaceholder": "Sélectionner un champ…", + "inputControl.editor.indexPatternSelect.patternLabel": "Modèle d'indexation", + "inputControl.editor.indexPatternSelect.patternPlaceholder": "Sélectionner un modèle d'indexation…", + "inputControl.editor.listControl.dynamicOptions.stringFieldDescription": "Uniquement disponible pour les champs de type chaîne", + "inputControl.editor.listControl.dynamicOptions.updateDescription": "Mettre à jour les options en réponse aux informations fournies par l'utilisateur", + "inputControl.editor.listControl.dynamicOptionsLabel": "Options dynamiques", + "inputControl.editor.listControl.multiselectDescription": "Permettre une sélection multiple", + "inputControl.editor.listControl.multiselectLabel": "Sélection multiple", + "inputControl.editor.listControl.parentDescription": "Les options sont basées sur la valeur du contrôle parent. Désactivé si le parent n'est pas défini.", + "inputControl.editor.listControl.parentLabel": "Contrôle parent", + "inputControl.editor.listControl.sizeDescription": "Nombre d'options", + "inputControl.editor.listControl.sizeLabel": "Taille", + "inputControl.editor.optionsTab.pinFiltersLabel": "Épingler les filtres pour toutes les applications", + "inputControl.editor.optionsTab.updateFilterLabel": "Mettre à jour les filtres Kibana à chaque modification", + "inputControl.editor.optionsTab.useTimeFilterLabel": "Utiliser le filtre temporel", + "inputControl.editor.rangeControl.decimalPlacesLabel": "Décimales", + "inputControl.editor.rangeControl.stepSizeLabel": "Taille de l'étape", + "inputControl.function.help": "Visualisation du contrôle d'entrée", + "inputControl.listControl.disableTooltip": "Désactivé jusqu'à ce que \"{label}\" soit défini.", + "inputControl.listControl.unableToFetchTooltip": "Impossible de récupérer les termes. Erreur : {errorMessage}.", + "inputControl.rangeControl.unableToFetchTooltip": "Impossible de récupérer les valeurs min. et max. de la plage. Erreur : {errorMessage}.", + "inputControl.register.controlsDescription": "Ajoutez des menus déroulants et des curseurs de plage à votre tableau de bord.", + "inputControl.register.controlsTitle": "Contrôles", + "inputControl.register.tabs.controlsTitle": "Contrôles", + "inputControl.register.tabs.optionsTitle": "Options", + "inputControl.vis.inputControlVis.applyChangesButtonLabel": "Appliquer les modifications", + "inputControl.vis.inputControlVis.cancelChangesButtonLabel": "Annuler les modifications", + "inputControl.vis.inputControlVis.clearFormButtonLabel": "Effacer le formulaire", + "inputControl.vis.listControl.partialResultsWarningMessage": "La liste des termes peut être incomplète, car la requête prend trop de temps. Ajustez les paramètres de saisie semi-automatique dans le fichier kibana.yml pour obtenir des résultats complets.", + "inputControl.vis.listControl.selectPlaceholder": "Sélectionner…", + "inputControl.vis.listControl.selectTextPlaceholder": "Sélectionner…", + "inspector.closeButton": "Fermer l'inspecteur", + "inspector.reqTimestampDescription": "Heure de début de la requête", + "inspector.reqTimestampKey": "Horodatage de la requête", + "inspector.requests.copyToClipboardLabel": "Copier dans le presse-papiers", + "inspector.requests.descriptionRowIconAriaLabel": "Description", + "inspector.requests.failedLabel": " (échec)", + "inspector.requests.noRequestsLoggedDescription.elementHasNotLoggedAnyRequestsText": "L'élément n'a pas (encore) consigné de requêtes.", + "inspector.requests.noRequestsLoggedDescription.whatDoesItUsuallyMeanText": "Cela signifie généralement qu'il n'était pas nécessaire de récupérer des données ou que l'élément n'a pas encore commencé à récupérer des données.", + "inspector.requests.noRequestsLoggedTitle": "Aucune requête consignée", + "inspector.requests.requestFailedTooltipTitle": "Échec de la requête", + "inspector.requests.requestInProgressAriaLabel": "Requête en cours", + "inspector.requests.requestsDescriptionTooltip": "Voir les requêtes qui ont collecté les données", + "inspector.requests.requestsTitle": "Requêtes", + "inspector.requests.requestSucceededTooltipTitle": "Requête réussie", + "inspector.requests.requestTabLabel": "Requête", + "inspector.requests.requestTimeLabel": "{requestTime}ms", + "inspector.requests.requestTooltipDescription": "Durée totale qu'a nécessité la requête.", + "inspector.requests.requestWasMadeDescription": "{requestsCount, plural, one {# requête a été effectuée} other {# requêtes ont été effectuées} }{failedRequests}", + "inspector.requests.requestWasMadeDescription.requestHadFailureText": ", {failedCount} a/ont échoué.", + "inspector.requests.responseTabLabel": "Réponse", + "inspector.requests.searchSessionId": "ID de la session de recherche : {searchSessionId}", + "inspector.requests.statisticsTabLabel": "Statistiques", + "inspector.title": "Inspecteur", + "inspector.view": "Vue : {viewName}", + "kibana_utils.history.savedObjectIsMissingNotificationMessage": "L'objet enregistré est manquant.", + "kibana_utils.stateManagement.stateHash.unableToRestoreUrlErrorMessage": "Impossible de restaurer complètement l'URL. Assurez-vous d'utiliser la fonctionnalité de partage.", + "kibana_utils.stateManagement.stateHash.unableToStoreHistoryInSessionErrorMessage": "Kibana n'est pas en mesure de stocker des éléments d'historique dans votre session, car le stockage est arrivé à saturation et il ne semble pas y avoir d'éléments pouvant être supprimés sans risque.\n\nCe problème peut généralement être corrigé en passant à un nouvel onglet, mais il peut être causé par un problème plus important. Si ce message s'affiche régulièrement, veuillez nous en faire part sur {gitHubIssuesUrl}.", + "kibana_utils.stateManagement.url.restoreUrlErrorTitle": "Erreur lors de la restauration de l'état depuis l'URL.", + "kibana_utils.stateManagement.url.saveStateInUrlErrorTitle": "Erreur lors de l'enregistrement de l'état dans l'URL.", + "kibana-react.dualRangeControl.maxInputAriaLabel": "Maximum de la plage", + "kibana-react.dualRangeControl.minInputAriaLabel": "Minimum de la plage", + "kibana-react.dualRangeControl.mustSetBothErrorMessage": "Les valeurs inférieure et supérieure doivent être définies.", + "kibana-react.dualRangeControl.outsideOfRangeErrorMessage": "Les valeurs doivent être comprises entre {min} et {max}, inclus.", + "kibana-react.dualRangeControl.upperValidErrorMessage": "La valeur supérieure doit être supérieure ou égale à la valeur inférieure.", + "kibana-react.exitFullScreenButton.exitFullScreenModeButtonAriaLabel": "Quitter le mode Plein écran", + "kibana-react.exitFullScreenButton.exitFullScreenModeButtonText": "Quitter le plein écran", + "kibana-react.exitFullScreenButton.fullScreenModeDescription": "En mode Plein écran, appuyez sur Échap pour quitter.", + "kibana-react.kbnOverviewPageHeader.devToolsButtonLabel": "Outils de développement", + "kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel": "Gérer", + "kibana-react.kibanaCodeEditor.ariaLabel": "Éditeur de code", + "kibana-react.kibanaCodeEditor.enterKeyLabel": "Entrée", + "kibana-react.kibanaCodeEditor.escapeKeyLabel": "Échap", + "kibana-react.kibanaCodeEditor.startEditing": "Appuyez sur {key} pour modifier.", + "kibana-react.kibanaCodeEditor.startEditingReadOnly": "Appuyez sur {key} pour interagir avec le code.", + "kibana-react.kibanaCodeEditor.stopEditing": "Appuyez sur {key} pour arrêter la modification.", + "kibana-react.kibanaCodeEditor.stopEditingReadOnly": "Appuyez sur {key} pour arrêter l'interaction.", + "kibana-react.mountPointPortal.errorMessage": "Erreur lors du rendu du contenu du portail.", + "kibana-react.noDataPage.cantDecide": "Vous ne savez pas quoi utiliser ? {link}", + "kibana-react.noDataPage.cantDecide.link": "Consultez la documentation pour en savoir plus.", + "kibana-react.noDataPage.elasticAgentCard.description": "Utilisez Elastic Agent pour collecter de manière simple et unifiée les données de vos machines.", + "kibana-react.noDataPage.elasticAgentCard.title": "Ajouter Elastic Agent", + "kibana-react.noDataPage.intro": "Ajoutez vos données pour commencer, ou {link} sur {solution}.", + "kibana-react.noDataPage.intro.link": "en savoir plus", + "kibana-react.noDataPage.noDataPage.recommended": "Recommandé", + "kibana-react.noDataPage.welcomeTitle": "Bienvenue dans Elastic {solution}.", + "kibana-react.pageFooter.changeDefaultRouteSuccessToast": "Page de destination mise à jour", + "kibana-react.pageFooter.changeHomeRouteLink": "Afficher une page différente à la connexion", + "kibana-react.pageFooter.makeDefaultRouteLink": "Choisir comme page de destination", + "kibana-react.solutionNav.collapsibleLabel": "Réduire la navigation latérale", + "kibana-react.solutionNav.mobileTitleText": "Menu {solutionName}", + "kibana-react.solutionNav.openLabel": "Ouvrir la navigation latérale", + "kibana-react.tableListView.listing.createNewItemButtonLabel": "Créer {entityName}", + "kibana-react.tableListView.listing.deleteButtonMessage": "Supprimer {itemCount} {entityName}", + "kibana-react.tableListView.listing.deleteConfirmModalDescription": "Vous ne pourrez pas récupérer les {entityNamePlural} supprimés.", + "kibana-react.tableListView.listing.deleteSelectedConfirmModal.title": "Supprimer {itemCount} {entityName} ?", + "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "Annuler", + "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "Supprimer", + "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.confirmButtonLabelDeleting": "Suppression", + "kibana-react.tableListView.listing.fetchErrorDescription": "Le listing {entityName} n'a pas pu être récupéré : {message}.", + "kibana-react.tableListView.listing.fetchErrorTitle": "Échec de la récupération du listing", + "kibana-react.tableListView.listing.listingLimitExceeded.advancedSettingsLinkText": "Paramètres avancés", + "kibana-react.tableListView.listing.listingLimitExceededDescription": "Vous avez {totalItems} {entityNamePlural}, mais votre paramètre {listingLimitText} empêche le tableau ci-dessous d'en afficher plus de {listingLimitValue}. Vous pouvez modifier ce paramètre sous {advancedSettingsLink}.", + "kibana-react.tableListView.listing.listingLimitExceededTitle": "Limite de listing dépassée", + "kibana-react.tableListView.listing.table.actionTitle": "Actions", + "kibana-react.tableListView.listing.table.editActionDescription": "Modifier", + "kibana-react.tableListView.listing.table.editActionName": "Modifier", + "kibana-react.tableListView.listing.unableToDeleteDangerMessage": "Impossible de supprimer le/les {entityName}(s)", + "kibanaOverview.addData.sampleDataButtonLabel": "Essayer l’exemple de données", + "kibanaOverview.addData.sectionTitle": "Ingérer des données", + "kibanaOverview.apps.title": "Explorer les applications", + "kibanaOverview.breadcrumbs.title": "Analytique", + "kibanaOverview.header.title": "Analytique", + "kibanaOverview.kibana.solution.description": "Explorez, visualisez et analysez vos données à l'aide d'une puissante suite d'outils et d'applications analytiques.", + "kibanaOverview.kibana.solution.title": "Analytique", + "kibanaOverview.manageData.sectionTitle": "Gérer vos données", + "kibanaOverview.more.title": "Toujours plus avec Elastic", + "kibanaOverview.news.title": "Nouveautés", + "kibanaOverview.noDataConfig.solutionName": "Analytique", + "lists.exceptions.doesNotExistOperatorLabel": "n'existe pas", + "lists.exceptions.existsOperatorLabel": "existe", + "lists.exceptions.isInListOperatorLabel": "est dans la liste", + "lists.exceptions.isNotInListOperatorLabel": "n'est pas dans la liste", + "lists.exceptions.isNotOneOfOperatorLabel": "n'est pas l'une des options suivantes", + "lists.exceptions.isNotOperatorLabel": "n'est pas", + "lists.exceptions.isOneOfOperatorLabel": "est l'une des options suivantes", + "lists.exceptions.isOperatorLabel": "est", + "management.breadcrumb": "Gestion de la Suite", + "management.landing.header": "Bienvenue dans Gestion de la Suite {version}", + "management.landing.subhead": "Gérez vos index, modèles d'indexation, objets enregistrés, paramètres Kibana et plus encore.", + "management.landing.text": "Vous trouverez une liste complète des applications dans le menu de gauche.", + "management.nav.label": "Gestion", + "management.sections.dataTip": "Gérez les données et les sauvegardes de vos clusters.", + "management.sections.dataTitle": "Données", + "management.sections.ingestTip": "Gérez la manière dont les données sont transformées et chargées dans le cluster.", + "management.sections.ingestTitle": "Ingestion", + "management.sections.insightsAndAlertingTip": "Gérez le mode de détection des changements dans vos données.", + "management.sections.insightsAndAlertingTitle": "Alertes et informations exploitables", + "management.sections.kibanaTip": "Personnalisez Kibana et gérez les objets enregistrés.", + "management.sections.kibanaTitle": "Kibana", + "management.sections.section.tip": "Contrôlez l'accès aux fonctionnalités et aux données.", + "management.sections.section.title": "Sécurité", + "management.sections.stackTip": "Gérez votre licence et mettez la Suite à niveau.", + "management.sections.stackTitle": "Suite", + "management.stackManagement.managementDescription": "La console centrale de gestion de la Suite Elastic.", + "management.stackManagement.managementLabel": "Gestion de la Suite", + "management.stackManagement.title": "Gestion de la Suite", + "monaco.painlessLanguage.autocomplete.docKeywordDescription": "Accéder à une valeur de champ dans un script au moyen de la syntaxe doc['field_name']", + "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "Émettre une valeur sans rien renvoyer", + "monaco.painlessLanguage.autocomplete.fieldValueDescription": "Récupérer la valeur du champ \"{fieldName}\"", + "monaco.painlessLanguage.autocomplete.paramsKeywordDescription": "Accéder aux variables transmises dans le script", + "newsfeed.emptyPrompt.noNewsText": "Si votre instance Kibana n'a pas accès à Internet, demandez à votre administrateur de désactiver cette fonctionnalité. Sinon, nous continuerons d'essayer de récupérer les actualités.", + "newsfeed.emptyPrompt.noNewsTitle": "Pas d'actualités ?", + "newsfeed.flyoutList.closeButtonLabel": "Fermer", + "newsfeed.flyoutList.versionTextLabel": "{version}", + "newsfeed.flyoutList.whatsNewTitle": "Nouveautés Elastic", + "newsfeed.headerButton.readAriaLabel": "Menu du fil d'actualités – Tous les éléments lus", + "newsfeed.headerButton.unreadAriaLabel": "Menu du fil d'actualités – Éléments non lus disponibles", + "newsfeed.loadingPrompt.gettingNewsText": "Obtention des dernières actualités…", + "presentationUtil.dashboardPicker.searchDashboardPlaceholder": "Recherche dans les tableaux de bord…", + "presentationUtil.labs.components.browserSwitchHelp": "Active l'atelier pour ce navigateur et persiste après sa fermeture.", + "presentationUtil.labs.components.browserSwitchName": "Navigateur", + "presentationUtil.labs.components.calloutHelp": "Actualiser pour appliquer les modifications", + "presentationUtil.labs.components.closeButtonLabel": "Fermer", + "presentationUtil.labs.components.descriptionMessage": "Essayez nos fonctionnalités expérimentales ou en cours.", + "presentationUtil.labs.components.disabledStatusMessage": "Par défaut : {status}", + "presentationUtil.labs.components.enabledStatusMessage": "Par défaut : {status}", + "presentationUtil.labs.components.kibanaSwitchHelp": "Active cet atelier pour tous les utilisateurs Kibana.", + "presentationUtil.labs.components.kibanaSwitchName": "Kibana", + "presentationUtil.labs.components.labFlagsLabel": "Indicateurs d'atelier", + "presentationUtil.labs.components.noProjectsinSolutionMessage": "Aucun atelier actuellement dans {solutionName}.", + "presentationUtil.labs.components.noProjectsMessage": "Aucun atelier actuellement disponible.", + "presentationUtil.labs.components.overrideFlagsLabel": "Remplacements", + "presentationUtil.labs.components.overridenIconTipLabel": "Valeur par défaut remplacée", + "presentationUtil.labs.components.resetToDefaultLabel": "Réinitialiser aux valeurs par défaut", + "presentationUtil.labs.components.sessionSwitchHelp": "Active l’atelier pour cette session de navigateur afin de le réinitialiser lors de sa fermeture.", + "presentationUtil.labs.components.sessionSwitchName": "Session", + "presentationUtil.labs.components.titleLabel": "Ateliers", + "presentationUtil.labs.enableDeferBelowFoldProjectDescription": "Les panneaux sous \"le pli\", la zone masquée en-dessous de la fenêtre accessible en faisant défiler, ne se chargeront pas immédiatement, mais seulement lorsqu'ils entreront dans la fenêtre d'affichage.", + "presentationUtil.labs.enableDeferBelowFoldProjectName": "Différer le chargement des panneaux sous \"le pli\"", + "presentationUtil.saveModalDashboard.addToDashboardLabel": "Ajouter au tableau de bord", + "presentationUtil.saveModalDashboard.dashboardInfoTooltip": "Les éléments ajoutés à la bibliothèque Visualize sont disponibles pour tous les tableaux de bord. Les modifications apportées à un élément de bibliothèque sont répercutées partout où il est utilisé.", + "presentationUtil.saveModalDashboard.existingDashboardOptionLabel": "Existant", + "presentationUtil.saveModalDashboard.libraryOptionLabel": "Ajouter à la bibliothèque", + "presentationUtil.saveModalDashboard.newDashboardOptionLabel": "Nouveau", + "presentationUtil.saveModalDashboard.noDashboardOptionLabel": "Aucun", + "presentationUtil.saveModalDashboard.saveAndGoToDashboardLabel": "Enregistrer et accéder au tableau de bord", + "presentationUtil.saveModalDashboard.saveLabel": "Enregistrer", + "presentationUtil.saveModalDashboard.saveToLibraryLabel": "Enregistrer et ajouter à la bibliothèque", + "presentationUtil.solutionToolbar.editorMenuButtonLabel": "Tous les éditeurs", + "presentationUtil.solutionToolbar.libraryButtonLabel": "Ajouter depuis la bibliothèque", + "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "Créer {createType}", + "presentationUtil.solutionToolbar.quickButton.legendLabel": "Création rapide", + "savedObjects.advancedSettings.listingLimitText": "Nombre d'objets à récupérer pour les pages de listing", + "savedObjects.advancedSettings.listingLimitTitle": "Limite de listing d’objets", + "savedObjects.advancedSettings.perPageText": "Nombre d'objets à afficher par page dans la boîte de dialogue de chargement", + "savedObjects.advancedSettings.perPageTitle": "Objets par page", + "savedObjects.confirmModal.cancelButtonLabel": "Annuler", + "savedObjects.confirmModal.overwriteButtonLabel": "Écraser", + "savedObjects.confirmModal.overwriteConfirmationMessage": "Êtes-vous sûr de vouloir écraser {title} ?", + "savedObjects.confirmModal.overwriteTitle": "Écraser {name} ?", + "savedObjects.confirmModal.saveDuplicateButtonLabel": "Enregistrer {name}", + "savedObjects.confirmModal.saveDuplicateConfirmationMessage": "Il y a déjà une occurrence de {name} avec le titre \"{title}\". Voulez-vous tout de même enregistrer ?", + "savedObjects.finder.filterButtonLabel": "Types", + "savedObjects.finder.searchPlaceholder": "Rechercher…", + "savedObjects.finder.sortAsc": "Croissant", + "savedObjects.finder.sortAuto": "Meilleure correspondance", + "savedObjects.finder.sortButtonLabel": "Trier", + "savedObjects.finder.sortDesc": "Décroissant", + "savedObjects.overwriteRejectedDescription": "La confirmation d'écrasement a été rejetée.", + "savedObjects.saveDuplicateRejectedDescription": "La confirmation d'enregistrement avec un doublon de titre a été rejetée.", + "savedObjects.saveModal.cancelButtonLabel": "Annuler", + "savedObjects.saveModal.descriptionLabel": "Description", + "savedObjects.saveModal.duplicateTitleDescription": "L'enregistrement de \"{title}\" crée un doublon de titre.", + "savedObjects.saveModal.duplicateTitleLabel": "Ce {objectType} existe déjà.", + "savedObjects.saveModal.saveAsNewLabel": "Enregistrer en tant que nouveau {objectType}", + "savedObjects.saveModal.saveButtonLabel": "Enregistrer", + "savedObjects.saveModal.saveTitle": "Enregistrer {objectType}", + "savedObjects.saveModal.titleLabel": "Titre", + "savedObjects.saveModalOrigin.addToOriginLabel": "Ajouter", + "savedObjects.saveModalOrigin.originAfterSavingSwitchLabel": "{originVerb} à {origin} après l'enregistrement", + "savedObjects.saveModalOrigin.returnToOriginLabel": "Renvoyer", + "savedObjects.saveModalOrigin.saveAndReturnLabel": "Enregistrer et renvoyer", + "savedObjectsManagement.breadcrumb.index": "Objets enregistrés", + "savedObjectsManagement.deleteConfirm.modalDeleteButtonLabel": "Supprimer", + "savedObjectsManagement.deleteConfirm.modalDescription": "Cette action supprime définitivement l'objet de Kibana.", + "savedObjectsManagement.deleteConfirm.modalTitle": "Supprimer \"{title}\" ?", + "savedObjectsManagement.deleteSavedObjectsConfirmModalDescription": "Cette action supprimera les objets enregistrés suivants :", + "savedObjectsManagement.importSummary.createdCountHeader": "{createdCount} nouveau(x)", + "savedObjectsManagement.importSummary.createdOutcomeLabel": "Créé", + "savedObjectsManagement.importSummary.errorCountHeader": "{errorCount} erreur(s)", + "savedObjectsManagement.importSummary.errorOutcomeLabel": "{errorMessage}", + "savedObjectsManagement.importSummary.headerLabel": "{importCount, plural, one {1 objet importé} other {# objets importés}}", + "savedObjectsManagement.importSummary.overwrittenCountHeader": "{overwrittenCount} écrasé(s)", + "savedObjectsManagement.importSummary.overwrittenOutcomeLabel": "Écrasé", + "savedObjectsManagement.importSummary.warnings.defaultButtonLabel": "Go", + "savedObjectsManagement.managementSectionLabel": "Objets enregistrés", + "savedObjectsManagement.objects.savedObjectsDescription": "Importez, exportez et gérez vos recherches enregistrées, vos visualisations et vos tableaux de bord.", + "savedObjectsManagement.objects.savedObjectsTitle": "Objets enregistrés", + "savedObjectsManagement.objectsTable.deleteConfirmModal.cannotDeleteCallout.title": "Certains objets ne peuvent pas être supprimés.", + "savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.content": "Les objets partagés sont supprimés de tous les espaces dans lesquels ils se trouvent.", + "savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.title": "{sharedObjectsCount, plural, one {# objet enregistré est partagé} other {# de vos objets enregistrés sont partagés}}.", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "Annuler", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel": "Supprimer {objectsCount, plural, one {# objet} other {# objets}}", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "ID", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "Titre", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "Type", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "Supprimer les objets enregistrés", + "savedObjectsManagement.objectsTable.export.successNotification": "Votre fichier est en cours de téléchargement en arrière-plan.", + "savedObjectsManagement.objectsTable.export.successWithExcludedObjectsNotification": "Votre fichier est en cours de téléchargement en arrière-plan. Certains objets ont été exclus de l'export. Vous trouverez la liste des objets exclus à la dernière ligne du fichier exporté.", + "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "Votre fichier est en cours de téléchargement en arrière-plan. Certains objets associés sont introuvables. Vous trouverez la liste des objets manquants à la dernière ligne du fichier exporté.", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "Annuler", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "Exporter tout", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "Options", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "Inclure les objets associés", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "Sélectionner les types d'objet à exporter", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle": "Exporter {filteredItemCount, plural, one {# objet} other {# objets}}", + "savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "Désolé, une erreur est survenue.", + "savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "Annuler", + "savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "Importer", + "savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "Impossible de traiter le fichier en raison d'une erreur : \"{error}\".", + "savedObjectsManagement.objectsTable.flyout.importPromptText": "Importer", + "savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "Importer les objets enregistrés", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "Confirmer toutes les modifications", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "Terminé", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "créer un nouveau modèle d'indexation", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "Les objets enregistrés suivants utilisent des modèles d'indexation qui n'existent pas. Veuillez sélectionner les modèles d'indexation que vous souhaitez réassocier aux objets. Vous pouvez {indexPatternLink} si nécessaire.", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "Conflits de modèle d'indexation", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "Nombre d'objets concernés", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "Décompte", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "ID du modèle d'indexation", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdName": "ID", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "Nouveau modèle d'indexation", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "Exemple d'objets concernés", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "Exemple d'objets concernés", + "savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel": "Sélectionner un fichier à importer", + "savedObjectsManagement.objectsTable.header.exportButtonLabel": "Exporter {filteredCount, plural, one{# objet} other {# objets}}", + "savedObjectsManagement.objectsTable.header.importButtonLabel": "Importer", + "savedObjectsManagement.objectsTable.header.refreshButtonLabel": "Actualiser", + "savedObjectsManagement.objectsTable.header.savedObjectsTitle": "Objets enregistrés", + "savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription": "Gérez et partagez vos objets enregistrés. Pour modifier les données sous-jacentes d'un objet, accédez à l’application associée.", + "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.disabledText": "Vérifiez si les objets ont déjà été copiés ou importés.", + "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.disabledTitle": "Rechercher les objets existants", + "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.enabledText": "Utilisez cette option pour créer une ou plusieurs copies de l'objet.", + "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.enabledTitle": "Créer de nouveaux objets avec des ID aléatoires", + "savedObjectsManagement.objectsTable.importModeControl.importOptionsTitle": "Options d'importation", + "savedObjectsManagement.objectsTable.importModeControl.overwrite.disabledLabel": "Demander une action en cas de conflit", + "savedObjectsManagement.objectsTable.importModeControl.overwrite.enabledLabel": "Écraser automatiquement les conflits", + "savedObjectsManagement.objectsTable.importSummary.unsupportedTypeError": "Type d'objet non pris en charge", + "savedObjectsManagement.objectsTable.overwriteModal.body.ambiguousConflict": "\"{title}\" est en conflit avec plusieurs objets existants. En écraser un ?", + "savedObjectsManagement.objectsTable.overwriteModal.body.conflict": "\"{title}\" est en conflit avec un objet existant. L'écraser ?", + "savedObjectsManagement.objectsTable.overwriteModal.cancelButtonText": "Ignorer", + "savedObjectsManagement.objectsTable.overwriteModal.overwriteButtonText": "Écraser", + "savedObjectsManagement.objectsTable.overwriteModal.selectControlLabel": "ID d'objet", + "savedObjectsManagement.objectsTable.overwriteModal.title": "Écraser {type} ?", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionDescription": "Inspecter cet objet enregistré", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionName": "Inspecter", + "savedObjectsManagement.objectsTable.relationships.columnActionsName": "Actions", + "savedObjectsManagement.objectsTable.relationships.columnErrorDescription": "Erreur rencontrée avec la relation", + "savedObjectsManagement.objectsTable.relationships.columnErrorName": "Erreur", + "savedObjectsManagement.objectsTable.relationships.columnIdDescription": "ID de l'objet enregistré", + "savedObjectsManagement.objectsTable.relationships.columnIdName": "ID", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.childAsValue": "Enfant", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.parentAsValue": "Parent", + "savedObjectsManagement.objectsTable.relationships.columnRelationshipName": "Relation directe", + "savedObjectsManagement.objectsTable.relationships.columnTitleDescription": "Titre de l'objet enregistré", + "savedObjectsManagement.objectsTable.relationships.columnTitleName": "Titre", + "savedObjectsManagement.objectsTable.relationships.columnTypeDescription": "Type de l'objet enregistré", + "savedObjectsManagement.objectsTable.relationships.columnTypeName": "Type", + "savedObjectsManagement.objectsTable.relationships.invalidRelationShip": "Cet objet enregistré présente des relations non valides.", + "savedObjectsManagement.objectsTable.relationships.relationshipsTitle": "Voici les objets enregistrés associés à {title}. La suppression de ce {type} a un impact sur ses objets parents, mais pas sur ses enfants.", + "savedObjectsManagement.objectsTable.relationships.renderErrorMessage": "Erreur", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.childAsValue.view": "Enfant", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.name": "Relation directe", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "Parent", + "savedObjectsManagement.objectsTable.relationships.search.filters.type.name": "Type", + "savedObjectsManagement.objectsTable.searchBar.unableToParseQueryErrorMessage": "Impossible d'analyser la requête", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionDescription": "Inspecter cet objet enregistré", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionName": "Inspecter", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionDescription": "Afficher les relations entre cet objet enregistré et d'autres objets enregistrés", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionName": "Relations", + "savedObjectsManagement.objectsTable.table.columnActionsName": "Actions", + "savedObjectsManagement.objectsTable.table.columnTitleDescription": "Titre de l'objet enregistré", + "savedObjectsManagement.objectsTable.table.columnTitleName": "Titre", + "savedObjectsManagement.objectsTable.table.columnTypeDescription": "Type de l'objet enregistré", + "savedObjectsManagement.objectsTable.table.columnTypeName": "Type", + "savedObjectsManagement.objectsTable.table.deleteButtonLabel": "Supprimer", + "savedObjectsManagement.objectsTable.table.deleteButtonTitle": "Impossible de supprimer les objets enregistrés", + "savedObjectsManagement.objectsTable.table.exportButtonLabel": "Exporter", + "savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel": "Exporter", + "savedObjectsManagement.objectsTable.table.typeFilterName": "Type", + "savedObjectsManagement.objectsTable.unableFindSavedObjectNotificationMessage": "Objet enregistré introuvable", + "savedObjectsManagement.objectsTable.unableFindSavedObjectsNotificationMessage": "Objets enregistrés introuvables", + "savedObjectsManagement.objectView.unableFindSavedObjectNotificationMessage": "Objet enregistré introuvable", + "savedObjectsManagement.view.fieldDoesNotExistErrorMessage": "Un champ associé à cet objet n'existe plus dans le modèle d'indexation.", + "savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage": "Le modèle d'indexation associé à cet objet n'existe plus.", + "savedObjectsManagement.view.savedObjectProblemErrorMessage": "Un problème est survenu avec cet objet enregistré.", + "savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage": "La recherche enregistrée associée à cet objet n'existe plus.", + "savedObjectsManagement.view.viewItemButtonLabel": "Afficher {title}", + "share.advancedSettings.csv.quoteValuesText": "Les valeurs doivent-elles être mises entre guillemets dans les exportations CSV ?", + "share.advancedSettings.csv.quoteValuesTitle": "Mettre les valeurs CSV entre guillemets", + "share.advancedSettings.csv.separatorText": "Séparer les valeurs exportées avec cette chaîne", + "share.advancedSettings.csv.separatorTitle": "Séparateur CSV", + "share.contextMenu.embedCodeLabel": "Incorporer le code", + "share.contextMenu.embedCodePanelTitle": "Incorporer le code", + "share.contextMenu.permalinkPanelTitle": "Permalien", + "share.contextMenu.permalinksLabel": "Permaliens", + "share.contextMenuTitle": "Partager ce {objectType}", + "share.urlPanel.canNotShareAsSavedObjectHelpText": "Impossible de partager comme objet enregistré tant que {objectType} n'a pas été enregistré.", + "share.urlPanel.copyIframeCodeButtonLabel": "Copier le code iFrame", + "share.urlPanel.copyLinkButtonLabel": "Copier le lien", + "share.urlPanel.generateLinkAsLabel": "Générer le lien en tant que", + "share.urlPanel.publicUrlHelpText": "Utilisez l'URL publique pour partager avec tout le monde. Elle permet un accès anonyme en une étape, en supprimant l'invite de connexion.", + "share.urlPanel.publicUrlLabel": "URL publique", + "share.urlPanel.savedObjectDescription": "Vous pouvez partager cette URL avec des personnes pour leur permettre de charger la version enregistrée la plus récente de ce {objectType}.", + "share.urlPanel.savedObjectLabel": "Objet enregistré", + "share.urlPanel.shortUrlHelpText": "Nous vous recommandons de partager des URL de snapshot raccourcies pour une compatibilité maximale. Internet Explorer présente des restrictions de longueur d'URL et certains analyseurs de wiki et de balisage ne fonctionnent pas bien avec les URL de snapshot longues, mais les URL courtes devraient bien fonctionner.", + "share.urlPanel.shortUrlLabel": "URL courte", + "share.urlPanel.snapshotDescription": "Les URL de snapshot encodent l'état actuel de {objectType} dans l'URL elle-même. Les modifications apportées au {objectType} enregistré ne seront pas visibles via cette URL.", + "share.urlPanel.snapshotLabel": "Snapshot", + "share.urlPanel.unableCreateShortUrlErrorMessage": "Impossible de créer une URL courte. Erreur : {errorMessage}.", + "share.urlPanel.urlGroupTitle": "URL", + "share.urlService.redirect.components.Error.title": "Erreur de redirection", + "share.urlService.redirect.components.Spinner.label": "Redirection…", + "share.urlService.redirect.RedirectManager.invalidParamParams": "Impossible d'analyser les paramètres du localisateur. Les paramètres du localisateur doivent être sérialisés en tant que JSON et définis au paramètre de recherche d'URL \"p\".", + "share.urlService.redirect.RedirectManager.locatorNotFound": "Le localisateur [ID = {id}] n'existe pas.", + "share.urlService.redirect.RedirectManager.missingParamLocator": "ID du localisateur non spécifié. Spécifiez le paramètre de recherche \"l\" dans l'URL ; ce devrait être un ID de localisateur existant.", + "share.urlService.redirect.RedirectManager.missingParamParams": "Paramètres du localisateur non spécifiés. Spécifiez le paramètre de recherche \"p\" dans l'URL ; ce devrait être un objet sérialisé JSON des paramètres du localisateur.", + "share.urlService.redirect.RedirectManager.missingParamVersion": "Version des paramètres du localisateur non spécifiée. Spécifiez le paramètre de recherche \"v\" dans l'URL ; ce devrait être la version de Kibana au moment de la génération des paramètres du localisateur.", + "telemetry.callout.appliesSettingTitle": "Les modifications apportées à ce paramètre s'appliquent dans {allOfKibanaText} et sont enregistrées automatiquement.", + "telemetry.callout.appliesSettingTitle.allOfKibanaText": "tout Kibana", + "telemetry.callout.clusterStatisticsDescription": "Voici un exemple des statistiques de cluster de base que nous collecterons. Cela comprend le nombre d'index, de partitions et de nœuds. Cela comprend également des statistiques d'utilisation de niveau élevé, comme l'état d'activation du monitoring.", + "telemetry.callout.clusterStatisticsTitle": "Statistiques du cluster", + "telemetry.callout.errorLoadingClusterStatisticsDescription": "Une erreur inattendue s'est produite lors de la récupération des statistiques du cluster. Cela peut être dû à un échec d'Elasticsearch ou de Kibana, ou d'une erreur réseau. Vérifiez Kibana, puis rechargez la page et réessayez.", + "telemetry.callout.errorLoadingClusterStatisticsTitle": "Erreur lors du chargement des statistiques du cluster", + "telemetry.callout.errorUnprivilegedUserDescription": "Vous ne disposez pas de l'accès requis pour voir les statistiques non chiffrées du cluster.", + "telemetry.callout.errorUnprivilegedUserTitle": "Erreur lors de l'affichage des statistiques du cluster", + "telemetry.clusterData": "données du cluster", + "telemetry.optInErrorToastText": "Une erreur s'est produite lors de la définition des préférences relatives aux statistiques d'utilisation.", + "telemetry.optInErrorToastTitle": "Erreur", + "telemetry.optInNoticeSeenErrorTitle": "Erreur", + "telemetry.optInNoticeSeenErrorToastText": "Une erreur s'est produite lors du rejet de l'avis.", + "telemetry.optInSuccessOff": "Collecte des données d'utilisation désactivée.", + "telemetry.optInSuccessOn": "Collecte des données d'utilisation activée.", + "telemetry.readOurUsageDataPrivacyStatementLinkText": "Déclaration de confidentialité", + "telemetry.securityData": "données de sécurité des points de terminaison", + "telemetry.telemetryBannerDescription": "Vous souhaitez nous aider à améliorer la Suite Elastic ? La collecte de données d'utilisation est actuellement désactivée. En activant la collecte de données d'utilisation, vous nous aidez à gérer et à améliorer nos produits et nos services. Consultez notre {privacyStatementLink} pour plus d'informations.", + "telemetry.telemetryConfigAndLinkDescription": "En activant la collecte de données d'utilisation, vous nous aidez à gérer et à améliorer nos produits et nos services. Consultez notre {privacyStatementLink} pour plus d'informations.", + "telemetry.telemetryOptedInDisableUsage": "désactivez les données d'utilisation ici", + "telemetry.telemetryOptedInDismissMessage": "Rejeter", + "telemetry.telemetryOptedInNoticeDescription": "Pour en savoir plus sur la manière dont les données d'utilisation nous aident à gérer et à améliorer nos produits et nos services, consultez notre {privacyStatementLink}. Pour mettre fin à la collecte, {disableLink}.", + "telemetry.telemetryOptedInNoticeTitle": "Aidez-nous à améliorer la Suite Elastic.", + "telemetry.telemetryOptedInPrivacyStatement": "Déclaration de confidentialité", + "telemetry.usageDataTitle": "Données d'utilisation", + "telemetry.welcomeBanner.disableButtonLabel": "Désactiver", + "telemetry.welcomeBanner.enableButtonLabel": "Activer", + "telemetry.welcomeBanner.telemetryConfigDetailsDescription.telemetryPrivacyStatementLinkText": "Déclaration de confidentialité", + "telemetry.welcomeBanner.title": "Aidez-nous à améliorer la Suite Elastic.", + "timelion.emptyExpressionErrorMessage": "Erreur Timelion : aucune expression fournie", + "timelion.expressionSuggestions.argument.description.acceptsText": "Accepte", + "timelion.expressionSuggestions.func.description.chainableHelpText": "Enchaînable", + "timelion.expressionSuggestions.func.description.dataSourceHelpText": "Source de données", + "timelion.fitFunctions.carry.downSampleErrorMessage": "N'utilisez pas la méthode fit \"carry\" pour sous-échantillonner, utilisez \"scale\" ou \"average\".", + "timelion.function.help": "Visualisation Timelion", + "timelion.help.functions.absHelpText": "Renvoyer la valeur absolue de chaque valeur dans la liste des séries", + "timelion.help.functions.aggregate.args.functionHelpText": "L'une des options suivantes : {functions}.", + "timelion.help.functions.aggregateHelpText": "Crée une ligne statique sur la base du résultat du traitement de tous les points de la série. Fonctions disponibles : {functions}", + "timelion.help.functions.bars.args.stackHelpText": "Vrai par défaut si les barres sont empilées", + "timelion.help.functions.bars.args.widthHelpText": "Largeur des barres en pixels", + "timelion.help.functions.barsHelpText": "Afficher la liste des séries sous la forme de barres", + "timelion.help.functions.color.args.colorHelpText": "Couleur des séries en valeurs hexadécimales, par ex. #c6c6c6 est un très joli gris clair. Si vous spécifiez plusieurs couleurs et que vous avez plusieurs séries, vous obtiendrez un dégradé, par ex. \"#00B1CC:#00FF94:#FF3A39:#CC1A6F\".", + "timelion.help.functions.colorHelpText": "Changer la couleur des séries", + "timelion.help.functions.common.args.fitHelpText": "Algorithme à utiliser pour adapter les séries à l'intervalle et à la période cible. Disponible : {fitFunctions}", + "timelion.help.functions.common.args.offsetHelpText": "Décalez la récupération des séries avec une expression de date, par ex. -1M pour afficher les événements d'il y a un mois comme s'ils se produisaient maintenant. Décalez les séries par rapport à la plage temporelle globale des graphiques en utilisant la valeur \"timerange\", par ex. \"timerange:-2\" pour obtenir un décalage correspondant à deux fois la plage temporelle globale du graphique dans le passé.", + "timelion.help.functions.condition.args.elseHelpText": "La valeur à laquelle le point sera défini si la comparaison est fausse. Si vous spécifiez une liste de séries, la première série sera utilisée.", + "timelion.help.functions.condition.args.ifHelpText": "La valeur à laquelle le point sera comparé. Si vous spécifiez une liste de séries, la première série sera utilisée.", + "timelion.help.functions.condition.args.operator.suggestions.eqHelpText": "égal", + "timelion.help.functions.condition.args.operator.suggestions.gteHelpText": "supérieur ou égal", + "timelion.help.functions.condition.args.operator.suggestions.gtHelpText": "supérieur à", + "timelion.help.functions.condition.args.operator.suggestions.lteHelpText": "inférieur ou égal", + "timelion.help.functions.condition.args.operator.suggestions.ltHelpText": "inférieur à", + "timelion.help.functions.condition.args.operator.suggestions.neHelpText": "différent", + "timelion.help.functions.condition.args.operatorHelpText": "Opérateur de comparaison à utiliser pour la comparaison ; les opérateurs valides sont eq (égal), ne (différent), lt (inférieur à), lte (inférieur ou égal), gt (supérieur à), gte (supérieur ou égal).", + "timelion.help.functions.condition.args.thenHelpText": "La valeur à laquelle le point sera défini si la comparaison est vraie. Si vous spécifiez une liste de séries, la première série sera utilisée.", + "timelion.help.functions.conditionHelpText": "Compare chaque point à un nombre ou au même point dans une autre série à l'aide d'un opérateur, puis définit sa valeur sur le résultat si la condition est vraie, avec un sinon facultatif.", + "timelion.help.functions.cusum.args.baseHelpText": "Numéro auquel commencer. Cela ajoute simplement ce numéro au début de la série", + "timelion.help.functions.cusumHelpText": "Renvoyez la somme cumulée d'une série, à partir d’une base.", + "timelion.help.functions.derivativeHelpText": "Tracez l'évolution des valeurs au fil du temps.", + "timelion.help.functions.divide.args.divisorHelpText": "Nombre de séries par lequel diviser. Une liste de plusieurs séries sera appliquée pour l'étiquette.", + "timelion.help.functions.divideHelpText": "Divise les valeurs d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.es.args.indexHelpText": "Index à interroger, caractères génériques acceptés. Fournissez le nom du modèle d'indexation pour les champs scriptés et le type de nom de champ devant les suggestions pour les arguments metrics, split et timefield.", + "timelion.help.functions.es.args.intervalHelpText": "**NE PAS UTILISER**. C'est amusant pour déboguer les fonctions fit, mais vous devriez vraiment utiliser le sélecteur d'intervalle.", + "timelion.help.functions.es.args.kibanaHelpText": "Respectez les filtres des tableaux de bord Kibana. Cela n'a d'effet qu’en cas d'utilisation dans des tableaux de bord Kibana", + "timelion.help.functions.es.args.metricHelpText": "Une agrégation d'indicateurs Elasticsearch Moyenne, Somme, Min, Max, Centiles ou Cardinalité, puis un champ. Par ex. \"sum:bytes\", \"percentiles:bytes:95,99,99.9\" ou simplement \"count\".", + "timelion.help.functions.es.args.qHelpText": "Requête dans la syntaxe de chaîne de requête Lucene", + "timelion.help.functions.es.args.splitHelpText": "Un champ Elasticsearch avec lequel diviser la série et une limite. Par ex. \"{hostnameSplitArg}\" pour obtenir les 10 premiers noms d'hôte.", + "timelion.help.functions.es.args.timefieldHelpText": "Champ de type \"date\" à utiliser pour l'axe X", + "timelion.help.functions.esHelpText": "Extraire des données d'une instance Elasticsearch", + "timelion.help.functions.firstHelpText": "Il s'agit d'une fonction interne qui renvoie simplement la liste de séries d'entrée. Ne l'utilisez pas.", + "timelion.help.functions.fit.args.modeHelpText": "L'algorithme à utiliser pour adapter les séries à la cible. L'une des options suivantes : {fitFunctions}.", + "timelion.help.functions.fitHelpText": "Remplit les valeurs nulles à l'aide d'une fonction fit définie.", + "timelion.help.functions.graphite.args.metricHelpText": "Indicateur Graphite à extraire, par ex. {metricExample}", + "timelion.help.functions.graphiteHelpText": "[expérimental] Extrayez des données de Graphite. Configurez votre serveur Graphite dans les paramètres avancés de Kibana.", + "timelion.help.functions.hide.args.hideHelpText": "Masquer ou afficher les séries", + "timelion.help.functions.hideHelpText": "Masquer les séries par défaut", + "timelion.help.functions.holt.args.alphaHelpText": "\n Pondération de lissage de 0 à 1.\n Augmentez l’alpha pour que la nouvelle série suive de plus près l'originale.\n Diminuez-le pour rendre la série plus lisse.", + "timelion.help.functions.holt.args.betaHelpText": "\n Pondération de tendance de 0 à 1.\n Augmentez le bêta pour que les lignes montantes/descendantes continuent à monter/descendre plus longtemps.\n Diminuez-le pour que la fonction apprenne plus rapidement la nouvelle tendance.", + "timelion.help.functions.holt.args.gammaHelpText": "\n Pondération saisonnière de 0 à 1. Vos données ressemblent-elles à une vague ?\n Augmentez cette valeur pour donner plus d'importance aux saisons récentes et ainsi modifier plus rapidement la forme de la vague.\n Diminuez-la pour réduire l'importance des nouvelles saisons et ainsi rendre l'historique plus important.\n ", + "timelion.help.functions.holt.args.sampleHelpText": "\n Le nombre de saisons à échantillonner avant de commencer à \"prédire\" dans une série saisonnière.\n (Utile uniquement avec gamma, par défaut : all)", + "timelion.help.functions.holt.args.seasonHelpText": "La longueur de la saison, par ex. 1w, si votre modèle se répète chaque semaine. (Utile uniquement avec gamma)", + "timelion.help.functions.holtHelpText": "\n Échantillonner le début d'une série et l'utiliser pour prévoir ce qui devrait se produire\n via plusieurs paramètres facultatifs. En règle générale, cela ne prédit pas\n l'avenir, mais ce qui devrait se produire maintenant en fonction des données passées,\n ce qui peut être utile pour la détection des anomalies. Notez que les valeurs null seront remplacées par des valeurs prévues.", + "timelion.help.functions.label.args.labelHelpText": "Valeur de légende pour les séries. Vous pouvez utiliser $1, $2, etc. dans la chaîne pour correspondre aux groupes de captures d'expressions régulières.", + "timelion.help.functions.label.args.regexHelpText": "Une expression régulière compatible avec les groupes de captures", + "timelion.help.functions.labelHelpText": "Modifiez l'étiquette des séries. Utiliser %s pour référencer l'étiquette existante", + "timelion.help.functions.legend.args.columnsHelpText": "Nombre de colonnes à utiliser lors de la division de la légende", + "timelion.help.functions.legend.args.position.suggestions.falseHelpText": "désactiver la légende", + "timelion.help.functions.legend.args.position.suggestions.neHelpText": "placer la légende dans le coin nord-est", + "timelion.help.functions.legend.args.position.suggestions.nwHelpText": "placer la légende dans le coin nord-ouest", + "timelion.help.functions.legend.args.position.suggestions.seHelpText": "placer la légende dans le coin sud-est", + "timelion.help.functions.legend.args.position.suggestions.swHelpText": "placer la légende dans le coin sud-ouest", + "timelion.help.functions.legend.args.positionHelpText": "Coin dans lequel placer la légende : nw, ne, se ou sw. Il est également possible d'indiquer \"false\" pour désactiver la légende.", + "timelion.help.functions.legend.args.showTimeHelpText": "Afficher la valeur temporelle en légende lors du passage du curseur sur le graphique. Par défaut : true.", + "timelion.help.functions.legend.args.timeFormatHelpText": "Modèle de format moment.js. Par défaut : {defaultTimeFormat}", + "timelion.help.functions.legendHelpText": "Définir la position et le style de la légende sur le tracé", + "timelion.help.functions.lines.args.fillHelpText": "Nombre compris entre 0 et 10. À utiliser pour créer des graphiques en aires.", + "timelion.help.functions.lines.args.showHelpText": "Afficher ou masquer les lignes", + "timelion.help.functions.lines.args.stackHelpText": "Empiler les lignes, souvent équivoque. Utilisez au moins des remplissages si vous utilisez cette option.", + "timelion.help.functions.lines.args.stepsHelpText": "Afficher la ligne comme une étape ; autrement dit, ne pas interpoler entre les points", + "timelion.help.functions.lines.args.widthHelpText": "Épaisseur de ligne", + "timelion.help.functions.linesHelpText": "Afficher la liste de séries sous la forme de lignes", + "timelion.help.functions.log.args.baseHelpText": "Définir la base logarithmique ; 10 par défaut", + "timelion.help.functions.logHelpText": "Renvoyer la valeur logarithmique de chaque valeur de la liste des séries (base par défaut : 10)", + "timelion.help.functions.max.args.valueHelpText": "Définit le point sur la valeur existante ou la valeur transmise, selon la plus élevée des deux. Si une liste de séries est transmise, elle doit contenir exactement 1 série.", + "timelion.help.functions.maxHelpText": "Valeurs maximales d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.min.args.valueHelpText": "Définit le point sur la valeur existante ou la valeur transmise, selon la plus basse des deux. Si une liste de séries est transmise, elle doit contenir exactement 1 série.", + "timelion.help.functions.minHelpText": "Valeurs minimales d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.movingaverage.args.positionHelpText": "Position des points moyens par rapport à l'heure du résultat. L'une des options suivantes : {validPositions}.", + "timelion.help.functions.movingaverage.args.windowHelpText": "Nombre de points ou une expression mathématique de date (par ex. 1d, 1M) à utiliser pour calculer la moyenne. Si une expression mathématique de date est spécifiée, la fonction sera la plus proche possible compte tenu de l'intervalle sélectionné. Si l'expression mathématique de date n'est pas divisible uniformément par l'intervalle, les résultats peuvent sembler être anormaux.", + "timelion.help.functions.movingaverageHelpText": "Calculez la moyenne mobile pour une fenêtre donnée. Idéal pour lisser les séries avec beaucoup de bruit.", + "timelion.help.functions.movingstd.args.positionHelpText": "Position de la section de la fenêtre par rapport à l'heure du résultat. Les options sont {positions}. Par défaut : {defaultPosition}.", + "timelion.help.functions.movingstd.args.windowHelpText": "Nombre de points à utiliser pour calculer l'écart-type.", + "timelion.help.functions.movingstdHelpText": "Calculez l'écart-type mobile pour une fenêtre donnée. Utilise l'algorithme naïf en deux passes. Les erreurs d'arrondi peuvent devenir plus évidentes avec les séries très longues ou celles comportant de très grands nombres.", + "timelion.help.functions.multiply.args.multiplierHelpText": "Nombre de séries par lequel multiplier. Une liste de plusieurs séries sera appliquée pour l'étiquette.", + "timelion.help.functions.multiplyHelpText": "Multiplie les valeurs d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.notAllowedGraphiteUrl": "Cette URL Graphite n'est pas configurée dans le fichier kibana.yml.\n Veuillez configurer votre liste de serveurs Graphite dans le fichier kibana.yml, sous \"timelion.graphiteUrls\", puis\n en sélectionner un dans les paramètres avancés de Kibana.", + "timelion.help.functions.points.args.fillColorHelpText": "Couleur à utiliser pour remplir le point", + "timelion.help.functions.points.args.fillHelpText": "Nombre compris entre 0 et 10 représentant l'opacité du remplissage", + "timelion.help.functions.points.args.radiusHelpText": "Taille des points", + "timelion.help.functions.points.args.showHelpText": "Afficher ou non les points", + "timelion.help.functions.points.args.symbolHelpText": "Symbole de point. L'un des options suivantes : {validSymbols}", + "timelion.help.functions.points.args.weightHelpText": "Épaisseur de la ligne autour du point", + "timelion.help.functions.pointsHelpText": "Afficher les séries sous la forme de points", + "timelion.help.functions.precision.args.precisionHelpText": "Le nombre de chiffres à garder lors de la troncature de chaque valeur", + "timelion.help.functions.precisionHelpText": "Le nombre de chiffres à garder lors de la troncature de la partie décimale de la valeur", + "timelion.help.functions.props.args.globalHelpText": "Définir des propositions sur la liste de séries plutôt que sur chaque série", + "timelion.help.functions.propsHelpText": "À utiliser à vos risques et périls ; définit des propriétés arbitraires sur la série. Par exemple : {example}", + "timelion.help.functions.quandl.args.codeHelpText": "Le code Quandl à tracer. Disponible sur quandl.com.", + "timelion.help.functions.quandl.args.positionHelpText": "Certaines sources Quandl renvoient plusieurs séries. Laquelle utiliser ? Index basé sur 1.", + "timelion.help.functions.quandlHelpText": "\n [expérimental]\n Extrayez des données de quandl.com à l'aide du code Quandl. Définissez {quandlKeyField} sur votre clé d'API gratuite dans\n les paramètres avancés de Kibana. La limite de taux de l'API est très basse sans clé.", + "timelion.help.functions.range.args.maxHelpText": "Nouvelle valeur maximale", + "timelion.help.functions.range.args.minHelpText": "Nouvelle valeur minimale", + "timelion.help.functions.rangeHelpText": "Modifie le maximum et le minimum d'une série sans changer la forme.", + "timelion.help.functions.scaleInterval.args.intervalHelpText": "Le nouvel intervalle en notation mathématique de date, par ex. 1s pour 1 seconde. 1m, 5m, 1M, 1w, 1y, etc.", + "timelion.help.functions.scaleIntervalHelpText": "Scale une valeur (généralement une somme ou un décompte) à un nouvel intervalle. Par exemple, un taux par seconde.", + "timelion.help.functions.static.args.labelHelpText": "Une manière rapide de définir l'étiquette pour la série. Vous pouvez également utiliser la fonction .label().", + "timelion.help.functions.static.args.valueHelpText": "La valeur unique à afficher. Vous pouvez également passer plusieurs valeurs, elles seront interpolées uniformément sur la plage temporelle.", + "timelion.help.functions.staticHelpText": "Dessine une valeur unique sur le graphique", + "timelion.help.functions.subtract.args.termHelpText": "Nombre de séries à soustraire de l'entrée. Une liste de plusieurs séries sera appliquée pour l'étiquette.", + "timelion.help.functions.subtractHelpText": "Soustrait les valeurs d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.sum.args.termHelpText": "Nombre de séries à ajouter à l'entrée. Une liste de plusieurs séries sera appliquée pour l'étiquette.", + "timelion.help.functions.sumHelpText": "Ajoute les valeurs d'une ou de plusieurs séries d'une liste de séries à chaque position, dans chaque série, de la liste de séries d'entrée.", + "timelion.help.functions.title.args.titleHelpText": "Titre pour le tracé.", + "timelion.help.functions.titleHelpText": "Ajoute un titre en haut du tracé. En cas d’appel sur plusieurs listes de séries, le dernier appel est utilisé.", + "timelion.help.functions.trend.args.endHelpText": "Quand arrêter de calculer par rapport au début ou à la fin. Par exemple, -10 indique qu'il faut arrêter de calculer 10 points avant la fin, et +15 indique que le calcul doit s'arrêter 15 points après le début. Par défaut : 0", + "timelion.help.functions.trend.args.modeHelpText": "L'algorithme à utiliser pour générer la courbe de tendance. L'une des options suivantes : {validRegressions}.", + "timelion.help.functions.trend.args.startHelpText": "Quand commencer à calculer par rapport au début ou à la fin. Par exemple, -10 indique qu'il faut commencer à calculer 10 points avant la fin, et +15 indique que le calcul doit commencer 15 points après le début. Par défaut : 0", + "timelion.help.functions.trendHelpText": "Dessine une courbe de tendance à l'aide d'un algorithme de régression spécifié.", + "timelion.help.functions.trim.args.endHelpText": "Compartiments à retirer de la fin de la série. Par défaut : 1", + "timelion.help.functions.trim.args.startHelpText": "Compartiments à retirer du début de la série. Par défaut : 1", + "timelion.help.functions.trimHelpText": "Définir N compartiments au début ou à la fin de la série sur null pour ajuster le \"problème de compartiment partiel\"", + "timelion.help.functions.worldbank.args.codeHelpText": "Chemin de l'API Worldbank (Banque mondiale). Il s'agit généralement de tout ce qui suit le domaine, avant la chaîne de requête. Par exemple : {apiPathExample}.", + "timelion.help.functions.worldbankHelpText": "\n [expérimental]\n Extrayez des données de {worldbankUrl} à l'aide du chemin d’accès aux séries.\n La Banque mondiale fournit surtout des données annuelles et n'a souvent aucune donnée pour l'année en cours.\n Essayez {offsetQuery} si vous n’obtenez pas de données pour les plages temporelles récentes.", + "timelion.help.functions.worldbankIndicators.args.countryHelpText": "Identifiant de pays de la Banque mondiale. Généralement le code à 2 caractères du pays.", + "timelion.help.functions.worldbankIndicators.args.indicatorHelpText": "Le code d'indicateur à utiliser. Vous devrez le rechercher sur {worldbankUrl}. Souvent très complexe. Par exemple, {indicatorExample} correspond à la population.", + "timelion.help.functions.worldbankIndicatorsHelpText": "\n [expérimental]\n Extrayez des données de {worldbankUrl} à l'aide du nom et de l'indicateur du pays. La Banque mondiale fournit\n surtout des données annuelles et n'a souvent aucune donnée pour l'année en cours. Essayez {offsetQuery} si vous n’obtenez pas de données pour\n les plages temporelles récentes.", + "timelion.help.functions.yaxis.args.colorHelpText": "Couleur de l'étiquette de l'axe", + "timelion.help.functions.yaxis.args.labelHelpText": "Étiquette de l'axe", + "timelion.help.functions.yaxis.args.maxHelpText": "Valeur max.", + "timelion.help.functions.yaxis.args.minHelpText": "Valeur min.", + "timelion.help.functions.yaxis.args.positionHelpText": "gauche ou droite", + "timelion.help.functions.yaxis.args.tickDecimalsHelpText": "Le nombre de décimales pour les étiquettes de graduation de l'axe Y.", + "timelion.help.functions.yaxis.args.unitsHelpText": "La fonction à utiliser pour mettre en forme les étiquettes de l'axe Y. L'une des options suivantes : {formatters}.", + "timelion.help.functions.yaxis.args.yaxisHelpText": "L'axe Y numéroté sur lequel tracer cette série, par exemple .yaxis(2) pour un deuxième axe Y.", + "timelion.help.functions.yaxisHelpText": "Configure une variété d'options pour l'axe Y, la plus importante étant sans doute celle permettant d'ajouter un énième (par ex. deuxième) axe Y.", + "timelion.noFunctionErrorMessage": "Fonction inconnue : {name}", + "timelion.panels.timechart.unknownIntervalErrorMessage": "Intervalle inconnu", + "timelion.requestHandlerErrorTitle": "Erreur de requête Timelion", + "timelion.serverSideErrors.argumentsOverflowErrorMessage": "Trop d'arguments transmis à : {functionName}", + "timelion.serverSideErrors.bucketsOverflowErrorMessage": "Nombre max. de compartiments dépassé : {bucketCount} sur {maxBuckets} autorisés. Sélectionnez un intervalle plus grand ou une période plus courte.", + "timelion.serverSideErrors.colorFunction.colorNotProvidedErrorMessage": "couleur non spécifiée", + "timelion.serverSideErrors.conditionFunction.unknownOperatorErrorMessage": "Opérateur inconnu", + "timelion.serverSideErrors.conditionFunction.wrongArgTypeErrorMessage": "doit être un nombre ou une liste de séries", + "timelion.serverSideErrors.esFunction.indexNotFoundErrorMessage": "Index Elasticsearch introuvable : {index}", + "timelion.serverSideErrors.holtFunction.missingParamsErrorMessage": "Vous devez spécifier une longueur de saison et une taille d'échantillon >= 2.", + "timelion.serverSideErrors.holtFunction.notEnoughPointsErrorMessage": "Au moins 2 points sont nécessaires pour utiliser le lissage exponentiel double.", + "timelion.serverSideErrors.movingaverageFunction.notValidPositionErrorMessage": "Les positions valides sont : {validPositions}.", + "timelion.serverSideErrors.movingstdFunction.notValidPositionErrorMessage": "Les positions valides sont : {validPositions}.", + "timelion.serverSideErrors.pointsFunction.notValidSymbolErrorMessage": "Les symboles valides sont : {validSymbols}.", + "timelion.serverSideErrors.quandlFunction.unsupportedIntervalErrorMessage": "Intervalle non pris en charge par quandl() : {interval}. Les intervalles pris en charge par quandl() sont les suivants : {intervals}.", + "timelion.serverSideErrors.sheetParseErrorMessage": "Attendu : {expectedDescription} au caractère {column}", + "timelion.serverSideErrors.unknownArgumentErrorMessage": "Argument inconnu pour {functionName} : {argumentName}", + "timelion.serverSideErrors.unknownArgumentTypeErrorMessage": "Type d'argument non pris en charge : {argument}", + "timelion.serverSideErrors.worldbankFunction.noDataErrorMessage": "La requête à la Banque mondiale a réussi, mais il n'y a pas de données pour {code}.", + "timelion.serverSideErrors.wrongFunctionArgumentTypeErrorMessage": "{functionName}({argumentName}) doit être l'une des options suivantes : {requiredTypes}. Obtenu : {actualType}", + "timelion.serverSideErrors.yaxisFunction.notSupportedUnitTypeErrorMessage": "{units} n'est pas un type d'unité pris en charge.", + "timelion.serverSideErrors.yaxisFunction.notValidCurrencyFormatErrorMessage": "La devise doit être un code à trois caractères.", + "timelion.timelionDescription": "Affichez des données temporelles sur un graphe.", + "timelion.uiSettings.defaultIndexDescription": "Index Elasticsearch par défaut dans lequel rechercher avec {esParam}", + "timelion.uiSettings.defaultIndexLabel": "Index par défaut", + "timelion.uiSettings.experimentalLabel": "expérimental", + "timelion.uiSettings.graphiteURLDescription": "{experimentalLabel} L'URL de l'hôte Graphite", + "timelion.uiSettings.graphiteURLLabel": "URL Graphite", + "timelion.uiSettings.legacyChartsLibraryDeprication": "Ce paramètre est déclassé et ne sera plus pris en charge à partir de la version 8.0.", + "timelion.uiSettings.legacyChartsLibraryDescription": "Active la bibliothèque de graphiques héritée pour les graphiques Timelion dans Visualize.", + "timelion.uiSettings.legacyChartsLibraryLabel": "Bibliothèque de graphiques Timelion héritée", + "timelion.uiSettings.maximumBucketsDescription": "Le nombre maximal de compartiments qu'une source de données unique peut renvoyer", + "timelion.uiSettings.maximumBucketsLabel": "Nombre maximal de compartiments", + "timelion.uiSettings.minimumIntervalDescription": "Le plus petit intervalle qui sera calculé lors de l'utilisation de l'option \"auto\"", + "timelion.uiSettings.minimumIntervalLabel": "Intervalle minimum", + "timelion.uiSettings.quandlKeyDescription": "{experimentalLabel} Votre clé d'API de www.quandl.com", + "timelion.uiSettings.quandlKeyLabel": "Clé Quandl", + "timelion.uiSettings.targetBucketsDescription": "Le nombre de compartiments visé lors de l'utilisation d'intervalles automatiques", + "timelion.uiSettings.targetBucketsLabel": "Compartiments cibles", + "timelion.uiSettings.timeFieldDescription": "Champ par défaut contenant un horodatage lors de l'utilisation de {esParam}", + "timelion.uiSettings.timeFieldLabel": "Champ temporel", + "timelion.vis.expressionLabel": "Expression Timelion", + "timelion.vis.interval.auto": "Auto", + "timelion.vis.interval.day": "1 jour", + "timelion.vis.interval.hour": "1 heure", + "timelion.vis.interval.minute": "1 minute", + "timelion.vis.interval.month": "1 mois", + "timelion.vis.interval.second": "1 seconde", + "timelion.vis.interval.week": "1 semaine", + "timelion.vis.interval.year": "1 an", + "timelion.vis.intervalLabel": "Intervalle", + "timelion.vis.invalidIntervalErrorMessage": "Format d'intervalle non valide.", + "timelion.vis.selectIntervalHelpText": "Choisissez une option ou créez une valeur personnalisée. Exemples : 30s, 20m, 24h, 2d, 1w, 1M", + "timelion.vis.selectIntervalPlaceholder": "Choisir un intervalle", + "uiActions.actionPanel.more": "Plus", + "uiActions.actionPanel.title": "Options", + "uiActions.errors.incompatibleAction": "Action non compatible", + "uiActions.triggers.rowClickkDescription": "Un clic sur une ligne de tableau", + "uiActions.triggers.rowClickTitle": "Clic sur ligne de tableau", + "visDefaultEditor.advancedToggle.advancedLinkLabel": "Avancé", + "visDefaultEditor.agg.disableAggButtonTooltip": "Désactiver l'agrégation {aggTitle} de {schemaTitle}", + "visDefaultEditor.agg.enableAggButtonTooltip": "Activer l'agrégation {aggTitle} de {schemaTitle}", + "visDefaultEditor.agg.errorsAriaLabel": "L'agrégation {aggTitle} de {schemaTitle} présente des erreurs.", + "visDefaultEditor.agg.modifyPriorityButtonTooltip": "Modifier la priorité de l'agrégation {aggTitle} de {schemaTitle} en la faisant glisser", + "visDefaultEditor.agg.removeDimensionButtonTooltip": "Supprimer l'agrégation {aggTitle} de {schemaTitle}", + "visDefaultEditor.agg.toggleEditorButtonAriaLabel": "Activer/Désactiver l'éditeur {schema}", + "visDefaultEditor.aggAdd.addButtonLabel": "Ajouter", + "visDefaultEditor.aggAdd.addGroupButtonLabel": "Ajouter {groupNameLabel}", + "visDefaultEditor.aggAdd.addSubGroupButtonLabel": "Ajouter sous-{groupNameLabel}", + "visDefaultEditor.aggAdd.bucketLabel": "compartiment", + "visDefaultEditor.aggAdd.maxBuckets": "Nombre maximal de {groupNameLabel} atteint", + "visDefaultEditor.aggAdd.metricLabel": "indicateur", + "visDefaultEditor.aggParams.errors.aggWrongRunOrderErrorMessage": "Les agrégations \"{schema}\" doivent s'exécuter avant tous les autres compartiments.", + "visDefaultEditor.aggSelect.aggregationLabel": "Agrégation", + "visDefaultEditor.aggSelect.helpLinkLabel": "Aide {aggTitle}", + "visDefaultEditor.aggSelect.noCompatibleAggsDescription": "Le modèle d'indexation {indexPatternTitle} ne possède pas de champs regroupables.", + "visDefaultEditor.aggSelect.selectAggPlaceholder": "Choisir une agrégation", + "visDefaultEditor.aggSelect.subAggregationLabel": "Sous-agrégation", + "visDefaultEditor.buckets.mustHaveBucketErrorMessage": "Ajoutez un compartiment avec une agrégation Histogramme de date ou Histogramme.", + "visDefaultEditor.controls.aggNotValidLabel": "- agrégation non valide -", + "visDefaultEditor.controls.aggregateWith.noAggsErrorTooltip": "Le champ choisi n'a pas d'agrégations compatibles.", + "visDefaultEditor.controls.aggregateWithLabel": "Agréger avec", + "visDefaultEditor.controls.aggregateWithTooltip": "Choisissez une stratégie pour combiner plusieurs occurrences ou un champ à valeurs multiples en un seul indicateur.", + "visDefaultEditor.controls.changePrecisionLabel": "Modifier la précision lors d'un zoom sur la carte", + "visDefaultEditor.controls.columnsLabel": "Colonnes", + "visDefaultEditor.controls.customMetricLabel": "Indicateur personnalisé", + "visDefaultEditor.controls.dateRanges.acceptedDateFormatsLinkText": "Formats de date acceptables", + "visDefaultEditor.controls.dateRanges.addRangeButtonLabel": "Ajouter une plage", + "visDefaultEditor.controls.dateRanges.errorMessage": "Chaque plage doit avoir au moins une date valide.", + "visDefaultEditor.controls.dateRanges.fromColumnLabel": "De", + "visDefaultEditor.controls.dateRanges.removeRangeButtonAriaLabel": "Supprimer la plage allant de {from} à {to}", + "visDefaultEditor.controls.dateRanges.toColumnLabel": "Au", + "visDefaultEditor.controls.definiteMetricLabel": "Indicateur : {metric}", + "visDefaultEditor.controls.dotSizeRatioHelpText": "Remplacez le rapport du rayon du plus petit point par le plus grand point.", + "visDefaultEditor.controls.dotSizeRatioLabel": "Rapport de taille de point", + "visDefaultEditor.controls.dropPartialBucketsLabel": "Abandonner les compartiments partiels", + "visDefaultEditor.controls.dropPartialBucketsTooltip": "Retirez les compartiments qui s'étendent au-delà de la plage temporelle afin que l'histogramme ne commence pas et ne se termine pas avec des compartiments incomplets.", + "visDefaultEditor.controls.extendedBounds.errorMessage": "Le minimum doit être inférieur ou égal au maximum.", + "visDefaultEditor.controls.extendedBounds.maxLabel": "Max.", + "visDefaultEditor.controls.extendedBounds.minLabel": "Min.", + "visDefaultEditor.controls.extendedBoundsLabel": "Étendre les limites", + "visDefaultEditor.controls.extendedBoundsTooltip": "Le minimum et le maximum ne filtrent pas de résultats, mais étendent plutôt les limites de l'ensemble de résultats.", + "visDefaultEditor.controls.field.fieldIsNotExists": "Le champ \"{fieldParameter}\" associé à cet objet n'existe plus dans le modèle d'indexation. Veuillez utiliser un autre champ.", + "visDefaultEditor.controls.field.fieldLabel": "Champ", + "visDefaultEditor.controls.field.invalidFieldForAggregation": "Le champ enregistré \"{fieldParameter}\" du modèle d'indexation \"{indexPatternTitle}\" n'est pas valide pour une utilisation avec cette agrégation. Veuillez sélectionner un nouveau champ.", + "visDefaultEditor.controls.field.noCompatibleFieldsDescription": "Le modèle d'indexation {indexPatternTitle} ne contient aucun des types de champs compatibles suivants : {fieldTypes}.", + "visDefaultEditor.controls.field.selectFieldPlaceholder": "Sélectionner un champ", + "visDefaultEditor.controls.filters.addFilterButtonLabel": "Ajouter un filtre", + "visDefaultEditor.controls.filters.definiteFilterLabel": "Étiquette du filtre {index}", + "visDefaultEditor.controls.filters.filterLabel": "Filtre {index}", + "visDefaultEditor.controls.filters.labelPlaceholder": "Étiquette", + "visDefaultEditor.controls.filters.removeFilterButtonAriaLabel": "Supprimer ce filtre", + "visDefaultEditor.controls.filters.toggleFilterButtonAriaLabel": "Activer/Désactiver l'étiquette du filtre", + "visDefaultEditor.controls.includeExclude.addUnitButtonLabel": "Ajouter une valeur", + "visDefaultEditor.controls.ipRanges.addRangeButtonLabel": "Ajouter une plage", + "visDefaultEditor.controls.ipRanges.cidrMaskAriaLabel": "Masque CIDR : {mask}", + "visDefaultEditor.controls.ipRanges.cidrMasksButtonLabel": "Masques CIDR", + "visDefaultEditor.controls.ipRanges.fromToButtonLabel": "De/à", + "visDefaultEditor.controls.ipRanges.ipRangeFromAriaLabel": "Début de la plage d’IP : {value}", + "visDefaultEditor.controls.ipRanges.ipRangeToAriaLabel": "Fin de la plage d’IP : {value}", + "visDefaultEditor.controls.ipRanges.removeCidrMaskButtonAriaLabel": "Supprimer la valeur du masque CIDR de {mask}", + "visDefaultEditor.controls.ipRanges.removeEmptyCidrMaskButtonAriaLabel": "Supprimer la valeur par défaut du masque CIDR", + "visDefaultEditor.controls.ipRanges.removeRangeAriaLabel": "Supprimer la plage allant de {from} à {to}", + "visDefaultEditor.controls.ipRangesAriaLabel": "Plages d’IP", + "visDefaultEditor.controls.jsonInputLabel": "Entrée JSON", + "visDefaultEditor.controls.jsonInputTooltip": "Toutes les propriétés au format JSON ajoutées ici seront fusionnées avec la définition d'agrégation Elasticsearch pour cette section. Par exemple, \"shard_size\" pour une agrégation de termes.", + "visDefaultEditor.controls.maxBars.autoPlaceholder": "Auto", + "visDefaultEditor.controls.maxBars.maxBarsHelpText": "Les intervalles seront sélectionnés automatiquement en fonction des données disponibles. Le nombre maximal de barres ne peut jamais être supérieur à la valeur {histogramMaxBars} des paramètres avancés.", + "visDefaultEditor.controls.maxBars.maxBarsLabel": "Barres max.", + "visDefaultEditor.controls.metricLabel": "Indicateur", + "visDefaultEditor.controls.metrics.bucketTitle": "Compartiment", + "visDefaultEditor.controls.metrics.metricTitle": "Indicateur", + "visDefaultEditor.controls.numberInterval.autoInteralIsUsed": "L'intervalle automatique est utilisé.", + "visDefaultEditor.controls.numberInterval.minimumIntervalLabel": "Intervalle minimum", + "visDefaultEditor.controls.numberInterval.minimumIntervalTooltip": "L'intervalle sera scalé automatiquement si la valeur fournie crée plus de compartiments que ce qui est spécifié par la valeur {histogramMaxBars} dans les paramètres avancés.", + "visDefaultEditor.controls.numberInterval.selectIntervalPlaceholder": "Saisir un intervalle", + "visDefaultEditor.controls.numberList.addUnitButtonLabel": "Ajouter {unitName}", + "visDefaultEditor.controls.numberList.duplicateValueErrorMessage": "Dupliquez la valeur.", + "visDefaultEditor.controls.numberList.enterValuePlaceholder": "Saisir une valeur", + "visDefaultEditor.controls.numberList.invalidAscOrderErrorMessage": "La valeur n'est pas dans l'ordre croissant.", + "visDefaultEditor.controls.numberList.invalidRangeErrorMessage": "La valeur doit être comprise dans la plage allant de {min} à {max}.", + "visDefaultEditor.controls.numberList.removeUnitButtonAriaLabel": "Supprimer la valeur de rang de {value}", + "visDefaultEditor.controls.onlyRequestDataAroundMapExtentLabel": "Demander uniquement des données sur l'étendue de la carte", + "visDefaultEditor.controls.onlyRequestDataAroundMapExtentTooltip": "Appliquer l'agrégation de filtres geo_bounding_box pour réduire la zone d’intérêt à la zone d'affichage de la carte avec collier", + "visDefaultEditor.controls.orderAgg.alphabeticalLabel": "Alphabétique", + "visDefaultEditor.controls.orderAgg.orderByLabel": "Classer par", + "visDefaultEditor.controls.orderLabel": "Ordre", + "visDefaultEditor.controls.otherBucket.groupValuesLabel": "Regrouper les autres valeurs dans un compartiment séparé", + "visDefaultEditor.controls.otherBucket.groupValuesTooltip": "Les valeurs qui ne sont pas dans le top N sont regroupées dans ce compartiment. Pour inclure les documents avec des valeurs manquantes, activez l'option \"Afficher les valeurs manquantes\".", + "visDefaultEditor.controls.otherBucket.showMissingValuesLabel": "Afficher les valeurs manquantes", + "visDefaultEditor.controls.otherBucket.showMissingValuesTooltip": "Ne fonctionne que pour les champs de type \"chaîne\". Lorsque cette option est activée, les documents avec des valeurs manquantes sont inclus dans la recherche. Si ce compartiment est dans le top N, il apparaît dans le graphique. S'il n'est pas dans le top N et que l’option \"Regrouper les autres valeurs dans un compartiment séparé\" est activée, Elasticsearch ajoute les valeurs manquantes à \"l'autre\" compartiment.", + "visDefaultEditor.controls.percentileRanks.percentUnitNameText": "pour cent", + "visDefaultEditor.controls.percentileRanks.valuesLabel": "Valeurs", + "visDefaultEditor.controls.percentileRanks.valueUnitNameText": "valeur", + "visDefaultEditor.controls.percentiles.percentsLabel": "Pour cent", + "visDefaultEditor.controls.placeMarkersOffGridLabel": "Placer les marqueurs hors grille (utiliser un centroïde géométrique)", + "visDefaultEditor.controls.precisionLabel": "Précision", + "visDefaultEditor.controls.ranges.addRangeButtonLabel": "Ajouter une plage", + "visDefaultEditor.controls.ranges.fromLabel": "De", + "visDefaultEditor.controls.ranges.greaterThanOrEqualPrepend": "≥", + "visDefaultEditor.controls.ranges.greaterThanOrEqualTooltip": "Supérieur ou égal à", + "visDefaultEditor.controls.ranges.lessThanPrepend": "<", + "visDefaultEditor.controls.ranges.lessThanTooltip": "Inférieur à", + "visDefaultEditor.controls.ranges.removeRangeButtonAriaLabel": "Supprimer la plage allant de {from} à {to}", + "visDefaultEditor.controls.ranges.toLabel": "Au", + "visDefaultEditor.controls.rowsLabel": "Lignes", + "visDefaultEditor.controls.scaleMetricsLabel": "Scaler les valeurs des indicateurs (déclassé)", + "visDefaultEditor.controls.scaleMetricsTooltip": "Si vous sélectionnez un intervalle minimal manuel et qu'un intervalle plus grand est utilisé, l'activation de cette option entraînera le scaling des indicateurs de décompte et de somme à l'intervalle manuel sélectionné.", + "visDefaultEditor.controls.showEmptyBucketsLabel": "Afficher les compartiments vides", + "visDefaultEditor.controls.showEmptyBucketsTooltip": "Afficher tous les compartiments, pas seulement ceux avec des résultats", + "visDefaultEditor.controls.sizeLabel": "Taille", + "visDefaultEditor.controls.sizeTooltip": "Demander les K premiers résultats. Plusieurs résultats seront combinés par le biais de \"agréger avec\".", + "visDefaultEditor.controls.sortOnLabel": "Trier en fonction de", + "visDefaultEditor.controls.splitByLegend": "Diviser le graphique par lignes ou colonnes.", + "visDefaultEditor.controls.timeInterval.createsTooLargeBucketsTooltip": "Cet intervalle crée des compartiments trop grands pour permettre l’affichage dans la plage temporelle sélectionnée, il a donc été réduit.", + "visDefaultEditor.controls.timeInterval.createsTooManyBucketsTooltip": "Cet intervalle crée trop de compartiments pour permettre l’affichage dans la plage temporelle sélectionnée, il a donc été augmenté.", + "visDefaultEditor.controls.timeInterval.invalidFormatErrorMessage": "Format d'intervalle non valide.", + "visDefaultEditor.controls.timeInterval.minimumIntervalLabel": "Intervalle minimum", + "visDefaultEditor.controls.timeInterval.scaledHelpText": "Actuellement scalé à {bucketDescription}", + "visDefaultEditor.controls.timeInterval.selectIntervalPlaceholder": "Choisir un intervalle", + "visDefaultEditor.controls.timeInterval.selectOptionHelpText": "Choisissez une option ou créez une valeur personnalisée. Exemples : 30s, 20m, 24h, 2d, 1w, 1M", + "visDefaultEditor.controls.useAutoInterval": "Utiliser l'intervalle automatique", + "visDefaultEditor.editorConfig.dateHistogram.customInterval.helpText": "Doit être un multiple de l'intervalle de configuration : {interval}.", + "visDefaultEditor.editorConfig.histogram.interval.helpText": "Doit être un multiple de l'intervalle de configuration : {interval}.", + "visDefaultEditor.metrics.wrongLastBucketTypeErrorMessage": "La dernière agrégation de compartiments doit être \"Histogramme de date\" ou \"Histogramme\" lorsque vous utilisez l'agrégation d'indicateurs \"{type}\".", + "visDefaultEditor.options.colorRanges.errorText": "Chaque plage doit être supérieure à la précédente.", + "visDefaultEditor.options.colorSchema.colorSchemaLabel": "Schéma de couleurs", + "visDefaultEditor.options.colorSchema.howToChangeColorsDescription": "Les couleurs individuelles peuvent être modifiées dans la légende.", + "visDefaultEditor.options.colorSchema.resetColorsButtonLabel": "Réinitialiser les couleurs", + "visDefaultEditor.options.colorSchema.reverseColorSchemaLabel": "Inverser le schéma", + "visDefaultEditor.options.percentageMode.documentationLabel": "Documentation Numeral.js", + "visDefaultEditor.options.percentageMode.numeralLabel": "Modèle de format", + "visDefaultEditor.options.percentageMode.percentageModeLabel": "Mode de pourcentage", + "visDefaultEditor.options.rangeErrorMessage": "Les valeurs doivent être comprises entre {min} et {max}, inclus.", + "visDefaultEditor.options.vislibBasicOptions.legendPositionLabel": "Position de la légende", + "visDefaultEditor.options.vislibBasicOptions.showTooltipLabel": "Afficher l'infobulle", + "visDefaultEditor.palettePicker.label": "Palette de couleurs", + "visDefaultEditor.sidebar.autoApplyChangesLabelOff": "Application automatique désactivée", + "visDefaultEditor.sidebar.autoApplyChangesLabelOn": "Application automatique activée", + "visDefaultEditor.sidebar.autoApplyChangesOff": "Off", + "visDefaultEditor.sidebar.autoApplyChangesOffLabel": "Application automatique désactivée", + "visDefaultEditor.sidebar.autoApplyChangesOn": "On", + "visDefaultEditor.sidebar.autoApplyChangesOnLabel": "Application automatique activée", + "visDefaultEditor.sidebar.autoApplyChangesTooltip": "Met automatiquement à jour la visualisation à chaque modification.", + "visDefaultEditor.sidebar.collapseButtonAriaLabel": "Activer/Désactiver la barre latérale", + "visDefaultEditor.sidebar.discardChangesButtonLabel": "Abandonner", + "visDefaultEditor.sidebar.errorButtonTooltip": "Les erreurs dans les champs mis en évidence doivent être corrigées.", + "visDefaultEditor.sidebar.indexPatternAriaLabel": "Modèle d'indexation : {title}", + "visDefaultEditor.sidebar.savedSearch.goToDiscoverButtonText": "Afficher cette recherche dans Discover", + "visDefaultEditor.sidebar.savedSearch.linkButtonAriaLabel": "Lier à la recherche enregistrée. Cliquez pour en savoir plus ou rompre le lien.", + "visDefaultEditor.sidebar.savedSearch.popoverHelpText": "Les modifications apportées ultérieurement à cette recherche enregistrée sont reflétées dans la visualisation. Pour désactiver les mises à jour automatiques, supprimez le lien.", + "visDefaultEditor.sidebar.savedSearch.popoverTitle": "Lié à la recherche enregistrée", + "visDefaultEditor.sidebar.savedSearch.titleAriaLabel": "Recherche enregistrée : {title}", + "visDefaultEditor.sidebar.savedSearch.unlinkSavedSearchButtonText": "Supprimer le lien avec la recherche enregistrée", + "visDefaultEditor.sidebar.tabs.dataLabel": "Données", + "visDefaultEditor.sidebar.tabs.optionsLabel": "Options", + "visDefaultEditor.sidebar.updateChartButtonLabel": "Mettre à jour", + "visDefaultEditor.sidebar.updateInfoTooltip": "CTRL + Entrée est le raccourci clavier pour Mettre à jour.", + "visTypeMarkdown.function.font.help": "Paramètres de police.", + "visTypeMarkdown.function.help": "Visualisation Markdown", + "visTypeMarkdown.function.markdown.help": "Markdown à rendre", + "visTypeMarkdown.function.openLinksInNewTab.help": "Ouvre les liens dans un nouvel onglet", + "visTypeMarkdown.markdownDescription": "Ajoutez du texte et des images à votre tableau de bord.", + "visTypeMarkdown.markdownTitleInWizard": "Texte", + "visTypeMarkdown.params.fontSizeLabel": "Taille de police de base en points", + "visTypeMarkdown.params.helpLinkLabel": "Aide", + "visTypeMarkdown.params.openLinksLabel": "Ouvrir les liens dans un nouvel onglet", + "visTypeMarkdown.tabs.dataText": "Données", + "visTypeMarkdown.tabs.optionsText": "Options", + "visTypeMetric.colorModes.backgroundOptionLabel": "Arrière-plan", + "visTypeMetric.colorModes.labelsOptionLabel": "Étiquettes", + "visTypeMetric.colorModes.noneOptionLabel": "Aucun", + "visTypeMetric.metricDescription": "Affiche un calcul sous la forme d'un nombre unique.", + "visTypeMetric.metricTitle": "Indicateur", + "visTypeMetric.params.color.useForLabel": "Utiliser la couleur pour", + "visTypeMetric.params.rangesTitle": "Plages", + "visTypeMetric.params.settingsTitle": "Paramètres", + "visTypeMetric.params.showTitleLabel": "Afficher le titre", + "visTypeMetric.params.style.fontSizeLabel": "Taille de police de l'indicateur en points", + "visTypeMetric.params.style.styleTitle": "Style", + "visTypeMetric.schemas.metricTitle": "Indicateur", + "visTypeMetric.schemas.splitGroupTitle": "Diviser le groupe", + "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.deprecation": "La bibliothèque de graphiques héritée pour les camemberts dans Visualize est déclassée et ne sera plus prise en charge à partir de la version 8.0.", + "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.description": "Active la bibliothèque de graphiques héritée pour les camemberts dans Visualize.", + "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.name": "Bibliothèque de graphiques héritée pour les camemberts", + "visTypePie.controls.truncateLabel": "Tronquer", + "visTypePie.editors.pie.decimalSliderLabel": "Nombre maximal de décimales pour les pourcentages", + "visTypePie.editors.pie.distinctColorsLabel": "Utiliser des couleurs distinctes pour chaque section", + "visTypePie.editors.pie.donutLabel": "Graphique en anneau", + "visTypePie.editors.pie.labelPositionLabel": "Position de l'étiquette", + "visTypePie.editors.pie.labelsSettingsTitle": "Paramètres des étiquettes", + "visTypePie.editors.pie.nestedLegendLabel": "Imbriquer la légende", + "visTypePie.editors.pie.pieSettingsTitle": "Paramètres du camembert", + "visTypePie.editors.pie.showLabelsLabel": "Afficher les étiquettes", + "visTypePie.editors.pie.showTopLevelOnlyLabel": "Afficher uniquement le niveau supérieur", + "visTypePie.editors.pie.showValuesLabel": "Afficher les valeurs", + "visTypePie.editors.pie.valueFormatsLabel": "Valeurs", + "visTypePie.labelPositions.insideOrOutsideText": "Intérieur ou extérieur", + "visTypePie.labelPositions.insideText": "Intérieur", + "visTypePie.legendPositions.bottomText": "Bas", + "visTypePie.legendPositions.leftText": "Gauche", + "visTypePie.legendPositions.rightText": "Droite", + "visTypePie.legendPositions.topText": "Haut", + "visTypePie.pie.metricTitle": "Taille de section", + "visTypePie.pie.pieDescription": "Comparez des données proportionnellement à un ensemble.", + "visTypePie.pie.pieTitle": "Camembert", + "visTypePie.pie.segmentTitle": "Diviser les sections", + "visTypePie.pie.splitTitle": "Diviser le graphique", + "visTypePie.valuesFormats.percent": "Afficher le pourcentage", + "visTypePie.valuesFormats.value": "Afficher la valeur", + "visTypeTable.defaultAriaLabel": "Visualisation du tableau de données", + "visTypeTable.function.adimension.buckets": "Compartiments", + "visTypeTable.function.args.bucketsHelpText": "Configuration des dimensions de compartiment", + "visTypeTable.function.args.metricsHelpText": "Configuration des dimensions d’indicateur", + "visTypeTable.function.args.percentageColHelpText": "Nom de la colonne pour laquelle afficher le pourcentage", + "visTypeTable.function.args.perPageHelpText": "Le nombre de lignes dans une page de tableau est utilisé pour la pagination.", + "visTypeTable.function.args.rowHelpText": "La valeur de ligne est utilisée pour le mode de division de tableau. Définir sur \"vrai\" pour diviser par ligne", + "visTypeTable.function.args.showToolbarHelpText": "Définir sur \"vrai\" pour afficher la barre d'outils de la grille avec le bouton \"Exporter\"", + "visTypeTable.function.args.showTotalHelpText": "Définir sur \"vrai\" pour afficher le nombre total de lignes", + "visTypeTable.function.args.splitColumnHelpText": "Diviser par la configuration des dimensions de colonne", + "visTypeTable.function.args.splitRowHelpText": "Diviser par la configuration des dimensions de ligne", + "visTypeTable.function.args.titleHelpText": "Titre de la visualisation. Le titre est utilisé comme nom de fichier par défaut pour l'exportation CSV.", + "visTypeTable.function.args.totalFuncHelpText": "Spécifie la fonction de calcul du nombre total de lignes. Les options possibles sont : ", + "visTypeTable.function.dimension.metrics": "Indicateurs", + "visTypeTable.function.dimension.splitColumn": "Diviser par colonne", + "visTypeTable.function.dimension.splitRow": "Diviser par ligne", + "visTypeTable.function.help": "Visualisation du tableau", + "visTypeTable.params.defaultPercentageCol": "Ne pas afficher", + "visTypeTable.params.PercentageColLabel": "Colonne de pourcentage", + "visTypeTable.params.percentageTableColumnName": "Pourcentages de {title}", + "visTypeTable.params.perPageLabel": "Nombre max. de lignes par page", + "visTypeTable.params.showMetricsLabel": "Afficher les indicateurs pour chaque compartiment/niveau", + "visTypeTable.params.showPartialRowsLabel": "Afficher les lignes partielles", + "visTypeTable.params.showPartialRowsTip": "Affichez les lignes contenant des données partielles. Les indicateurs de chaque compartiment/niveau seront toujours calculés, même s'ils ne sont pas affichés.", + "visTypeTable.params.showToolbarLabel": "Afficher la barre d'outils", + "visTypeTable.params.showTotalLabel": "Afficher le total", + "visTypeTable.params.totalFunctionLabel": "Fonction de total", + "visTypeTable.sort.ascLabel": "Tri croissant", + "visTypeTable.sort.descLabel": "Tri décroissant", + "visTypeTable.tableCellFilter.filterForValueAriaLabel": "Filtrer sur la valeur : {cellContent}", + "visTypeTable.tableCellFilter.filterForValueText": "Filtrer sur la valeur", + "visTypeTable.tableCellFilter.filterOutValueAriaLabel": "Exclure la valeur : {cellContent}", + "visTypeTable.tableCellFilter.filterOutValueText": "Exclure la valeur", + "visTypeTable.tableVisDescription": "Affichez des données en lignes et en colonnes.", + "visTypeTable.tableVisEditorConfig.schemas.bucketTitle": "Diviser les lignes", + "visTypeTable.tableVisEditorConfig.schemas.metricTitle": "Indicateur", + "visTypeTable.tableVisEditorConfig.schemas.splitTitle": "Diviser le tableau", + "visTypeTable.tableVisTitle": "Tableau de données", + "visTypeTable.totalAggregations.averageText": "Moyenne", + "visTypeTable.totalAggregations.countText": "Décompte", + "visTypeTable.totalAggregations.maxText": "Max.", + "visTypeTable.totalAggregations.minText": "Min.", + "visTypeTable.totalAggregations.sumText": "Somme", + "visTypeTable.vis.controls.exportButtonAriaLabel": "Exporter {dataGridAriaLabel} au format CSV", + "visTypeTable.vis.controls.exportButtonFormulasWarning": "Votre fichier CSV contient des caractères que les applications de feuilles de calcul pourraient considérer comme des formules.", + "visTypeTable.vis.controls.exportButtonLabel": "Exporter", + "visTypeTable.vis.controls.formattedCSVButtonLabel": "Formaté", + "visTypeTable.vis.controls.rawCSVButtonLabel": "Brut", + "visTypeTagCloud.orientations.multipleText": "Multiple", + "visTypeTagCloud.orientations.rightAngledText": "Angle droit", + "visTypeTagCloud.orientations.singleText": "Unique", + "visTypeTagCloud.scales.linearText": "Linéaire", + "visTypeTagCloud.scales.logText": "Log", + "visTypeTagCloud.scales.squareRootText": "Racine carrée", + "visTypeTagCloud.vis.schemas.metricTitle": "Taille de balise", + "visTypeTagCloud.vis.schemas.segmentTitle": "Balises", + "visTypeTagCloud.vis.tagCloudDescription": "Affichez la fréquence des mots avec la taille de police.", + "visTypeTagCloud.vis.tagCloudTitle": "Nuage de balises", + "visTypeTagCloud.visParams.fontSizeLabel": "Plage de taille de police en pixels", + "visTypeTagCloud.visParams.orientationsLabel": "Orientations", + "visTypeTagCloud.visParams.showLabelToggleLabel": "Afficher l'étiquette", + "visTypeTagCloud.visParams.textScaleLabel": "Échelle de texte", + "visTypeTimeseries.addDeleteButtons.addButtonDefaultTooltip": "Ajouter", + "visTypeTimeseries.addDeleteButtons.cloneButtonDefaultTooltip": "Cloner", + "visTypeTimeseries.addDeleteButtons.deleteButtonDefaultTooltip": "Supprimer", + "visTypeTimeseries.addDeleteButtons.reEnableTooltip": "Réactiver", + "visTypeTimeseries.addDeleteButtons.temporarilyDisableTooltip": "Désactiver temporairement", + "visTypeTimeseries.advancedSettings.maxBucketsText": "A un impact sur la densité de l'histogramme TSVB. Doit être défini sur une valeur supérieure à \"histogram:maxBars\".", + "visTypeTimeseries.advancedSettings.maxBucketsTitle": "Limite de compartiments TSVB", + "visTypeTimeseries.aggRow.addMetricButtonTooltip": "Ajouter un indicateur", + "visTypeTimeseries.aggRow.deleteMetricButtonTooltip": "Supprimer un indicateur", + "visTypeTimeseries.aggSelect.aggGroups.metricAggLabel": "Agrégations d'indicateurs", + "visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel": "Agrégations de pipelines parents", + "visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel": "Agrégations de pipelines enfants", + "visTypeTimeseries.aggSelect.aggGroups.specialAggLabel": "Agrégations spéciales", + "visTypeTimeseries.aggSelect.selectAggPlaceholder": "Sélectionner une agrégation", + "visTypeTimeseries.annotationsEditor.addDataSourceButtonLabel": "Ajouter une source de données", + "visTypeTimeseries.annotationsEditor.dataSourcesLabel": "Sources de données", + "visTypeTimeseries.annotationsEditor.fieldsLabel": "Champs (requis – chemins séparés par des virgules)", + "visTypeTimeseries.annotationsEditor.howToCreateAnnotationDataSourceDescription": "Cliquez sur le bouton ci-dessous pour créer une source de données d'annotation.", + "visTypeTimeseries.annotationsEditor.iconLabel": "Icône (requis)", + "visTypeTimeseries.annotationsEditor.ignoreGlobalFiltersLabel": "Ignorer les filtres globaux ?", + "visTypeTimeseries.annotationsEditor.ignorePanelFiltersLabel": "Ignorer les filtres de panneau ?", + "visTypeTimeseries.annotationsEditor.queryStringLabel": "Chaîne de requête", + "visTypeTimeseries.annotationsEditor.rowTemplateHelpText": "eg.{rowTemplateExample}", + "visTypeTimeseries.annotationsEditor.rowTemplateLabel": "Modèle de ligne (requis)", + "visTypeTimeseries.annotationsEditor.timeFieldLabel": "Champ temporel (requis)", + "visTypeTimeseries.axisLabelOptions.axisLabel": "par {unitValue} {unitString}", + "visTypeTimeseries.calculateLabel.bucketScriptsLabel": "Script de compartiment", + "visTypeTimeseries.calculateLabel.countLabel": "Décompte", + "visTypeTimeseries.calculateLabel.filterRatioLabel": "Rapport de filtre", + "visTypeTimeseries.calculateLabel.mathLabel": "Mathématique", + "visTypeTimeseries.calculateLabel.positiveRateLabel": "Taux de compteur de {field}", + "visTypeTimeseries.calculateLabel.seriesAggLabel": "Agrégation de séries ({metricFunction})", + "visTypeTimeseries.calculateLabel.staticValueLabel": "Valeur statique de {metricValue}", + "visTypeTimeseries.calculateLabel.unknownLabel": "Inconnu", + "visTypeTimeseries.calculation.aggregationLabel": "Agrégation", + "visTypeTimeseries.calculation.painlessScriptDescription": "Les variables sont des clés sur l'objet {params}, c.-à-d. {paramsName}. Pour accéder à l'intervalle de compartiment (en millisecondes), utilisez {paramsInterval}.", + "visTypeTimeseries.calculation.painlessScriptLabel": "Script Painless", + "visTypeTimeseries.calculation.variablesLabel": "Variables", + "visTypeTimeseries.colorPicker.clearIconLabel": "Effacer", + "visTypeTimeseries.colorPicker.notAccessibleAriaLabel": "Sélecteur de couleur, non accessible", + "visTypeTimeseries.colorPicker.notAccessibleWithValueAriaLabel": "Sélecteur de couleur ({value}), non accessible", + "visTypeTimeseries.colorRules.adjustChartSizeAriaLabel": "Utilisez les flèches haut/bas pour ajuster la taille du graphique.", + "visTypeTimeseries.colorRules.defaultPrimaryNameLabel": "arrière-plan", + "visTypeTimeseries.colorRules.defaultSecondaryNameLabel": "texte", + "visTypeTimeseries.colorRules.emptyLabel": "vide", + "visTypeTimeseries.colorRules.greaterThanLabel": "> supérieur à", + "visTypeTimeseries.colorRules.greaterThanOrEqualLabel": ">= supérieur ou égal à", + "visTypeTimeseries.colorRules.ifMetricIsLabel": "si l'indicateur est", + "visTypeTimeseries.colorRules.lessThanLabel": "< inférieur à", + "visTypeTimeseries.colorRules.lessThanOrEqualLabel": "<= inférieur ou égal à", + "visTypeTimeseries.colorRules.setPrimaryColorLabel": "Définissez {primaryName} sur", + "visTypeTimeseries.colorRules.setSecondaryColorLabel": "et {secondaryName} sur", + "visTypeTimeseries.colorRules.valueAriaLabel": "Valeur", + "visTypeTimeseries.cumulativeSum.aggregationLabel": "Agrégation", + "visTypeTimeseries.cumulativeSum.metricLabel": "Indicateur", + "visTypeTimeseries.dataFormatPicker.bytesLabel": "Octets", + "visTypeTimeseries.dataFormatPicker.customLabel": "Personnalisé", + "visTypeTimeseries.dataFormatPicker.decimalPlacesLabel": "Décimales", + "visTypeTimeseries.dataFormatPicker.durationLabel": "Durée", + "visTypeTimeseries.dataFormatPicker.fromLabel": "De", + "visTypeTimeseries.dataFormatPicker.numberLabel": "Nombre", + "visTypeTimeseries.dataFormatPicker.percentLabel": "Pour cent", + "visTypeTimeseries.dataFormatPicker.toLabel": "À", + "visTypeTimeseries.defaultDataFormatterLabel": "Formateur de données", + "visTypeTimeseries.derivative.aggregationLabel": "Agrégation", + "visTypeTimeseries.derivative.metricLabel": "Indicateur", + "visTypeTimeseries.derivative.unitsLabel": "Unités (1s, 1m, etc.)", + "visTypeTimeseries.durationOptions.daysLabel": "Jours", + "visTypeTimeseries.durationOptions.hoursLabel": "Heures", + "visTypeTimeseries.durationOptions.humanize": "Lisible par l'utilisateur", + "visTypeTimeseries.durationOptions.microsecondsLabel": "Microsecondes", + "visTypeTimeseries.durationOptions.millisecondsLabel": "Millisecondes", + "visTypeTimeseries.durationOptions.minutesLabel": "Minutes", + "visTypeTimeseries.durationOptions.monthsLabel": "Mois", + "visTypeTimeseries.durationOptions.nanosecondsLabel": "Nanosecondes", + "visTypeTimeseries.durationOptions.picosecondsLabel": "Picosecondes", + "visTypeTimeseries.durationOptions.secondsLabel": "Secondes", + "visTypeTimeseries.durationOptions.weeksLabel": "Semaines", + "visTypeTimeseries.durationOptions.yearsLabel": "Années", + "visTypeTimeseries.emptyTextValue": "(vide)", + "visTypeTimeseries.error.requestForPanelFailedErrorMessage": "La requête pour ce panneau a échoué.", + "visTypeTimeseries.fetchFields.loadIndexPatternFieldsErrorMessage": "Impossible de charger les champs index_pattern", + "visTypeTimeseries.fieldSelect.fieldIsNotValid": "Le champ \"{fieldParameter}\" n'est pas valide pour une utilisation avec l'index actuel. Veuillez sélectionner un nouveau champ.", + "visTypeTimeseries.fieldSelect.selectFieldPlaceholder": "Sélectionner un champ…", + "visTypeTimeseries.filterRatio.aggregationLabel": "Agrégation", + "visTypeTimeseries.filterRatio.denominatorLabel": "Dénominateur", + "visTypeTimeseries.filterRatio.fieldLabel": "Champ", + "visTypeTimeseries.filterRatio.metricAggregationLabel": "Agrégation d'indicateurs", + "visTypeTimeseries.filterRatio.numeratorLabel": "Numérateur", + "visTypeTimeseries.function.help": "Visualisation TSVB", + "visTypeTimeseries.gauge.dataTab.dataButtonLabel": "Données", + "visTypeTimeseries.gauge.dataTab.metricsButtonLabel": "Indicateurs", + "visTypeTimeseries.gauge.editor.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.gauge.editor.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.gauge.editor.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.gauge.editor.labelPlaceholder": "Étiquette", + "visTypeTimeseries.gauge.editor.toggleEditorAriaLabel": "Activer/Désactiver l'éditeur de séries", + "visTypeTimeseries.gauge.optionsTab.backgroundColorLabel": "Couleur d'arrière-plan :", + "visTypeTimeseries.gauge.optionsTab.colorRulesLabel": "Règles de couleur", + "visTypeTimeseries.gauge.optionsTab.dataLabel": "Données", + "visTypeTimeseries.gauge.optionsTab.gaugeLineWidthLabel": "Largeur de la ligne de jauge", + "visTypeTimeseries.gauge.optionsTab.gaugeMaxLabel": "Jauge max. (vide pour auto)", + "visTypeTimeseries.gauge.optionsTab.gaugeStyleLabel": "Style de jauge", + "visTypeTimeseries.gauge.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.gauge.optionsTab.innerColorLabel": "Couleur intérieure :", + "visTypeTimeseries.gauge.optionsTab.innerLineWidthLabel": "Largeur de la ligne intérieure", + "visTypeTimeseries.gauge.optionsTab.optionsButtonLabel": "Options", + "visTypeTimeseries.gauge.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.gauge.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.gauge.optionsTab.styleLabel": "Style", + "visTypeTimeseries.gauge.styleOptions.circleLabel": "Cercle", + "visTypeTimeseries.gauge.styleOptions.halfCircleLabel": "Demi-cercle", + "visTypeTimeseries.getInterval.daysLabel": "jours", + "visTypeTimeseries.getInterval.hoursLabel": "heures", + "visTypeTimeseries.getInterval.minutesLabel": "minutes", + "visTypeTimeseries.getInterval.monthsLabel": "mois", + "visTypeTimeseries.getInterval.secondsLabel": "secondes", + "visTypeTimeseries.getInterval.weeksLabel": "semaines", + "visTypeTimeseries.getInterval.yearsLabel": "années", + "visTypeTimeseries.handleErrorResponse.unexpectedError": "Erreur inattendue", + "visTypeTimeseries.iconSelect.asteriskLabel": "Astérisque", + "visTypeTimeseries.iconSelect.bellLabel": "Cloche", + "visTypeTimeseries.iconSelect.boltLabel": "Éclair", + "visTypeTimeseries.iconSelect.bombLabel": "Bombe", + "visTypeTimeseries.iconSelect.bugLabel": "Bug", + "visTypeTimeseries.iconSelect.commentLabel": "Commentaire", + "visTypeTimeseries.iconSelect.exclamationCircleLabel": "Cercle exclamation", + "visTypeTimeseries.iconSelect.exclamationTriangleLabel": "Triangle exclamation", + "visTypeTimeseries.iconSelect.fireLabel": "Feu", + "visTypeTimeseries.iconSelect.flagLabel": "Drapeau", + "visTypeTimeseries.iconSelect.heartLabel": "Cœur", + "visTypeTimeseries.iconSelect.mapMarkerLabel": "Repère", + "visTypeTimeseries.iconSelect.mapPinLabel": "Punaise", + "visTypeTimeseries.iconSelect.starLabel": "Étoile", + "visTypeTimeseries.iconSelect.tagLabel": "Balise", + "visTypeTimeseries.indexPattern.detailLevel": "Niveau de détail", + "visTypeTimeseries.indexPattern.detailLevelAriaLabel": "Niveau de détail", + "visTypeTimeseries.indexPattern.detailLevelHelpText": "Contrôle les intervalles auto et gte en fonction de la plage temporelle. Les paramètres avancés {histogramTargetBars} et {histogramMaxBars} ont un impact sur l'intervalle par défaut.", + "visTypeTimeseries.indexPattern.dropLastBucketLabel": "Abandonner le dernier compartiment ?", + "visTypeTimeseries.indexPattern.finest": "Plus fin", + "visTypeTimeseries.indexPattern.intervalHelpText": "Exemples : auto, 1m, 1d, 7d, 1y, >=1m", + "visTypeTimeseries.indexPattern.intervalLabel": "Intervalle", + "visTypeTimeseries.indexPattern.timeFieldLabel": "Champ temporel", + "visTypeTimeseries.indexPattern.timeRange.entireTimeRange": "Toute la plage temporelle", + "visTypeTimeseries.indexPattern.timeRange.error": "Vous ne pouvez pas utiliser \"{mode}\" avec le type d'index actuel.", + "visTypeTimeseries.indexPattern.timeRange.hint": "Ce paramètre contrôle la période utilisée pour la mise en correspondance des documents. L'option \"Toute la plage temporelle\" mettra en correspondance tous les documents sélectionnés dans le sélecteur d'heure. L'option \"Dernière valeur\" ne mettra en correspondance que les documents pour l'intervalle spécifié à partir de la fin de la plage temporelle.", + "visTypeTimeseries.indexPattern.timeRange.label": "Mode de plage temporelle des données", + "visTypeTimeseries.indexPattern.timeRange.lastValue": "Dernière valeur", + "visTypeTimeseries.indexPattern.timeRange.selectTimeRange": "Sélectionner", + "visTypeTimeseries.indexPattern.сoarse": "Grossier", + "visTypeTimeseries.indexPatternSelect.label": "Modèle d'indexation", + "visTypeTimeseries.indexPatternSelect.switchModePopover.areaLabel": "Configurer le mode de sélection du modèle d'indexation", + "visTypeTimeseries.indexPatternSelect.switchModePopover.title": "Mode de sélection du modèle d'indexation", + "visTypeTimeseries.indexPatternSelect.switchModePopover.useKibanaIndices": "Utiliser uniquement les modèles d'indexation Kibana", + "visTypeTimeseries.kbnVisTypes.metricsDescription": "Réalisez des analyses avancées de vos données temporelles.", + "visTypeTimeseries.kbnVisTypes.metricsTitle": "TSVB", + "visTypeTimeseries.lastValueModeIndicator.lastBucketDate": "Compartiment : {lastBucketDate}", + "visTypeTimeseries.lastValueModeIndicator.lastValue": "Dernière valeur", + "visTypeTimeseries.lastValueModeIndicator.lastValueModeBadgeAriaLabel": "Afficher les détails de la dernière valeur", + "visTypeTimeseries.lastValueModeIndicator.panelInterval": "Intervalle : {formattedPanelInterval}", + "visTypeTimeseries.lastValueModePopover.gearButton": "Modifier l'option d'affichage de l'indicateur Dernière valeur", + "visTypeTimeseries.lastValueModePopover.switch": "Afficher l'étiquette lors de l'utilisation du mode Dernière valeur", + "visTypeTimeseries.lastValueModePopover.title": "Options de Dernière valeur", + "visTypeTimeseries.markdown.alignOptions.bottomLabel": "Bas", + "visTypeTimeseries.markdown.alignOptions.middleLabel": "Milieu", + "visTypeTimeseries.markdown.alignOptions.topLabel": "Haut", + "visTypeTimeseries.markdown.dataTab.dataButtonLabel": "Données", + "visTypeTimeseries.markdown.dataTab.metricsButtonLabel": "Indicateurs", + "visTypeTimeseries.markdown.editor.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.markdown.editor.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.markdown.editor.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.markdown.editor.labelPlaceholder": "Étiquette", + "visTypeTimeseries.markdown.editor.toggleEditorAriaLabel": "Activer/Désactiver l'éditeur de séries", + "visTypeTimeseries.markdown.editor.variableNamePlaceholder": "Nom de la variable", + "visTypeTimeseries.markdown.optionsTab.backgroundColorLabel": "Couleur d'arrière-plan :", + "visTypeTimeseries.markdown.optionsTab.customCSSLabel": "CSS personnalisé (prend en charge Less)", + "visTypeTimeseries.markdown.optionsTab.dataLabel": "Données", + "visTypeTimeseries.markdown.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.markdown.optionsTab.openLinksInNewTab": "Ouvrir les liens dans un nouvel onglet ?", + "visTypeTimeseries.markdown.optionsTab.optionsButtonLabel": "Options", + "visTypeTimeseries.markdown.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.markdown.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.markdown.optionsTab.showScrollbarsLabel": "Afficher les barres de défilement ?", + "visTypeTimeseries.markdown.optionsTab.styleLabel": "Style", + "visTypeTimeseries.markdown.optionsTab.verticalAlignmentLabel": "Alignement vertical :", + "visTypeTimeseries.markdownEditor.howToAccessEntireTreeDescription": "Il existe également une variable spéciale nommée {all} que vous pouvez utiliser pour accéder à l'ensemble de l'arborescence. C'est utile pour créer des listes avec des données à l'aide d'une action Regrouper par :", + "visTypeTimeseries.markdownEditor.howToUseVariablesInMarkdownDescription": "Les variables suivantes peuvent être utilisées dans Markdown à l'aide de la syntaxe Handlebar (moustache). {handlebarLink} sur les expressions disponibles.", + "visTypeTimeseries.markdownEditor.howUseVariablesInMarkdownDescription.documentationLinkText": "Cliquer ici pour la documentation", + "visTypeTimeseries.markdownEditor.nameLabel": "Nom", + "visTypeTimeseries.markdownEditor.noVariablesAvailableDescription": "Aucune variable disponible pour les indicateurs de données sélectionnés.", + "visTypeTimeseries.markdownEditor.valueLabel": "Valeur", + "visTypeTimeseries.math.aggregationLabel": "Agrégation", + "visTypeTimeseries.math.expressionDescription": "Ce champ utilise des expressions mathématiques de base (voir {link}). Les variables sont des clés sur l'objet {params}, c.-à-d. {paramsName}. Pour accéder à toutes les données, utilisez {paramsValues} pour un tableau de valeurs et {paramsTimestamps} pour un tableau d’horodatages. {paramsTimestamp} est disponible pour l'horodatage du compartiment actuel, {paramsIndex} est disponible pour l'index du compartiment actuel et {paramsInterval} est disponible pour l'intervalle en millisecondes.", + "visTypeTimeseries.math.expressionDescription.tinyMathLinkText": "TinyMath", + "visTypeTimeseries.math.expressionLabel": "Expression", + "visTypeTimeseries.math.variablesLabel": "Variables", + "visTypeTimeseries.metric.dataTab.dataButtonLabel": "Données", + "visTypeTimeseries.metric.dataTab.metricsButtonLabel": "Indicateurs", + "visTypeTimeseries.metric.editor.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.metric.editor.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.metric.editor.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.metric.editor.labelPlaceholder": "Étiquette", + "visTypeTimeseries.metric.editor.toggleEditorAriaLabel": "Activer/Désactiver l'éditeur de séries", + "visTypeTimeseries.metric.optionsTab.colorRulesLabel": "Règles de couleur", + "visTypeTimeseries.metric.optionsTab.dataLabel": "Données", + "visTypeTimeseries.metric.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.metric.optionsTab.optionsButtonLabel": "Options", + "visTypeTimeseries.metric.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.metric.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.metricMissingErrorMessage": "Indicateur manquant {field}", + "visTypeTimeseries.metricSelect.selectMetricPlaceholder": "Sélectionner l'indicateur…", + "visTypeTimeseries.missingPanelConfigDescription": "Configuration de panneau manquante pour \"{modelType}\"", + "visTypeTimeseries.movingAverage.aggregationLabel": "Agrégation", + "visTypeTimeseries.movingAverage.alpha": "Alpha", + "visTypeTimeseries.movingAverage.beta": "Bêta", + "visTypeTimeseries.movingAverage.gamma": "Gamma", + "visTypeTimeseries.movingAverage.metricLabel": "Indicateur", + "visTypeTimeseries.movingAverage.model.selectPlaceholder": "Sélectionner", + "visTypeTimeseries.movingAverage.modelLabel": "Modèle", + "visTypeTimeseries.movingAverage.modelOptions.exponentiallyWeightedLabel": "Pondéré exponentiellement", + "visTypeTimeseries.movingAverage.modelOptions.holtLinearLabel": "Holt–Linéaire", + "visTypeTimeseries.movingAverage.modelOptions.holtWintersLabel": "Holt-Winters", + "visTypeTimeseries.movingAverage.modelOptions.linearLabel": "Linéaire", + "visTypeTimeseries.movingAverage.modelOptions.simpleLabel": "Simple", + "visTypeTimeseries.movingAverage.multiplicative": "Multiplicative", + "visTypeTimeseries.movingAverage.multiplicative.selectPlaceholder": "Sélectionner", + "visTypeTimeseries.movingAverage.multiplicativeOptions.false": "Faux", + "visTypeTimeseries.movingAverage.multiplicativeOptions.true": "Vrai", + "visTypeTimeseries.movingAverage.period": "Période", + "visTypeTimeseries.movingAverage.windowSizeHint": "La fenêtre doit toujours être au moins deux fois plus grande que la période.", + "visTypeTimeseries.movingAverage.windowSizeLabel": "Taille de la fenêtre", + "visTypeTimeseries.noButtonLabel": "Non", + "visTypeTimeseries.percentile.aggregationLabel": "Agrégation", + "visTypeTimeseries.percentile.fieldLabel": "Champ", + "visTypeTimeseries.percentile.fillToLabel": "Remplir à :", + "visTypeTimeseries.percentile.modeLabel": "Mode :", + "visTypeTimeseries.percentile.modeOptions.bandLabel": "Bande", + "visTypeTimeseries.percentile.modeOptions.lineLabel": "Ligne", + "visTypeTimeseries.percentile.percentile": "Centile", + "visTypeTimeseries.percentile.percentileAriaLabel": "Centile", + "visTypeTimeseries.percentile.percents": "Pour cent", + "visTypeTimeseries.percentile.shadeLabel": "Ombre (0 à 1) :", + "visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits": "Nombre de chiffres à valeur significative (histogramme HDR)", + "visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits.hint": "L'histogramme HDR (High Dynamic Range, grande plage dynamique) est une autre implémentation qui peut être utile lors du calcul des rangs centiles pour les mesures de la latence, car elle peut être plus rapide que l'implémentation t-digest, bien qu'elle présente une empreinte mémoire plus élevée. Le paramètre \"Nombre de chiffres à valeur significative\" spécifie le nombre de chiffres significatifs pour la résolution des valeurs de l'histogramme.", + "visTypeTimeseries.percentileRank.aggregationLabel": "Agrégation", + "visTypeTimeseries.percentileRank.fieldLabel": "Champ", + "visTypeTimeseries.percentileRank.values": "Valeurs", + "visTypeTimeseries.positiveOnly.aggregationLabel": "Agrégation", + "visTypeTimeseries.positiveOnly.metricLabel": "Indicateur", + "visTypeTimeseries.positiveRate.aggregationLabel": "Agrégation", + "visTypeTimeseries.positiveRate.helpText": "Cette agrégation ne doit être appliquée qu'à {link} ; il s'agit d'un raccourci pour appliquer Max., Dérivée et Positif uniquement à un champ.", + "visTypeTimeseries.positiveRate.helpTextLink": "nombres augmentant de manière monolithique", + "visTypeTimeseries.positiveRate.unitSelectPlaceholder": "Sélectionner le scaling…", + "visTypeTimeseries.positiveRate.unitsLabel": "Scaling", + "visTypeTimeseries.postiveRate.fieldLabel": "Champ", + "visTypeTimeseries.replaceVars.errors.markdownErrorDescription": "Veuillez vérifier que vous utilisez uniquement Markdown, des variables connues et des expressions Handlebar intégrées.", + "visTypeTimeseries.replaceVars.errors.markdownErrorTitle": "Erreur lors du traitement de votre Markdown", + "visTypeTimeseries.replaceVars.errors.unknownVarDescription": "{badVar} est une variable inconnue.", + "visTypeTimeseries.replaceVars.errors.unknownVarTitle": "Erreur lors du traitement de votre Markdown", + "visTypeTimeseries.searchStrategyUndefinedErrorMessage": "La stratégie de recherche n'était pas définie.", + "visTypeTimeseries.serialDiff.aggregationLabel": "Agrégation", + "visTypeTimeseries.serialDiff.lagLabel": "Décalage", + "visTypeTimeseries.serialDiff.metricLabel": "Indicateur", + "visTypeTimeseries.series.missingAggregationKeyErrorMessage": "La clé des agrégations est manquante dans la réponse. Vérifiez vos autorisations pour cette requête.", + "visTypeTimeseries.series.shouldOneSeriesPerRequestErrorMessage": "Il ne devrait y avoir qu'une seule série par requête.", + "visTypeTimeseries.seriesAgg.aggregationLabel": "Agrégation", + "visTypeTimeseries.seriesAgg.functionLabel": "Fonction", + "visTypeTimeseries.seriesAgg.functionOptions.avgLabel": "Moy.", + "visTypeTimeseries.seriesAgg.functionOptions.countLabel": "Nombre de séries", + "visTypeTimeseries.seriesAgg.functionOptions.cumulativeSumLabel": "Somme cumulée", + "visTypeTimeseries.seriesAgg.functionOptions.maxLabel": "Max.", + "visTypeTimeseries.seriesAgg.functionOptions.minLabel": "Min.", + "visTypeTimeseries.seriesAgg.functionOptions.overallAvgLabel": "Moy. générale", + "visTypeTimeseries.seriesAgg.functionOptions.overallMaxLabel": "Max. général", + "visTypeTimeseries.seriesAgg.functionOptions.overallMinLabel": "Min. général", + "visTypeTimeseries.seriesAgg.functionOptions.overallSumLabel": "Somme générale", + "visTypeTimeseries.seriesAgg.functionOptions.sumLabel": "Somme", + "visTypeTimeseries.seriesAgg.seriesAggIsNotCompatibleLabel": "L'agrégation de séries n'est pas compatible avec la visualisation de tableau.", + "visTypeTimeseries.seriesConfig.filterLabel": "Filtre", + "visTypeTimeseries.seriesConfig.ignoreGlobalFilterDisabledTooltip": "Cette option est désactivée, car les filtres globaux sont ignorés dans les options du panneau.", + "visTypeTimeseries.seriesConfig.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.seriesConfig.missingSeriesComponentDescription": "Composant de série manquant pour le type de panneau : {panelType}", + "visTypeTimeseries.seriesConfig.offsetSeriesTimeLabel": "Décaler l'heure de la série de (1m, 1h, 1w, 1d)", + "visTypeTimeseries.seriesConfig.templateHelpText": "par ex. {templateExample}", + "visTypeTimeseries.seriesConfig.templateLabel": "Modèle", + "visTypeTimeseries.sort.dragToSortAriaLabel": "Faire glisser pour trier", + "visTypeTimeseries.sort.dragToSortTooltip": "Faire glisser pour trier", + "visTypeTimeseries.splits.everything.groupByLabel": "Regrouper par", + "visTypeTimeseries.splits.filter.groupByLabel": "Regrouper par", + "visTypeTimeseries.splits.filter.queryStringLabel": "Chaîne de requête", + "visTypeTimeseries.splits.filterItems.labelAriaLabel": "Étiquette", + "visTypeTimeseries.splits.filterItems.labelPlaceholder": "Étiquette", + "visTypeTimeseries.splits.filters.groupByLabel": "Regrouper par", + "visTypeTimeseries.splits.groupBySelect.modeOptions.everythingLabel": "Tout", + "visTypeTimeseries.splits.groupBySelect.modeOptions.filterLabel": "Filtre", + "visTypeTimeseries.splits.groupBySelect.modeOptions.filtersLabel": "Filtres", + "visTypeTimeseries.splits.groupBySelect.modeOptions.termsLabel": "Termes", + "visTypeTimeseries.splits.terms.byLabel": "Par", + "visTypeTimeseries.splits.terms.defaultCountLabel": "Nombre de docs (par défaut)", + "visTypeTimeseries.splits.terms.directionLabel": "Sens", + "visTypeTimeseries.splits.terms.dirOptions.ascendingLabel": "Croissant", + "visTypeTimeseries.splits.terms.dirOptions.descendingLabel": "Décroissant", + "visTypeTimeseries.splits.terms.excludeLabel": "Exclure", + "visTypeTimeseries.splits.terms.groupByLabel": "Regrouper par", + "visTypeTimeseries.splits.terms.includeLabel": "Inclure", + "visTypeTimeseries.splits.terms.orderByLabel": "Classer par", + "visTypeTimeseries.splits.terms.sizePlaceholder": "Taille", + "visTypeTimeseries.splits.terms.termsLabel": "Termes", + "visTypeTimeseries.splits.terms.topLabel": "Haut", + "visTypeTimeseries.static.aggregationLabel": "Agrégation", + "visTypeTimeseries.static.staticValuesLabel": "Valeur statique", + "visTypeTimeseries.stdAgg.aggregationLabel": "Agrégation", + "visTypeTimeseries.stdAgg.fieldLabel": "Champ", + "visTypeTimeseries.stdDeviation.aggregationLabel": "Agrégation", + "visTypeTimeseries.stdDeviation.fieldLabel": "Champ", + "visTypeTimeseries.stdDeviation.modeLabel": "Mode", + "visTypeTimeseries.stdDeviation.modeOptions.boundsBandLabel": "Bande de limites", + "visTypeTimeseries.stdDeviation.modeOptions.lowerBoundLabel": "Limite inférieure", + "visTypeTimeseries.stdDeviation.modeOptions.rawLabel": "Brut", + "visTypeTimeseries.stdDeviation.modeOptions.upperBoundLabel": "Limite supérieure", + "visTypeTimeseries.stdDeviation.sigmaLabel": "Sigma", + "visTypeTimeseries.stdSibling.aggregationLabel": "Agrégation", + "visTypeTimeseries.stdSibling.metricLabel": "Indicateur", + "visTypeTimeseries.stdSibling.modeLabel": "Mode", + "visTypeTimeseries.stdSibling.modeOptions.boundsBandLabel": "Bande de limites", + "visTypeTimeseries.stdSibling.modeOptions.lowerBoundLabel": "Limite inférieure", + "visTypeTimeseries.stdSibling.modeOptions.rawLabel": "Brut", + "visTypeTimeseries.stdSibling.modeOptions.upperBoundLabel": "Limite supérieure", + "visTypeTimeseries.stdSibling.sigmaLabel": "Sigma", + "visTypeTimeseries.table.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.table.aggregateFunctionLabel": "Fonction agrégée", + "visTypeTimeseries.table.avgLabel": "Moy.", + "visTypeTimeseries.table.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.table.colorRulesLabel": "Règles de couleurs", + "visTypeTimeseries.table.columnNotSortableTooltip": "Cette colonne ne peut pas être triée", + "visTypeTimeseries.table.cumulativeSumLabel": "Somme cumulée", + "visTypeTimeseries.table.dataTab.columnLabel": "Étiquette de colonne", + "visTypeTimeseries.table.dataTab.columnsButtonLabel": "Colonnes", + "visTypeTimeseries.table.dataTab.defineFieldDescription": "Pour la visualisation du tableau, vous devez définir un champ sur lequel effectuer le regroupement, en utilisant une agrégation de termes.", + "visTypeTimeseries.table.dataTab.groupByFieldLabel": "Champ Regrouper par", + "visTypeTimeseries.table.dataTab.rowsLabel": "Lignes", + "visTypeTimeseries.table.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.table.fieldLabel": "Champ", + "visTypeTimeseries.table.filterLabel": "Filtre", + "visTypeTimeseries.table.labelAriaLabel": "Étiquette", + "visTypeTimeseries.table.labelPlaceholder": "Étiquette", + "visTypeTimeseries.table.maxLabel": "Max", + "visTypeTimeseries.table.minLabel": "Min", + "visTypeTimeseries.table.noResultsAvailableWithDescriptionMessage": "Aucun résultat disponible. Vous devez choisir un champ Regrouper par pour cette visualisation.", + "visTypeTimeseries.table.optionsTab.dataLabel": "Données", + "visTypeTimeseries.table.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.table.optionsTab.itemUrlHelpText": "Prend en charge les modèles de moustaches. {key} est défini sur le terme.", + "visTypeTimeseries.table.optionsTab.itemUrlLabel": "URL de l'élément", + "visTypeTimeseries.table.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.table.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.table.overallAvgLabel": "Moy. générale", + "visTypeTimeseries.table.overallMaxLabel": "Max général", + "visTypeTimeseries.table.overallMinLabel": "Min général", + "visTypeTimeseries.table.overallSumLabel": "Somme générale", + "visTypeTimeseries.table.showTrendArrowsLabel": "Afficher les flèches de tendance ?", + "visTypeTimeseries.table.sumLabel": "Somme", + "visTypeTimeseries.table.tab.metricsLabel": "Indicateurs", + "visTypeTimeseries.table.tab.optionsLabel": "Options", + "visTypeTimeseries.table.templateHelpText": "par ex. {templateExample}", + "visTypeTimeseries.table.templateLabel": "Modèle", + "visTypeTimeseries.table.toggleSeriesEditorAriaLabel": "Basculer l'éditeur de séries", + "visTypeTimeseries.timeSeries.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.timeseries.annotationsTab.annotationsButtonLabel": "Annotations", + "visTypeTimeseries.timeSeries.axisMaxLabel": "Max. de l'axe", + "visTypeTimeseries.timeSeries.axisMinLabel": "Min. de l'axe", + "visTypeTimeseries.timeSeries.axisPositionLabel": "Position de l'axe", + "visTypeTimeseries.timeSeries.barLabel": "Barre", + "visTypeTimeseries.timeSeries.chartBar.chartTypeLabel": "Type de graphique", + "visTypeTimeseries.timeSeries.chartBar.fillLabel": "Remplissage (0 à 1)", + "visTypeTimeseries.timeSeries.chartBar.lineWidthLabel": "Largeur de la ligne", + "visTypeTimeseries.timeSeries.chartBar.stackedLabel": "Empilé", + "visTypeTimeseries.timeSeries.chartLine.chartTypeLabel": "Type de graphique", + "visTypeTimeseries.timeSeries.chartLine.fillLabel": "Remplissage (0 à 1)", + "visTypeTimeseries.timeSeries.chartLine.lineWidthLabel": "Largeur de la ligne", + "visTypeTimeseries.timeSeries.chartLine.pointSizeLabel": "Taille du point", + "visTypeTimeseries.timeSeries.chartLine.stackedLabel": "Empilé", + "visTypeTimeseries.timeSeries.chartLine.stepsLabel": "Étapes", + "visTypeTimeseries.timeSeries.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.timeseries.dataTab.dataButtonLabel": "Données", + "visTypeTimeseries.timeSeries.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.timeSeries.gradientLabel": "Gradient", + "visTypeTimeseries.timeSeries.hideInLegendLabel": "Masquer dans la légende", + "visTypeTimeseries.timeSeries.labelPlaceholder": "Étiquette", + "visTypeTimeseries.timeSeries.leftLabel": "Gauche", + "visTypeTimeseries.timeseries.legendPositionOptions.bottomLabel": "Bas", + "visTypeTimeseries.timeseries.legendPositionOptions.leftLabel": "Gauche", + "visTypeTimeseries.timeseries.legendPositionOptions.rightLabel": "Droite", + "visTypeTimeseries.timeSeries.lineLabel": "Ligne", + "visTypeTimeseries.timeSeries.noneLabel": "Aucun", + "visTypeTimeseries.timeSeries.offsetSeriesTimeLabel": "Décaler l'heure de la série de (1m, 1h, 1w, 1d)", + "visTypeTimeseries.timeseries.optionsTab.axisMaxLabel": "Max. de l'axe", + "visTypeTimeseries.timeseries.optionsTab.axisMinLabel": "Min. de l'axe", + "visTypeTimeseries.timeseries.optionsTab.axisPositionLabel": "Position de l'axe", + "visTypeTimeseries.timeseries.optionsTab.axisScaleLabel": "Échelle de l'axe", + "visTypeTimeseries.timeseries.optionsTab.backgroundColorLabel": "Couleur de l'arrière-plan :", + "visTypeTimeseries.timeseries.optionsTab.dataLabel": "Données", + "visTypeTimeseries.timeseries.optionsTab.displayGridLabel": "Afficher la grille", + "visTypeTimeseries.timeseries.optionsTab.ignoreDaylightTimeLabel": "Ignorer l'heure d'été ?", + "visTypeTimeseries.timeseries.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.timeseries.optionsTab.legendPositionLabel": "Position de la légende", + "visTypeTimeseries.timeseries.optionsTab.maxLinesLabel": "Nombre maxi de lignes de légende", + "visTypeTimeseries.timeseries.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.timeseries.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.timeseries.optionsTab.showLegendLabel": "Afficher la légende ?", + "visTypeTimeseries.timeseries.optionsTab.styleLabel": "Style", + "visTypeTimeseries.timeseries.optionsTab.tooltipMode": "Infobulle", + "visTypeTimeseries.timeseries.optionsTab.truncateLegendLabel": "Tronquer la légende ?", + "visTypeTimeseries.timeSeries.percentLabel": "Pour cent", + "visTypeTimeseries.timeseries.positionOptions.leftLabel": "Gauche", + "visTypeTimeseries.timeseries.positionOptions.rightLabel": "Droite", + "visTypeTimeseries.timeSeries.rainbowLabel": "Arc-en-ciel", + "visTypeTimeseries.timeSeries.rightLabel": "Droite", + "visTypeTimeseries.timeseries.scaleOptions.logLabel": "Logarithmique", + "visTypeTimeseries.timeseries.scaleOptions.normalLabel": "Normal", + "visTypeTimeseries.timeSeries.separateAxisLabel": "Axe séparé ?", + "visTypeTimeseries.timeSeries.splitColorThemeLabel": "Thème de couleurs de division", + "visTypeTimeseries.timeSeries.stackedLabel": "Empilé", + "visTypeTimeseries.timeSeries.stackedWithinSeriesLabel": "Empilé dans la série", + "visTypeTimeseries.timeSeries.tab.metricsLabel": "Indicateurs", + "visTypeTimeseries.timeSeries.tab.optionsLabel": "Options", + "visTypeTimeseries.timeSeries.templateHelpText": "par ex. {templateExample}", + "visTypeTimeseries.timeSeries.templateLabel": "Modèle", + "visTypeTimeseries.timeSeries.toggleSeriesEditorAriaLabel": "Basculer l'éditeur de séries", + "visTypeTimeseries.timeseries.tooltipOptions.showAll": "Afficher toutes les valeurs", + "visTypeTimeseries.timeseries.tooltipOptions.showFocused": "Afficher les valeurs ciblées", + "visTypeTimeseries.topHit.aggregateWith.selectPlaceholder": "Sélectionner…", + "visTypeTimeseries.topHit.aggregateWithLabel": "Agréger avec", + "visTypeTimeseries.topHit.aggregationLabel": "Agrégation", + "visTypeTimeseries.topHit.aggWithOptions.averageLabel": "Moy.", + "visTypeTimeseries.topHit.aggWithOptions.concatenate": "Concaténer", + "visTypeTimeseries.topHit.aggWithOptions.maxLabel": "Max", + "visTypeTimeseries.topHit.aggWithOptions.minLabel": "Min", + "visTypeTimeseries.topHit.aggWithOptions.sumLabel": "Somme", + "visTypeTimeseries.topHit.fieldLabel": "Champ", + "visTypeTimeseries.topHit.order.selectPlaceholder": "Sélectionner…", + "visTypeTimeseries.topHit.orderByLabel": "Classer par", + "visTypeTimeseries.topHit.orderLabel": "Ordre", + "visTypeTimeseries.topHit.orderOptions.ascLabel": "Croiss.", + "visTypeTimeseries.topHit.orderOptions.descLabel": "Décroiss.", + "visTypeTimeseries.topHit.sizeLabel": "Taille", + "visTypeTimeseries.topN.addSeriesTooltip": "Ajouter une série", + "visTypeTimeseries.topN.cloneSeriesTooltip": "Cloner la série", + "visTypeTimeseries.topN.dataTab.dataButtonLabel": "Données", + "visTypeTimeseries.topN.deleteSeriesTooltip": "Supprimer la série", + "visTypeTimeseries.topN.labelPlaceholder": "Étiquette", + "visTypeTimeseries.topN.optionsTab.backgroundColorLabel": "Couleur de l'arrière-plan :", + "visTypeTimeseries.topN.optionsTab.colorRulesLabel": "Règles de couleurs", + "visTypeTimeseries.topN.optionsTab.dataLabel": "Données", + "visTypeTimeseries.topN.optionsTab.ignoreGlobalFilterLabel": "Ignorer le filtre global ?", + "visTypeTimeseries.topN.optionsTab.itemUrlDescription": "Prend en charge les modèles de moustaches. {key} est défini sur le terme.", + "visTypeTimeseries.topN.optionsTab.itemUrlLabel": "URL de l'élément", + "visTypeTimeseries.topN.optionsTab.panelFilterLabel": "Filtre de panneau", + "visTypeTimeseries.topN.optionsTab.panelOptionsButtonLabel": "Options du panneau", + "visTypeTimeseries.topN.optionsTab.styleLabel": "Style", + "visTypeTimeseries.topN.tab.metricsLabel": "Indicateurs", + "visTypeTimeseries.topN.tab.optionsLabel": "Options", + "visTypeTimeseries.topN.toggleSeriesEditorAriaLabel": "Basculer l'éditeur de séries", + "visTypeTimeseries.units.auto": "auto", + "visTypeTimeseries.units.perDay": "par jour", + "visTypeTimeseries.units.perHour": "par heure", + "visTypeTimeseries.units.perMillisecond": "par milliseconde", + "visTypeTimeseries.units.perMinute": "par minute", + "visTypeTimeseries.units.perSecond": "par seconde", + "visTypeTimeseries.unsupportedSplit.splitIsUnsupportedDescription": "Diviser par {modelType} n'est pas pris en charge.", + "visTypeTimeseries.vars.variableNameAriaLabel": "Nom de la variable", + "visTypeTimeseries.vars.variableNamePlaceholder": "Nom de la variable", + "visTypeTimeseries.visEditorVisualization.applyChangesLabel": "Appliquer les modifications", + "visTypeTimeseries.visEditorVisualization.autoApplyLabel": "Appliquer automatiquement", + "visTypeTimeseries.visEditorVisualization.changesHaveNotBeenAppliedMessage": "Les modifications apportées à cette visualisation n'ont pas été appliquées.", + "visTypeTimeseries.visEditorVisualization.changesSuccessfullyAppliedMessage": "Les dernières modifications ont été appliquées.", + "visTypeTimeseries.visEditorVisualization.changesWillBeAutomaticallyAppliedMessage": "Les modifications seront appliquées automatiquement.", + "visTypeTimeseries.visPicker.gaugeLabel": "Jauge", + "visTypeTimeseries.visPicker.metricLabel": "Indicateur", + "visTypeTimeseries.visPicker.tableLabel": "Tableau", + "visTypeTimeseries.visPicker.timeSeriesLabel": "Séries temporelles", + "visTypeTimeseries.visPicker.topNLabel": "N premiers", + "visTypeTimeseries.yesButtonLabel": "Oui", + "visTypeVega.editor.formatError": "Erreur lors du formatage des spécifications", + "visTypeVega.editor.reformatAsHJSONButtonLabel": "Reformater en HJSON", + "visTypeVega.editor.reformatAsJSONButtonLabel": "Reformater en JSON, supprimer les commentaires", + "visTypeVega.editor.vegaDocumentationLinkText": "Documentation Vega", + "visTypeVega.editor.vegaEditorOptionsButtonAriaLabel": "Options de l'éditeur Vega", + "visTypeVega.editor.vegaHelpButtonAriaLabel": "Aide Vega", + "visTypeVega.editor.vegaHelpLinkText": "Aide Kibana Vega", + "visTypeVega.editor.vegaLiteDocumentationLinkText": "Documentation Vega-Lite", + "visTypeVega.emsFileParser.emsFileNameDoesNotExistErrorMessage": "{emsfile} {emsfileName} n'existe pas", + "visTypeVega.emsFileParser.missingNameOfFileErrorMessage": "{dataUrlParam} avec {dataUrlParamValue} requiert le paramètre {nameParam} (nom du fichier)", + "visTypeVega.esQueryParser.autointervalValueTypeErrorMessage": "{autointerval} doit être {trueValue} ou un nombre", + "visTypeVega.esQueryParser.dataUrlMustNotHaveLegacyAndBodyQueryValuesAtTheSameTimeErrorMessage": "{dataUrlParam} ne doit pas avoir de {legacyContext} existant et de valeurs {bodyQueryConfigName} en même temps", + "visTypeVega.esQueryParser.dataUrlMustNotHaveLegacyContextTogetherWithContextOrTimefieldErrorMessage": "{dataUrlParam} ne doit pas avoir de {legacyContext} avec {context} ou {timefield}", + "visTypeVega.esQueryParser.legacyContextCanBeTrueErrorMessage": "{legacyContext} existant peut être {trueValue} (ignore le sélecteur de plage temporelle), ou il peut s'agir du nom du champ temporel, par ex. {timestampParam}", + "visTypeVega.esQueryParser.legacyUrlShouldChangeToWarningMessage": "{urlParam} existant : {legacyUrl} doit être modifié en {result}", + "visTypeVega.esQueryParser.shiftMustValueTypeErrorMessage": "{shiftParam} doit être une valeur numérique", + "visTypeVega.esQueryParser.timefilterValueErrorMessage": "La propriété {timefilter} doit être définie sur {trueValue}, {minValue} ou {maxValue}", + "visTypeVega.esQueryParser.unknownUnitValueErrorMessage": "Valeur {unitParamName} inconnue. Doit être l'une des valeurs suivantes : [{unitParamValues}]", + "visTypeVega.esQueryParser.unnamedRequest": "Requête sans nom #{index}", + "visTypeVega.esQueryParser.urlBodyValueTypeErrorMessage": "{configName} doit être un objet", + "visTypeVega.esQueryParser.urlContextAndUrlTimefieldMustNotBeUsedErrorMessage": "{urlContext} et {timefield} ne doivent pas être utilisés lorsque {queryParam} est défini", + "visTypeVega.function.help": "Visualisation Vega", + "visTypeVega.inspector.dataSetsLabel": "Ensembles de données", + "visTypeVega.inspector.dataViewer.dataSetAriaLabel": "Ensemble de données", + "visTypeVega.inspector.dataViewer.gridAriaLabel": "Grille de données {name}", + "visTypeVega.inspector.signalValuesLabel": "Valeurs de signal", + "visTypeVega.inspector.signalViewer.gridAriaLabel": "Grille de données des valeurs de signal", + "visTypeVega.inspector.specLabel": "Spéc.", + "visTypeVega.inspector.specViewer.copyToClipboardLabel": "Copier dans le presse-papiers", + "visTypeVega.inspector.vegaAdapter.signal": "Signal", + "visTypeVega.inspector.vegaAdapter.value": "Valeur", + "visTypeVega.inspector.vegaDebugLabel": "Débogage Vega", + "visTypeVega.mapView.experimentalMapLayerInfo": "Les calques de cartes sont expérimentaux et ne sont pas soumis aux accords de niveau de service d'assistance des fonctionnalités officielles en disponibilité générale. Pour apporter des commentaires, veuillez créer une entrée dans {githubLink}.", + "visTypeVega.mapView.mapStyleNotFoundWarningMessage": "{mapStyleParam} est introuvable", + "visTypeVega.mapView.minZoomAndMaxZoomHaveBeenSwappedWarningMessage": "{minZoomPropertyName} et {maxZoomPropertyName} ont été permutés", + "visTypeVega.mapView.resettingPropertyToMaxValueWarningMessage": "Réinitialisation de {name} sur {max}", + "visTypeVega.mapView.resettingPropertyToMinValueWarningMessage": "Réinitialisation de {name} sur {min}", + "visTypeVega.type.vegaDescription": "Utilisez Vega pour créer de nouveaux types de visualisations.", + "visTypeVega.type.vegaNote": "Requiert une connaissance de la syntaxe Vega.", + "visTypeVega.type.vegaTitleInWizard": "Visualisation personnalisée", + "visTypeVega.urlParser.dataUrlRequiresUrlParameterInFormErrorMessage": "{dataUrlParam} requiert un paramètre {urlParam} sous la forme \"{formLink}\"", + "visTypeVega.urlParser.urlShouldHaveQuerySubObjectWarningMessage": "L'utilisation d'un {urlObject} requiert un sous-objet {subObjectName}", + "visTypeVega.vegaParser.autoSizeDoesNotAllowFalse": "{autoSizeParam} est activé ; il peut uniquement être désactivé en définissant {autoSizeParam} sur {noneParam}", + "visTypeVega.vegaParser.baseView.externalUrlsAreNotEnabledErrorMessage": "Les URL externes ne sont pas activées. Ajouter {enableExternalUrls} à {kibanaConfigFileName}", + "visTypeVega.vegaParser.baseView.functionIsNotDefinedForGraphErrorMessage": "{funcName} n'est pas défini pour ce graphe", + "visTypeVega.vegaParser.baseView.indexNotFoundErrorMessage": "Impossible de trouver l'index {index}", + "visTypeVega.vegaParser.baseView.timeValuesTypeErrorMessage": "Erreur lors de la définition du filtre de temps : les deux valeurs temporelles doivent être des dates relatives ou absolues. {start}, {end}", + "visTypeVega.vegaParser.baseView.unableToFindDefaultIndexErrorMessage": "Impossible de trouver l'index par défaut", + "visTypeVega.vegaParser.centerOnMarkConfigValueTypeErrorMessage": "Les valeurs attendues pour {configName} sont {trueValue}, {falseValue} ou un nombre", + "visTypeVega.vegaParser.dataExceedsSomeParamsUseTimesLimitErrorMessage": "Les données ne doivent pas avoir plus d'un paramètre {urlParam}, {valuesParam} et {sourceParam}", + "visTypeVega.vegaParser.hostConfigIsDeprecatedWarningMessage": "{deprecatedConfigName} a été déclassé. Utilisez {newConfigName} à la place.", + "visTypeVega.vegaParser.hostConfigValueTypeErrorMessage": "S'il est présent, le paramètre {configName} doit être un objet", + "visTypeVega.vegaParser.inputSpecDoesNotSpecifySchemaErrorMessage": "Vos spécifications requièrent un champ {schemaParam} avec une URL valide pour\nVega (voir {vegaSchemaUrl}) ou\nVega-Lite (voir {vegaLiteSchemaUrl}).\nL'URL est uniquement un identificateur. Kibana et votre navigateur n'accéderont jamais à cette URL.", + "visTypeVega.vegaParser.invalidVegaSpecErrorMessage": "Spécification Vega non valide", + "visTypeVega.vegaParser.kibanaConfigValueTypeErrorMessage": "S'il est présent, le paramètre {configName} doit être un objet", + "visTypeVega.vegaParser.maxBoundsValueTypeWarningMessage": "{maxBoundsConfigName} doit être un tableau avec quatre nombres", + "visTypeVega.vegaParser.notSupportedUrlTypeErrorMessage": "{urlObject} n'est pas pris en charge", + "visTypeVega.vegaParser.notValidLibraryVersionForInputSpecWarningMessage": "Les spécifications d'entrée utilisent {schemaLibrary} {schemaVersion}, mais la version actuelle de {schemaLibrary} est {libraryVersion}.", + "visTypeVega.vegaParser.paddingConfigValueTypeErrorMessage": "La valeur attendue pour {configName} est un nombre", + "visTypeVega.vegaParser.someKibanaConfigurationIsNoValidWarningMessage": "{configName} n'est pas valide", + "visTypeVega.vegaParser.someKibanaParamValueTypeWarningMessage": "{configName} doit être une valeur booléenne", + "visTypeVega.vegaParser.textTruncateConfigValueTypeErrorMessage": "La valeur attendue pour {configName} est une valeur booléenne", + "visTypeVega.vegaParser.unexpectedValueForPositionConfigurationErrorMessage": "Valeur inattendue pour la configuration {configurationName}", + "visTypeVega.vegaParser.unrecognizedControlsLocationValueErrorMessage": "Valeur {controlsLocationParam} non reconnue. Valeur attendue parmi [{locToDirMap}]", + "visTypeVega.vegaParser.unrecognizedDirValueErrorMessage": "Valeur {dirParam} non reconnue. Valeur attendue parmi [{expectedValues}]", + "visTypeVega.vegaParser.VLCompilerShouldHaveGeneratedSingleProtectionObjectErrorMessage": "Erreur interne : le compilateur Vega-Lite aurait dû générer un objet de projection unique", + "visTypeVega.vegaParser.widthAndHeightParamsAreIgnored": "Les paramètres {widthParam} et {heightParam} sont ignorés, car {autoSizeParam} est activé. Pour le désactiver, définissez {autoSizeParam} sur {noneParam}", + "visTypeVega.vegaParser.widthAndHeightParamsAreRequired": "Aucun rendu n'est généré lorsque {autoSizeParam} est défini sur {noneParam} quand les spécifications {vegaLiteParam} à facette ou répétées sont utilisées. Pour y remédier, retirez {autoSizeParam} ou utilisez {vegaParam}.", + "visTypeVega.visualization.renderErrorTitle": "Erreur Vega", + "visTypeVega.visualization.unableToRenderWithoutDataWarningMessage": "Impossible de générer un rendu sans données", + "visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsText": "Nombre maximal de groupes pouvant être renvoyés par une source de données unique. Un nombre plus élevé pourra impacter négativement les performances de rendu du navigateur", + "visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsTitle": "Nombre maximal de groupes pour la carte thermique", + "visTypeVislib.aggResponse.allDocsTitle": "Tous les docs", + "visTypeVislib.controls.gaugeOptions.alignmentLabel": "Alignement", + "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "Étendre automatiquement la plage", + "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "Étend la plage jusqu'à la valeur maximale de vos données.", + "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "Type de jauge", + "visTypeVislib.controls.gaugeOptions.labelsTitle": "Étiquettes", + "visTypeVislib.controls.gaugeOptions.rangesTitle": "Plages", + "visTypeVislib.controls.gaugeOptions.showLabelsLabel": "Afficher les étiquettes", + "visTypeVislib.controls.gaugeOptions.showLegendLabel": "Afficher la légende", + "visTypeVislib.controls.gaugeOptions.showOutline": "Afficher le contour", + "visTypeVislib.controls.gaugeOptions.showScaleLabel": "Afficher l'échelle", + "visTypeVislib.controls.gaugeOptions.styleTitle": "Style", + "visTypeVislib.controls.gaugeOptions.subTextLabel": "Sous-étiquette", + "visTypeVislib.functions.pie.help": "Visualisation camembert", + "visTypeVislib.functions.vislib.help": "Visualisation Vislib", + "visTypeVislib.gauge.alignmentAutomaticTitle": "Automatique", + "visTypeVislib.gauge.alignmentHorizontalTitle": "Horizontal", + "visTypeVislib.gauge.alignmentVerticalTitle": "Vertical", + "visTypeVislib.gauge.gaugeDescription": "Affichez le statut d'un indicateur.", + "visTypeVislib.gauge.gaugeTitle": "Jauge", + "visTypeVislib.gauge.gaugeTypes.arcText": "Arc", + "visTypeVislib.gauge.gaugeTypes.circleText": "Cercle", + "visTypeVislib.gauge.groupTitle": "Diviser le groupe", + "visTypeVislib.gauge.metricTitle": "Indicateur", + "visTypeVislib.goal.goalDescription": "Suivez la progression d'un indicateur vers un objectif.", + "visTypeVislib.goal.goalTitle": "Objectif", + "visTypeVislib.goal.groupTitle": "Diviser le groupe", + "visTypeVislib.goal.metricTitle": "Indicateur", + "visTypeVislib.vislib.errors.noResultsFoundTitle": "Aucun résultat trouvé", + "visTypeVislib.vislib.heatmap.maxBucketsText": "Trop de séries sont définies ({nr}). La valeur de configuration maximale est {max}.", + "visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "Filtrer pour la valeur {legendDataLabel}", + "visTypeVislib.vislib.legend.filterOptionsLegend": "{legendDataLabel}, options de filtre", + "visTypeVislib.vislib.legend.filterOutValueButtonAriaLabel": "Filtrer la valeur {legendDataLabel}", + "visTypeVislib.vislib.legend.loadingLabel": "chargement…", + "visTypeVislib.vislib.legend.toggleLegendButtonAriaLabel": "Basculer la légende", + "visTypeVislib.vislib.legend.toggleLegendButtonTitle": "Basculer la légende", + "visTypeVislib.vislib.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}, options de basculement", + "visTypeVislib.vislib.tooltip.fieldLabel": "champ", + "visTypeVislib.vislib.tooltip.valueLabel": "valeur", + "visTypeXy.aggResponse.allDocsTitle": "Tous les docs", + "visTypeXy.area.areaDescription": "Mettez en avant les données entre un axe et une ligne.", + "visTypeXy.area.areaTitle": "Aire", + "visTypeXy.area.groupTitle": "Diviser la série", + "visTypeXy.area.metricsTitle": "Axe Y", + "visTypeXy.area.radiusTitle": "Taille du point", + "visTypeXy.area.segmentTitle": "Axe X", + "visTypeXy.area.splitTitle": "Diviser le graphique", + "visTypeXy.area.tabs.metricsAxesTitle": "Indicateurs et axes", + "visTypeXy.area.tabs.panelSettingsTitle": "Paramètres du panneau", + "visTypeXy.axisModes.normalText": "Normal", + "visTypeXy.axisModes.percentageText": "Pourcentage", + "visTypeXy.axisModes.silhouetteText": "Silhouette", + "visTypeXy.axisModes.wiggleText": "Ondulé", + "visTypeXy.categoryAxis.rotate.angledText": "En angle", + "visTypeXy.categoryAxis.rotate.horizontalText": "Horizontal", + "visTypeXy.categoryAxis.rotate.verticalText": "Vertical", + "visTypeXy.chartModes.normalText": "Normal", + "visTypeXy.chartModes.stackedText": "Empilé", + "visTypeXy.chartTypes.areaText": "Aire", + "visTypeXy.chartTypes.barText": "Barre", + "visTypeXy.chartTypes.lineText": "Ligne", + "visTypeXy.controls.pointSeries.categoryAxis.alignLabel": "Aligner", + "visTypeXy.controls.pointSeries.categoryAxis.filterLabelsLabel": "Étiquettes de filtre", + "visTypeXy.controls.pointSeries.categoryAxis.labelsTitle": "Étiquettes", + "visTypeXy.controls.pointSeries.categoryAxis.positionLabel": "Position", + "visTypeXy.controls.pointSeries.categoryAxis.showLabel": "Afficher les lignes et étiquettes de l'axe", + "visTypeXy.controls.pointSeries.categoryAxis.showLabelsLabel": "Afficher les étiquettes", + "visTypeXy.controls.pointSeries.categoryAxis.xAxisTitle": "Axe X", + "visTypeXy.controls.pointSeries.gridAxis.dontShowLabel": "Ne pas afficher", + "visTypeXy.controls.pointSeries.gridAxis.gridText": "Grille", + "visTypeXy.controls.pointSeries.gridAxis.xAxisLinesLabel": "Afficher les lignes de l'axe X", + "visTypeXy.controls.pointSeries.gridAxis.yAxisLinesLabel": "Lignes de l'axe Y", + "visTypeXy.controls.pointSeries.series.chartTypeLabel": "Type de graphique", + "visTypeXy.controls.pointSeries.series.circlesRadius": "Taille des points", + "visTypeXy.controls.pointSeries.series.lineModeLabel": "Mode ligne", + "visTypeXy.controls.pointSeries.series.lineWidthLabel": "Largeur de la ligne", + "visTypeXy.controls.pointSeries.series.metricsTitle": "Indicateurs", + "visTypeXy.controls.pointSeries.series.modeLabel": "Mode", + "visTypeXy.controls.pointSeries.series.newAxisLabel": "Nouvel axe…", + "visTypeXy.controls.pointSeries.series.showDotsLabel": "Afficher les points", + "visTypeXy.controls.pointSeries.series.showLineLabel": "Afficher la ligne", + "visTypeXy.controls.pointSeries.series.valueAxisLabel": "Axe des valeurs", + "visTypeXy.controls.pointSeries.seriesAccordionAriaLabel": "Basculer les options {agg}", + "visTypeXy.controls.pointSeries.valueAxes.addButtonTooltip": "Ajouter l'axe Y", + "visTypeXy.controls.pointSeries.valueAxes.customExtentsLabel": "Extensions personnalisées", + "visTypeXy.controls.pointSeries.valueAxes.maxLabel": "Max", + "visTypeXy.controls.pointSeries.valueAxes.minErrorMessage": "Min doit être inférieur à Max.", + "visTypeXy.controls.pointSeries.valueAxes.minLabel": "Min", + "visTypeXy.controls.pointSeries.valueAxes.minNeededScaleText": "Min doit être supérieur à 0 lorsqu'une échelle logarithmique est sélectionnée.", + "visTypeXy.controls.pointSeries.valueAxes.modeLabel": "Mode", + "visTypeXy.controls.pointSeries.valueAxes.positionLabel": "Position", + "visTypeXy.controls.pointSeries.valueAxes.removeButtonTooltip": "Retirer l'axe Y", + "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "Marge des limites", + "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "La marge des limites doit être supérieure ou égale à 0.", + "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "Scaler sur les limites de données", + "visTypeXy.controls.pointSeries.valueAxes.scaleTypeLabel": "Type d'échelle", + "visTypeXy.controls.pointSeries.valueAxes.setAxisExtentsLabel": "Définir la portée de l'axe", + "visTypeXy.controls.pointSeries.valueAxes.showLabel": "Afficher les lignes et étiquettes de l'axe", + "visTypeXy.controls.pointSeries.valueAxes.titleLabel": "Titre", + "visTypeXy.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "Basculer la portée personnalisée", + "visTypeXy.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "Basculer les options {axisName}", + "visTypeXy.controls.pointSeries.valueAxes.yAxisTitle": "Axes Y", + "visTypeXy.controls.truncateLabel": "Tronquer", + "visTypeXy.editors.elasticChartsOptions.detailedTooltip.label": "Afficher l'infobulle détaillée", + "visTypeXy.editors.elasticChartsOptions.detailedTooltip.tooltip": "Active l'ancienne infobulle détaillée pour l'affichage d'une valeur unique. Lorsque cette option est désactivée, une nouvelle infobulle résumée affichera plusieurs valeurs.", + "visTypeXy.editors.elasticChartsOptions.fillOpacity": "Opacité de remplissage", + "visTypeXy.editors.elasticChartsOptions.missingValuesLabel": "Remplir les valeurs manquantes", + "visTypeXy.editors.pointSeries.currentTimeMarkerLabel": "Repère de temps actuel", + "visTypeXy.editors.pointSeries.orderBucketsBySumLabel": "Classer les groupes par somme", + "visTypeXy.editors.pointSeries.settingsTitle": "Paramètres", + "visTypeXy.editors.pointSeries.showLabels": "Afficher les valeurs sur le graphique", + "visTypeXy.editors.pointSeries.thresholdLine.colorLabel": "Couleur de la ligne", + "visTypeXy.editors.pointSeries.thresholdLine.showLabel": "Afficher la ligne de seuil", + "visTypeXy.editors.pointSeries.thresholdLine.styleLabel": "Style de la ligne", + "visTypeXy.editors.pointSeries.thresholdLine.valueLabel": "Valeur seuil", + "visTypeXy.editors.pointSeries.thresholdLine.widthLabel": "Largeur de la ligne", + "visTypeXy.editors.pointSeries.thresholdLineSettingsTitle": "Ligne de seuil", + "visTypeXy.fittingFunctionsTitle.carry": "Dernière (remplit les blancs avec la dernière valeur)", + "visTypeXy.fittingFunctionsTitle.linear": "Linéaire (remplit les blancs avec une ligne)", + "visTypeXy.fittingFunctionsTitle.lookahead": "Suivante (remplit les blancs avec la valeur suivante)", + "visTypeXy.fittingFunctionsTitle.none": "Masquer (ne remplit pas les blancs)", + "visTypeXy.fittingFunctionsTitle.zero": "Zéro (remplit les blancs avec des zéros)", + "visTypeXy.function.adimension.bucket": "Groupe", + "visTypeXy.function.adimension.dotSize": "Taille du point", + "visTypeXy.function.args.addLegend.help": "Afficher la légende du graphique", + "visTypeXy.function.args.addTimeMarker.help": "Afficher le repère de temps", + "visTypeXy.function.args.addTooltip.help": "Afficher l'infobulle au survol", + "visTypeXy.function.args.args.chartType.help": "Type de graphique. Peut être linéaire, en aires ou histogramme", + "visTypeXy.function.args.categoryAxes.help": "Configuration de l'axe de catégorie", + "visTypeXy.function.args.detailedTooltip.help": "Afficher l'infobulle détaillée", + "visTypeXy.function.args.fillOpacity.help": "Définit l'opacité du remplissage du graphique en aires", + "visTypeXy.function.args.fittingFunction.help": "Nom de la fonction d'adaptation", + "visTypeXy.function.args.gridCategoryLines.help": "Afficher les lignes de catégories de la grille dans le graphique", + "visTypeXy.function.args.gridValueAxis.help": "Nom de l'axe des valeurs pour lequel la grille est affichée", + "visTypeXy.function.args.isVislibVis.help": "Indicateur des anciennes visualisations vislib. Utilisé pour la rétro-compatibilité, notamment pour les couleurs", + "visTypeXy.function.args.labels.help": "Configuration des étiquettes du graphique", + "visTypeXy.function.args.legendPosition.help": "Positionner la légende en haut, en bas, à gauche ou à droite du graphique", + "visTypeXy.function.args.orderBucketsBySum.help": "Classer les groupes par somme", + "visTypeXy.function.args.palette.help": "Définit le nom de la palette du graphique", + "visTypeXy.function.args.radiusRatio.help": "Rapport de taille des points", + "visTypeXy.function.args.seriesDimension.help": "Configuration de la dimension de la série", + "visTypeXy.function.args.seriesParams.help": "Configuration des paramètres de la série", + "visTypeXy.function.args.splitColumnDimension.help": "Configuration de la dimension Diviser par colonne", + "visTypeXy.function.args.splitRowDimension.help": "Configuration de la dimension Diviser par ligne", + "visTypeXy.function.args.thresholdLine.help": "Configuration de la ligne de seuil", + "visTypeXy.function.args.times.help": "Configuration du repère de temps", + "visTypeXy.function.args.valueAxes.help": "Configuration de l'axe des valeurs", + "visTypeXy.function.args.widthDimension.help": "Configuration de la dimension en largeur", + "visTypeXy.function.args.xDimension.help": "Configuration de la dimension de l'axe X", + "visTypeXy.function.args.yDimension.help": "Configuration de la dimension de l'axe Y", + "visTypeXy.function.args.zDimension.help": "Configuration de la dimension de l'axe Z", + "visTypeXy.function.categoryAxis.help": "Génère l'objet axe de catégorie", + "visTypeXy.function.categoryAxis.id.help": "ID de l'axe de catégorie", + "visTypeXy.function.categoryAxis.labels.help": "Configuration de l'étiquette de l'axe", + "visTypeXy.function.categoryAxis.position.help": "Position de l'axe de catégorie", + "visTypeXy.function.categoryAxis.scale.help": "Configuration de l'échelle", + "visTypeXy.function.categoryAxis.show.help": "Afficher l'axe de catégorie", + "visTypeXy.function.categoryAxis.title.help": "Titre de l'axe de catégorie", + "visTypeXy.function.categoryAxis.type.help": "Type de l'axe de catégorie. Peut être une catégorie ou une valeur", + "visTypeXy.function.dimension.metric": "Indicateur", + "visTypeXy.function.dimension.splitcolumn": "Division de colonne", + "visTypeXy.function.dimension.splitrow": "Division de ligne", + "visTypeXy.function.label.color.help": "Couleur de l'étiquette", + "visTypeXy.function.label.filter.help": "Masque les étiquettes qui se chevauchent et les éléments en double sur l'axe", + "visTypeXy.function.label.help": "Génère l'objet étiquette", + "visTypeXy.function.label.overwriteColor.help": "Écraser la couleur", + "visTypeXy.function.label.rotate.help": "Faire pivoter l'angle", + "visTypeXy.function.label.show.help": "Afficher l'étiquette", + "visTypeXy.function.label.truncate.help": "Nombre de symboles avant troncature", + "visTypeXy.function.scale.boundsMargin.help": "Marge des limites", + "visTypeXy.function.scale.defaultYExtents.help": "Indicateur qui permet de scaler sur les limites de données", + "visTypeXy.function.scale.help": "Génère l'objet échelle", + "visTypeXy.function.scale.max.help": "Valeur max", + "visTypeXy.function.scale.min.help": "Valeur min", + "visTypeXy.function.scale.mode.help": "Mode échelle. Peut être normal, pourcentage, ondulé ou silhouette", + "visTypeXy.function.scale.setYExtents.help": "Indicateur qui permet de définir votre propre portée", + "visTypeXy.function.scale.type.help": "Type d'échelle. Peut être linéaire, logarithmique ou racine carrée", + "visTypeXy.function.seriesParam.circlesRadius.help": "Définit la taille des cercles (rayon)", + "visTypeXy.function.seriesParam.drawLinesBetweenPoints.help": "Trace des lignes entre des points", + "visTypeXy.function.seriesparam.help": "Génère un objet paramètres de la série", + "visTypeXy.function.seriesParam.id.help": "ID des paramètres de la série", + "visTypeXy.function.seriesParam.interpolate.help": "Mode d'interpolation. Peut être linéaire, cardinal ou palier suivant", + "visTypeXy.function.seriesParam.label.help": "Nom des paramètres de la série", + "visTypeXy.function.seriesParam.lineWidth.help": "Largeur de ligne", + "visTypeXy.function.seriesParam.mode.help": "Mode graphique. Peut être empilé ou pourcentage", + "visTypeXy.function.seriesParam.show.help": "Afficher les paramètres", + "visTypeXy.function.seriesParam.showCircles.help": "Afficher les cercles", + "visTypeXy.function.seriesParam.type.help": "Type de graphique. Peut être linéaire, en aires ou histogramme", + "visTypeXy.function.seriesParam.valueAxis.help": "Nom de l'axe des valeurs", + "visTypeXy.function.thresholdLine.color.help": "Couleur de la ligne de seuil", + "visTypeXy.function.thresholdLine.help": "Génère un objet ligne de seuil", + "visTypeXy.function.thresholdLine.show.help": "Afficher la ligne de seuil", + "visTypeXy.function.thresholdLine.style.help": "Style de la ligne de seuil. Peut être pleine, en tirets ou en point-tiret", + "visTypeXy.function.thresholdLine.value.help": "Valeur seuil", + "visTypeXy.function.thresholdLine.width.help": "Largeur de la ligne de seuil", + "visTypeXy.function.timeMarker.class.help": "Nom de classe Css", + "visTypeXy.function.timeMarker.color.help": "Couleur du repère de temps", + "visTypeXy.function.timemarker.help": "Génère un objet repère de temps", + "visTypeXy.function.timeMarker.opacity.help": "Opacité du repère de temps", + "visTypeXy.function.timeMarker.time.help": "Heure exacte", + "visTypeXy.function.timeMarker.width.help": "Largeur du repère de temps", + "visTypeXy.function.valueAxis.axisParams.help": "Paramètres de l'axe des valeurs", + "visTypeXy.function.valueaxis.help": "Génère l'objet axe des valeurs", + "visTypeXy.function.valueAxis.name.help": "Nom de l'axe des valeurs", + "visTypeXy.functions.help": "Visualisation XY", + "visTypeXy.histogram.groupTitle": "Diviser la série", + "visTypeXy.histogram.histogramDescription": "Présente les données en barres verticales sur un axe.", + "visTypeXy.histogram.histogramTitle": "Barre verticale", + "visTypeXy.histogram.metricTitle": "Axe Y", + "visTypeXy.histogram.radiusTitle": "Taille du point", + "visTypeXy.histogram.segmentTitle": "Axe X", + "visTypeXy.histogram.splitTitle": "Diviser le graphique", + "visTypeXy.horizontalBar.groupTitle": "Diviser la série", + "visTypeXy.horizontalBar.horizontalBarDescription": "Présente les données en barres horizontales sur un axe.", + "visTypeXy.horizontalBar.horizontalBarTitle": "Barre horizontale", + "visTypeXy.horizontalBar.metricTitle": "Axe Y", + "visTypeXy.horizontalBar.radiusTitle": "Taille du point", + "visTypeXy.horizontalBar.segmentTitle": "Axe X", + "visTypeXy.horizontalBar.splitTitle": "Diviser le graphique", + "visTypeXy.interpolationModes.smoothedText": "Lissé", + "visTypeXy.interpolationModes.steppedText": "Par paliers", + "visTypeXy.interpolationModes.straightText": "Droit", + "visTypeXy.legend.filterForValueButtonAriaLabel": "Filtre pour la valeur", + "visTypeXy.legend.filterOptionsLegend": "{legendDataLabel}, options de filtre", + "visTypeXy.legend.filterOutValueButtonAriaLabel": "Filtrer la valeur", + "visTypeXy.legendPositions.bottomText": "Bas", + "visTypeXy.legendPositions.leftText": "Gauche", + "visTypeXy.legendPositions.rightText": "Droite", + "visTypeXy.legendPositions.topText": "Haut", + "visTypeXy.line.groupTitle": "Diviser la série", + "visTypeXy.line.lineDescription": "Affiche les données sous forme d'une série de points.", + "visTypeXy.line.lineTitle": "Ligne", + "visTypeXy.line.metricTitle": "Axe Y", + "visTypeXy.line.radiusTitle": "Taille du point", + "visTypeXy.line.segmentTitle": "Axe X", + "visTypeXy.line.splitTitle": "Diviser le graphique", + "visTypeXy.scaleTypes.linearText": "Linéaire", + "visTypeXy.scaleTypes.logText": "Logarithmique", + "visTypeXy.scaleTypes.squareRootText": "Racine carrée", + "visTypeXy.thresholdLine.style.dashedText": "Tirets", + "visTypeXy.thresholdLine.style.dotdashedText": "Point-tiret", + "visTypeXy.thresholdLine.style.fullText": "Pleine", + "visualizations.advancedSettings.visualizeEnableLabsText": "Permet aux utilisateurs de créer, d’afficher et de modifier des visualisations expérimentales. Si la fonctionnalité est désactivée,\n seules les visualisations considérées prêtes pour la production sont disponibles pour l'utilisateur.", + "visualizations.advancedSettings.visualizeEnableLabsTitle": "Activer les visualisations expérimentales", + "visualizations.disabledLabVisualizationLink": "Lire la documentation", + "visualizations.disabledLabVisualizationMessage": "Veuillez activer le mode lab dans les paramètres avancés pour consulter les visualisations lab.", + "visualizations.disabledLabVisualizationTitle": "{title} est une visualisation lab.", + "visualizations.displayName": "Visualisation", + "visualizations.embeddable.placeholderTitle": "Titre de l'espace réservé", + "visualizations.function.range.from.help": "Début de la plage", + "visualizations.function.range.help": "Génère un objet plage", + "visualizations.function.range.to.help": "Fin de la plage", + "visualizations.function.visDimension.accessor.help": "Colonne de votre ensemble de données à utiliser (index de colonne ou nom de colonne)", + "visualizations.function.visDimension.format.help": "Format", + "visualizations.function.visDimension.formatParams.help": "Paramètres de format", + "visualizations.function.visDimension.help": "Génère un objet dimension visConfig", + "visualizations.function.xyDimension.aggType.help": "Type d'agrégation", + "visualizations.function.xydimension.help": "Génère un objet dimension xy", + "visualizations.function.xyDimension.label.help": "Étiquette", + "visualizations.function.xyDimension.params.help": "Paramètres", + "visualizations.function.xyDimension.visDimension.help": "Configuration de l'objet dimension", + "visualizations.initializeWithoutIndexPatternErrorMessage": "Tentative d'initialisation des agrégations sans modèle d'indexation", + "visualizations.newVisWizard.aggBasedGroupDescription": "Utilisez notre bibliothèque Visualize classique pour créer des graphiques basés sur des agrégations.", + "visualizations.newVisWizard.aggBasedGroupTitle": "Basé sur une agrégation", + "visualizations.newVisWizard.chooseSourceTitle": "Choisir une source", + "visualizations.newVisWizard.experimentalTitle": "Expérimental", + "visualizations.newVisWizard.experimentalTooltip": "Cette visualisation est susceptible d'être modifiée ou supprimée dans une version ultérieure, et n'est pas soumise à l'accord de niveau de service d'assistance.", + "visualizations.newVisWizard.exploreOptionLinkText": "Explorer les options", + "visualizations.newVisWizard.filterVisTypeAriaLabel": "Filtrer un type de visualisation", + "visualizations.newVisWizard.goBackLink": "Sélectionner une visualisation différente", + "visualizations.newVisWizard.helpTextAriaLabel": "Commencez à créer votre visualisation en sélectionnant un type pour cette visualisation. Appuyez sur Échap pour fermer ce mode. Appuyez sur Tab pour aller plus loin.", + "visualizations.newVisWizard.learnMoreText": "Envie d'en savoir plus ?", + "visualizations.newVisWizard.newVisTypeTitle": "Nouveau {visTypeName}", + "visualizations.newVisWizard.readDocumentationLink": "Lire la documentation", + "visualizations.newVisWizard.resultsFound": "{resultCount, plural, one {type trouvé} other {types trouvés}}", + "visualizations.newVisWizard.searchSelection.notFoundLabel": "Aucun index ni aucune recherche enregistrée correspondant(e) trouvé(e).", + "visualizations.newVisWizard.searchSelection.savedObjectType.search": "Recherche enregistrée", + "visualizations.newVisWizard.title": "Nouvelle visualisation", + "visualizations.newVisWizard.toolsGroupTitle": "Outils", + "visualizations.noResultsFoundTitle": "Aucun résultat trouvé", + "visualizations.savedObjectName": "Visualisation", + "visualizations.savingVisualizationFailed.errorMsg": "L'enregistrement de la visualisation a échoué", + "visualizations.visualizationTypeInvalidMessage": "Type de visualisation non valide \"{visType}\"", + "xpack.actions.actionTypeRegistry.get.missingActionTypeErrorMessage": "Le type d'action \"{id}\" n'est pas enregistré.", + "xpack.actions.actionTypeRegistry.register.duplicateActionTypeErrorMessage": "Le type d'action \"{id}\" est déjà enregistré.", + "xpack.actions.alertHistoryEsIndexConnector.name": "Index Elasticsearch d'historique d'alertes", + "xpack.actions.appName": "Actions", + "xpack.actions.builtin.case.swimlaneTitle": "Swimlane", + "xpack.actions.builtin.cases.jiraTitle": "Jira", + "xpack.actions.builtin.cases.resilientTitle": "IBM Resilient", + "xpack.actions.builtin.configuration.apiAllowedHostsError": "erreur lors de la configuration de l'action du connecteur : {message}", + "xpack.actions.builtin.email.customViewInKibanaMessage": "Ce message a été envoyé par Kibana. [{kibanaFooterLinkText}]({link}).", + "xpack.actions.builtin.email.errorSendingErrorMessage": "erreur lors de l'envoi de l'e-mail", + "xpack.actions.builtin.email.kibanaFooterLinkText": "Accéder à Kibana", + "xpack.actions.builtin.email.sentByKibanaMessage": "Ce message a été envoyé par Kibana.", + "xpack.actions.builtin.emailTitle": "E-mail", + "xpack.actions.builtin.esIndex.errorIndexingErrorMessage": "erreur lors de l'indexation des documents", + "xpack.actions.builtin.esIndexTitle": "Index", + "xpack.actions.builtin.jira.configuration.apiAllowedHostsError": "erreur lors de la configuration de l'action du connecteur : {message}", + "xpack.actions.builtin.pagerduty.invalidTimestampErrorMessage": "erreur lors de l'analyse de l'horodatage \"{timestamp}\"", + "xpack.actions.builtin.pagerduty.missingDedupkeyErrorMessage": "DedupKey est requis lorsque eventAction est \"{eventAction}\"", + "xpack.actions.builtin.pagerduty.pagerdutyConfigurationError": "erreur lors de la configuration de l'action pagerduty : {message}", + "xpack.actions.builtin.pagerduty.postingErrorMessage": "erreur lors de la publication de l'événement pagerduty", + "xpack.actions.builtin.pagerduty.postingRetryErrorMessage": "erreur lors de la publication de l'événement pagerduty : statut http {status}, réessayer ultérieurement", + "xpack.actions.builtin.pagerduty.postingUnexpectedErrorMessage": "erreur lors de la publication de l'événement pagerduty : statut inattendu {status}", + "xpack.actions.builtin.pagerduty.timestampParsingFailedErrorMessage": "erreur lors de l'analyse de l'horodatage \"{timestamp}\" : {message}", + "xpack.actions.builtin.pagerdutyTitle": "PagerDuty", + "xpack.actions.builtin.serverLog.errorLoggingErrorMessage": "erreur lors du logging du message", + "xpack.actions.builtin.serverLogTitle": "Log de serveur", + "xpack.actions.builtin.serviceNowITSMTitle": "ServiceNow ITSM", + "xpack.actions.builtin.serviceNowSIRTitle": "ServiceNow SecOps", + "xpack.actions.builtin.serviceNowTitle": "ServiceNow", + "xpack.actions.builtin.slack.errorPostingErrorMessage": "erreur lors de la publication du message slack", + "xpack.actions.builtin.slack.errorPostingRetryDateErrorMessage": "erreur lors de la publication d'un message slack, réessayer à cette date/heure : {retryString}", + "xpack.actions.builtin.slack.errorPostingRetryLaterErrorMessage": "erreur lors de la publication d'un message slack, réessayer ultérieurement", + "xpack.actions.builtin.slack.slackConfigurationError": "erreur lors de la configuration de l'action slack : {message}", + "xpack.actions.builtin.slack.slackConfigurationErrorNoHostname": "erreur lors de la configuration de l'action slack : impossible d'analyser le nom de l'hôte depuis webhookUrl", + "xpack.actions.builtin.slack.unexpectedHttpResponseErrorMessage": "réponse http inattendue de Slack : {httpStatus} {httpStatusText}", + "xpack.actions.builtin.slack.unexpectedNullResponseErrorMessage": "réponse nulle inattendue de Slack", + "xpack.actions.builtin.slackTitle": "Slack", + "xpack.actions.builtin.swimlane.configuration.apiAllowedHostsError": "erreur lors de la configuration de l'action du connecteur : {message}", + "xpack.actions.builtin.swimlaneTitle": "Swimlane", + "xpack.actions.builtin.teams.errorPostingRetryDateErrorMessage": "erreur lors de la publication d'un message Microsoft Teams, réessayer à cette date/heure : {retryString}", + "xpack.actions.builtin.teams.errorPostingRetryLaterErrorMessage": "erreur lors de la publication d'un message Microsoft Teams, réessayer ultérieurement", + "xpack.actions.builtin.teams.invalidResponseErrorMessage": "erreur lors de la publication sur Microsoft Teams, réponse non valide", + "xpack.actions.builtin.teams.teamsConfigurationError": "erreur lors de la configuration de l'action teams : {message}", + "xpack.actions.builtin.teams.teamsConfigurationErrorNoHostname": "erreur lors de la configuration de l'action teams : impossible d'analyser le nom de l'hôte depuis webhookUrl", + "xpack.actions.builtin.teams.unreachableErrorMessage": "erreur lors de la publication sur Microsoft Teams, erreur inattendue", + "xpack.actions.builtin.teamsTitle": "Microsoft Teams", + "xpack.actions.builtin.webhook.invalidResponseErrorMessage": "erreur lors de l'appel de webhook, réponse non valide", + "xpack.actions.builtin.webhook.invalidResponseRetryDateErrorMessage": "erreur lors de l'appel de webhook, réessayer à cette date/heure : {retryString}", + "xpack.actions.builtin.webhook.invalidResponseRetryLaterErrorMessage": "erreur lors de l'appel de webhook, réessayer ultérieurement", + "xpack.actions.builtin.webhook.invalidUsernamePassword": "l'utilisateur et le mot de passe doivent être spécifiés", + "xpack.actions.builtin.webhook.requestFailedErrorMessage": "erreur lors de l'appel de webhook, requête échouée", + "xpack.actions.builtin.webhook.unreachableErrorMessage": "erreur lors de l'appel de webhook, erreur inattendue", + "xpack.actions.builtin.webhook.webhookConfigurationError": "erreur lors de la configuration de l'action webhook : {message}", + "xpack.actions.builtin.webhook.webhookConfigurationErrorNoHostname": "erreur lors de la configuration de l'action webhook : impossible d'analyser l'url : {err}", + "xpack.actions.builtin.webhookTitle": "Webhook", + "xpack.actions.disabledActionTypeError": "le type d'action \"{actionType}\" n'est pas activé dans la configuration Kibana xpack.actions.enabledActionTypes", + "xpack.actions.featureRegistry.actionsFeatureName": "Actions et connecteurs", + "xpack.actions.savedObjects.goToConnectorsButtonText": "Accéder aux connecteurs", + "xpack.actions.savedObjects.onImportText": "{connectorsWithSecretsLength} {connectorsWithSecretsLength, plural, one {Le connecteur contient} other {Les connecteurs contiennent}} des informations sensibles qui requièrent des mises à jour.", + "xpack.actions.serverSideErrors.expirerdLicenseErrorMessage": "Le type d'action {actionTypeId} est désactivé, car votre licence {licenseType} a expiré.", + "xpack.actions.serverSideErrors.invalidLicenseErrorMessage": "Le type d'action {actionTypeId} est désactivé, car votre licence {licenseType} ne le prend pas en charge. Veuillez mettre à niveau votre licence.", + "xpack.actions.serverSideErrors.predefinedActionDeleteDisabled": "L'action préconfigurée {id} n'est pas autorisée à effectuer des suppressions.", + "xpack.actions.serverSideErrors.predefinedActionUpdateDisabled": "L'action préconfigurée {id} n'est pas autorisée à effectuer des mises à jour.", + "xpack.actions.serverSideErrors.unavailableLicenseErrorMessage": "Le type d'action {actionTypeId} est désactivé, car les informations de licence ne sont pas disponibles actuellement.", + "xpack.actions.serverSideErrors.unavailableLicenseInformationErrorMessage": "Les actions sont indisponibles - les informations de licence ne sont pas disponibles actuellement.", + "xpack.actions.urlAllowedHostsConfigurationError": "Le {field} cible \"{value}\" n'est pas ajouté à la configuration Kibana xpack.actions.allowedHosts", + "xpack.alerting.alertNavigationRegistry.get.missingNavigationError": "La navigation pour le type d'alerte \"{alertType}\" dans \"{consumer}\" n'est pas enregistrée.", + "xpack.alerting.alertNavigationRegistry.register.duplicateDefaultError": "La navigation par défaut dans \"{consumer}\" est déjà enregistrée.", + "xpack.alerting.alertNavigationRegistry.register.duplicateNavigationError": "La navigation pour le type d'alerte \"{alertType}\" dans \"{consumer}\" est déjà enregistrée.", + "xpack.alerting.api.error.disabledApiKeys": "L'alerting se base sur les clés d'API qui semblent désactivées", + "xpack.alerting.appName": "Alerting", + "xpack.alerting.builtinActionGroups.recovered": "Récupéré", + "xpack.alerting.injectActionParams.email.kibanaFooterLinkText": "Afficher la règle dans Kibana", + "xpack.alerting.rulesClient.invalidDate": "Date non valide pour le {field} de paramètre : \"{dateValue}\"", + "xpack.alerting.rulesClient.validateActions.invalidGroups": "Groupes d'actions non valides : {groups}", + "xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "Connecteurs non valides : {groups}", + "xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "Le type de règle [id=\"{id}\"] ne peut pas être enregistré. Le groupe d'actions [{actionGroup}] ne peut pas être utilisé à la fois comme groupe de récupération et comme groupe d'actions actif.", + "xpack.alerting.ruleTypeRegistry.register.reservedActionGroupUsageError": "Le type de règle [id=\"{id}\"] ne peut pas être enregistré. Les groupes d'actions [{actionGroups}] sont réservés par le framework.", + "xpack.alerting.savedObjects.goToRulesButtonText": "Accéder aux règles", + "xpack.alerting.savedObjects.onImportText": "{rulesSavedObjectsLength} {rulesSavedObjectsLength, plural, one {La règle doit être activée} other {Les règles doivent être activées}} après l'importation.", + "xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "Les alertes sont indisponibles – les informations de licence ne sont pas disponibles actuellement.", + "xpack.apm.a.thresholdMet": "Seuil atteint", + "xpack.apm.addDataButtonLabel": "Ajouter des données", + "xpack.apm.agentConfig.allOptionLabel": "Tous", + "xpack.apm.agentConfig.apiRequestSize.description": "Taille totale compressée maximale du corps de la requête envoyé à l'API d'ingestion du serveur APM depuis un encodage fragmenté (diffusion HTTP).\nVeuillez noter qu'un léger dépassement est possible.\n\nLes unités d'octets autorisées sont \"b\", \"kb\" et \"mb\". \"1kb\" correspond à \"1024b\".", + "xpack.apm.agentConfig.apiRequestSize.label": "Taille de la requête API", + "xpack.apm.agentConfig.apiRequestTime.description": "Durée maximale de l'ouverture d'une requête HTTP sur le serveur APM.\n\nREMARQUE : cette valeur doit être inférieure à celle du paramètre \"read_timeout\" du serveur APM.", + "xpack.apm.agentConfig.apiRequestTime.label": "Heure de la requête API", + "xpack.apm.agentConfig.captureBody.description": "Pour les transactions qui sont des requêtes HTTP, l'agent peut éventuellement capturer le corps de la requête (par ex., variables POST).\nPour les transactions qui sont initiées par la réception d'un message depuis un agent de message, l'agent peut capturer le corps du message texte.", + "xpack.apm.agentConfig.captureBody.label": "Capturer le corps", + "xpack.apm.agentConfig.captureHeaders.description": "Si cette option est définie sur \"true\", l'agent capturera les en-têtes de la requête HTTP et de la réponse (y compris les cookies), ainsi que les en-têtes/les propriétés du message lors de l'utilisation de frameworks de messagerie (tels que Kafka).\n\nREMARQUE : Si \"false\" est défini, cela permet de réduire la bande passante du réseau, l'espace disque et les allocations d'objets.", + "xpack.apm.agentConfig.captureHeaders.label": "Capturer les en-têtes", + "xpack.apm.agentConfig.chooseService.editButton": "Modifier", + "xpack.apm.agentConfig.chooseService.service.environment.label": "Environnement", + "xpack.apm.agentConfig.chooseService.service.name.label": "Nom de service", + "xpack.apm.agentConfig.circuitBreakerEnabled.description": "Nombre booléen spécifiant si le disjoncteur doit être activé ou non. Lorsqu'il est activé, l'agent interroge régulièrement les monitorings de tension pour détecter l'état de tension du système/du processus/de la JVM. Si L'UN des monitorings détecte un signe de tension, l'agent s'interrompt, comme si l'option de configuration \"recording\" était définie sur \"false\", réduisant ainsi la consommation des ressources au minimum. Pendant l'interruption, l'agent continue à interroger les mêmes monitorings pour vérifier si l'état de tension a été allégé. Si TOUS les monitorings indiquent que le système, le processus et la JVM ne sont plus en état de tension, l'agent reprend son activité et redevient entièrement fonctionnel.", + "xpack.apm.agentConfig.circuitBreakerEnabled.label": "Disjoncteur activé", + "xpack.apm.agentConfig.configTable.appliedTooltipMessage": "Appliqué par au moins un agent", + "xpack.apm.agentConfig.configTable.configTable.failurePromptText": "La liste des configurations d'agent n'a pas pu être récupérée. Votre utilisateur ne dispose peut-être pas d'autorisations suffisantes.", + "xpack.apm.agentConfig.configTable.createConfigButtonLabel": "Créer une configuration", + "xpack.apm.agentConfig.configTable.emptyPromptTitle": "Aucune configuration trouvée.", + "xpack.apm.agentConfig.configTable.environmentColumnLabel": "Environnement de service", + "xpack.apm.agentConfig.configTable.lastUpdatedColumnLabel": "Dernière mise à jour", + "xpack.apm.agentConfig.configTable.notAppliedTooltipMessage": "Appliqué par aucun agent pour le moment", + "xpack.apm.agentConfig.configTable.serviceNameColumnLabel": "Nom de service", + "xpack.apm.agentConfig.configurationsPanelTitle": "Configurations", + "xpack.apm.agentConfig.configurationsPanelTitle.noPermissionTooltipLabel": "Votre rôle d'utilisateur ne dispose pas des autorisations nécessaires pour créer des configurations d'agent", + "xpack.apm.agentConfig.createConfigButtonLabel": "Créer une configuration", + "xpack.apm.agentConfig.createConfigTitle": "Créer une configuration", + "xpack.apm.agentConfig.deleteModal.cancel": "Annuler", + "xpack.apm.agentConfig.deleteModal.confirm": "Supprimer", + "xpack.apm.agentConfig.deleteModal.text": "Vous êtes sur le point de supprimer la configuration du service \"{serviceName}\" et de l'environnement \"{environment}\".", + "xpack.apm.agentConfig.deleteModal.title": "Supprimer la configuration", + "xpack.apm.agentConfig.deleteSection.deleteConfigFailedText": "Une erreur est survenue lors de la suppression d'une configuration de \"{serviceName}\". Erreur : \"{errorMessage}\"", + "xpack.apm.agentConfig.deleteSection.deleteConfigFailedTitle": "La configuration n'a pas pu être supprimée", + "xpack.apm.agentConfig.deleteSection.deleteConfigSucceededText": "Vous avez supprimé une configuration de \"{serviceName}\" avec succès. La propagation jusqu'aux agents pourra prendre un certain temps.", + "xpack.apm.agentConfig.deleteSection.deleteConfigSucceededTitle": "La configuration a été supprimée", + "xpack.apm.agentConfig.editConfigTitle": "Modifier la configuration", + "xpack.apm.agentConfig.enableLogCorrelation.description": "Nombre booléen spécifiant si l'agent doit être intégré au MDC de SLF4J pour activer la corrélation de logs de suivi. Si cette option est configurée sur \"true\", l'agent définira \"trace.id\" et \"transaction.id\" pour les intervalles et transactions actifs sur le MDC. Depuis la version 1.16.0 de l'agent Java, l'agent ajoute également le \"error.id\" de l'erreur capturée au MDC juste avant le logging du message d'erreur. REMARQUE : bien qu'il soit autorisé d'activer ce paramètre au moment de l'exécution, vous ne pouvez pas le désactiver sans redémarrage.", + "xpack.apm.agentConfig.enableLogCorrelation.label": "Activer la corrélation de logs", + "xpack.apm.agentConfig.logLevel.description": "Définit le niveau de logging pour l'agent", + "xpack.apm.agentConfig.logLevel.label": "Niveau de log", + "xpack.apm.agentConfig.newConfig.description": "Affinez votre configuration d'agent depuis l'application APM. Les modifications sont automatiquement propagées à vos agents APM, ce qui vous évite d'effectuer un redéploiement.", + "xpack.apm.agentConfig.profilingInferredSpansEnabled.description": "Définissez cette option sur \"true\" pour que l'agent crée des intervalles pour des exécutions de méthodes basées sur async-profiler, un profiler d'échantillonnage (ou profiler statistique). En raison de la nature du fonctionnement des profilers d'échantillonnage, la durée des intervalles générés n'est pas exacte, il ne s'agit que d'estimations. \"profiling_inferred_spans_sampling_interval\" vous permet d'ajuster avec exactitude le compromis entre précision et surcharge. Les intervalles générés sont créés à la fin d'une session de profilage. Cela signifie qu'il existe un délai entre les intervalles réguliers et les intervalles générés visibles dans l'interface utilisateur. REMARQUE : cette fonctionnalité n'est pas disponible sous Windows.", + "xpack.apm.agentConfig.profilingInferredSpansEnabled.label": "Intervalles générés par le profilage activés", + "xpack.apm.agentConfig.profilingInferredSpansExcludedClasses.description": "Exclut les classes pour lesquelles aucun intervalle généré par le profiler ne doit être créé. Cette option prend en charge le caractère générique \"*\" qui correspond à zéro caractère ou plus. La correspondance n'est pas sensible à la casse par défaut. L'ajout de \"(?-i)\" au début d'un élément rend la correspondance sensible à la casse.", + "xpack.apm.agentConfig.profilingInferredSpansExcludedClasses.label": "Classes exclues des intervalles générés par le profilage", + "xpack.apm.agentConfig.profilingInferredSpansIncludedClasses.description": "Si cette option est définie, l'agent ne créera des intervalles générés que pour les méthodes correspondant à cette liste. La définition d'une valeur peut diminuer légèrement la surcharge et réduire l'encombrement en ne créant des intervalles que pour les classes qui vous intéressent. Cette option prend en charge le caractère générique \"*\" qui correspond à zéro caractère ou plus. Par exemple : \"org.example.myapp.*\". La correspondance n'est pas sensible à la casse par défaut. L'ajout de \"(?-i)\" au début d'un élément rend la correspondance sensible à la casse.", + "xpack.apm.agentConfig.profilingInferredSpansIncludedClasses.label": "Classes incluses des intervalles générés par le profilage", + "xpack.apm.agentConfig.profilingInferredSpansMinDuration.description": "Durée minimale d'un intervalle généré. Veuillez noter que la durée minimale est également définie de façon implicite par l'intervalle d'échantillonnage. Toutefois, l'augmentation de l'intervalle d'échantillonnage diminue également la précision de la durée des intervalles générés.", + "xpack.apm.agentConfig.profilingInferredSpansMinDuration.label": "Durée minimale des intervalles générés par le profilage", + "xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.description": "Fréquence à laquelle les traces de pile sont rassemblées au cours d'une session de profilage. Plus vous définissez un chiffre bas, plus les durées seront précises. Cela induit une surcharge plus élevée et un plus grand nombre d'intervalles, pour des opérations potentiellement non pertinentes. La durée minimale d'un intervalle généré par le profilage est identique à la valeur de ce paramètre.", + "xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.label": "Intervalle d'échantillonnage des intervalles générés par le profilage", + "xpack.apm.agentConfig.range.errorText": "{rangeType, select,\n between {doit être compris entre {min} et {max}}\n gt {doit être supérieur à {min}}\n lt {doit être inférieur à {max}}\n other {doit être un entier}\n }", + "xpack.apm.agentConfig.recording.description": "Lorsque l'enregistrement est activé, l'agent instrumente les requêtes HTTP entrantes, effectue le suivi des erreurs, et collecte et envoie les indicateurs. Lorsque l'enregistrement n'est pas activé, l'agent agit comme un noop, sans collecter de données ni communiquer avec le serveur AMP, sauf pour rechercher la configuration mise à jour. Puisqu'il s'agit d'un commutateur réversible, les threads d'agents ne sont pas détruits lorsque le mode sans enregistrement est défini. Ils restent principalement inactifs, de sorte que la surcharge est négligeable. Vous pouvez utiliser ce paramètre pour contrôler dynamiquement si Elastic APM doit être activé ou désactivé.", + "xpack.apm.agentConfig.recording.label": "Enregistrement", + "xpack.apm.agentConfig.sanitizeFiledNames.description": "Il est parfois nécessaire d'effectuer un nettoyage, c'est-à-dire de supprimer les données sensibles envoyées à Elastic APM. Cette configuration accepte une liste de modèles de caractères génériques de champs de noms qui doivent être nettoyés. Ils s'appliquent aux en-têtes HTTP (y compris les cookies) et aux données \"application/x-www-form-urlencoded\" (champs de formulaire POST). La chaîne de la requête et le corps de la requête capturé (comme des données \"application/json\") ne seront pas nettoyés.", + "xpack.apm.agentConfig.sanitizeFiledNames.label": "Nettoyer les noms des champs", + "xpack.apm.agentConfig.saveConfig.failed.text": "Une erreur est survenue pendant l'enregistrement de la configuration de \"{serviceName}\". Erreur : \"{errorMessage}\"", + "xpack.apm.agentConfig.saveConfig.failed.title": "La configuration n'a pas pu être enregistrée", + "xpack.apm.agentConfig.saveConfig.succeeded.text": "La configuration de \"{serviceName}\" a été enregistrée. La propagation jusqu'aux agents pourra prendre un certain temps.", + "xpack.apm.agentConfig.saveConfig.succeeded.title": "Configuration enregistrée", + "xpack.apm.agentConfig.saveConfigurationButtonLabel": "Étape suivante", + "xpack.apm.agentConfig.serverTimeout.description": "Si une requête au serveur APM prend plus de temps que le délai d'expiration configuré,\nla requête est annulée et l'événement (exception ou transaction) est abandonné.\nDéfinissez sur 0 pour désactiver les délais d'expiration.\n\nAVERTISSEMENT : si les délais d'expiration sont désactivés ou définis sur une valeur élevée, il est possible que votre application rencontre des problèmes de mémoire en cas d'expiration du serveur APM.", + "xpack.apm.agentConfig.serverTimeout.label": "Délai d'expiration du serveur", + "xpack.apm.agentConfig.servicePage.alreadyConfiguredOption": "déjà configuré", + "xpack.apm.agentConfig.servicePage.cancelButton": "Annuler", + "xpack.apm.agentConfig.servicePage.environment.description": "Seul un environnement unique par configuration est pris en charge.", + "xpack.apm.agentConfig.servicePage.environment.fieldLabel": "Environnement de service", + "xpack.apm.agentConfig.servicePage.environment.title": "Environnement", + "xpack.apm.agentConfig.servicePage.service.description": "Choisissez le service que vous souhaitez configurer.", + "xpack.apm.agentConfig.servicePage.service.fieldLabel": "Nom de service", + "xpack.apm.agentConfig.servicePage.service.title": "Service", + "xpack.apm.agentConfig.settingsPage.discardChangesButton": "Abandonner les modifications", + "xpack.apm.agentConfig.settingsPage.notFound.message": "La configuration demandée n'existe pas", + "xpack.apm.agentConfig.settingsPage.notFound.title": "Désolé, une erreur est survenue", + "xpack.apm.agentConfig.settingsPage.saveButton": "Enregistrer la configuration", + "xpack.apm.agentConfig.spanFramesMinDuration.description": "Dans ses paramètres par défaut, l'agent APM collectera une trace de la pile avec chaque intervalle enregistré.\nBien qu'il soit très pratique de trouver l'endroit exact dans votre code qui provoque l'intervalle, la collecte de cette trace de la pile provoque une certaine surcharge. \nLorsque cette option est définie sur une valeur négative, telle que \"-1ms\", les traces de pile sont collectées pour tous les intervalles. En choisissant une valeur positive, par ex. \"5ms\", la collecte des traces de pile se limitera aux intervalles dont la durée est égale ou supérieure à la valeur donnée, par ex. 5 millisecondes.\n\nPour désactiver complètement la collecte des traces de pile des intervalles, réglez la valeur sur \"0ms\".", + "xpack.apm.agentConfig.spanFramesMinDuration.label": "Durée minimale des cadres des intervalles", + "xpack.apm.agentConfig.stackTraceLimit.description": "En définissant cette option sur 0, la collecte des traces de pile sera désactivée. Toute valeur entière positive sera utilisée comme nombre maximal de cadres à collecter. La valeur -1 signifie que tous les cadres seront collectés.", + "xpack.apm.agentConfig.stackTraceLimit.label": "Limite de trace de pile", + "xpack.apm.agentConfig.stressMonitorCpuDurationThreshold.description": "Durée minimale requise pour déterminer si le système est actuellement sous tension ou si la tension précédemment détectée a été allégée. Toutes les mesures réalisées pendant ce laps de temps doivent être cohérentes par rapport au seuil concerné pour pouvoir détecter un changement d'état de tension. La valeur doit être d'au moins \"1m\".", + "xpack.apm.agentConfig.stressMonitorCpuDurationThreshold.label": "Seuil de durée de tension CPU du monitoring", + "xpack.apm.agentConfig.stressMonitorGcReliefThreshold.description": "Seuil utilisé par le monitoring RM pour identifier le moment auquel le segment de mémoire n'est pas sous tension. Si le \"stress_monitor_gc_stress_threshold\" a été franchi, l'agent le considérera comme un état de tension du segment de mémoire. Pour déterminer l'état de tension comme terminé, le pourcentage de mémoire occupée dans TOUS les pools de mémoire doit être inférieur à ce seuil. Le monitoring RM ne se base que sur la consommation de mémoire mesurée après une RM récente.", + "xpack.apm.agentConfig.stressMonitorGcReliefThreshold.label": "Seuil d'allègement de la tension du monitoring RM", + "xpack.apm.agentConfig.stressMonitorGcStressThreshold.description": "Seuil utilisé par le monitoring RM pour identifier la tension du segment de mémoire. Ce même seuil sera utilisé pour tous les pools de mémoire, de sorte que si L'UN d'entre eux a un pourcentage d'utilisation qui dépasse ce seuil, l'agent l'interprétera comme une tension de segment de mémoire. Le monitoring RM ne se base que sur la consommation de mémoire mesurée après une RM récente.", + "xpack.apm.agentConfig.stressMonitorGcStressThreshold.label": "Seuil de tension du monitoring RM", + "xpack.apm.agentConfig.stressMonitorSystemCpuReliefThreshold.description": "Seuil utilisé par le monitoring du CPU système pour déterminer que le système n'est pas sous tension au niveau du processeur. Si le monitor détecte une tension de CPU, le CPU système mesuré doit être inférieur à ce seuil pour une durée d'au moins \"stress_monitor_cpu_duration_threshold\", pour que le monitoring établisse l'allègement de la tension de CPU.", + "xpack.apm.agentConfig.stressMonitorSystemCpuReliefThreshold.label": "Seuil d'allègement de la tension du monitoring du CPU système", + "xpack.apm.agentConfig.stressMonitorSystemCpuStressThreshold.description": "Seuil utilisé par le monitoring du CPU du système pour détecter la tension du processeur du système. Si le CPU système dépasse ce seuil pour une durée d'au moins \"stress_monitor_cpu_duration_threshold\", le monitoring considère qu'il est en état de tension.", + "xpack.apm.agentConfig.stressMonitorSystemCpuStressThreshold.label": "Seuil de tension du monitoring du CPU système", + "xpack.apm.agentConfig.transactionIgnoreUrl.description": "Utilisé pour limiter l'instrumentation des requêtes vers certaines URL. Cette configuration accepte une liste séparée par des virgules de modèles de caractères génériques de chemins d'URL qui doivent être ignorés. Lorsqu'une requête HTTP entrante sera détectée, son chemin de requête sera confronté à chaque élément figurant dans cette liste. Par exemple, l'ajout de \"/home/index\" à cette liste permettrait de faire correspondre et de supprimer l'instrumentation de \"http://localhost/home/index\" ainsi que de \"http://whatever.com/home/index?value1=123\"", + "xpack.apm.agentConfig.transactionIgnoreUrl.label": "Ignorer les transactions basées sur les URL", + "xpack.apm.agentConfig.transactionMaxSpans.description": "Limite la quantité d'intervalles enregistrés par transaction.", + "xpack.apm.agentConfig.transactionMaxSpans.label": "Nb maxi d'intervalles de transaction", + "xpack.apm.agentConfig.transactionSampleRate.description": "Par défaut, l'agent échantillonnera chaque transaction (par ex. requête à votre service). Pour réduire la surcharge et les exigences de stockage, vous pouvez définir le taux d'échantillonnage sur une valeur comprise entre 0,0 et 1,0. La durée globale et le résultat des transactions non échantillonnées seront toujours enregistrés, mais pas les informations de contexte, les étiquettes ni les intervalles.", + "xpack.apm.agentConfig.transactionSampleRate.label": "Taux d'échantillonnage des transactions", + "xpack.apm.agentConfig.unsavedSetting.tooltip": "Non enregistré", + "xpack.apm.agentMetrics.java.gcRate": "Taux RM", + "xpack.apm.agentMetrics.java.gcRateChartTitle": "Récupération de mémoire par minute", + "xpack.apm.agentMetrics.java.gcTime": "Durée RM", + "xpack.apm.agentMetrics.java.gcTimeChartTitle": "Durée de récupération de mémoire par minute", + "xpack.apm.agentMetrics.java.heapMemoryChartTitle": "Segment de mémoire", + "xpack.apm.agentMetrics.java.heapMemorySeriesCommitted": "Moy. allouée", + "xpack.apm.agentMetrics.java.heapMemorySeriesMax": "Limite moy.", + "xpack.apm.agentMetrics.java.heapMemorySeriesUsed": "Moy. utilisée", + "xpack.apm.agentMetrics.java.nonHeapMemoryChartTitle": "Segment de mémoire sans tas", + "xpack.apm.agentMetrics.java.nonHeapMemorySeriesCommitted": "Moy. allouée", + "xpack.apm.agentMetrics.java.nonHeapMemorySeriesUsed": "Moy. utilisée", + "xpack.apm.agentMetrics.java.threadCount": "Nombre moy.", + "xpack.apm.agentMetrics.java.threadCountChartTitle": "Nombre de threads", + "xpack.apm.agentMetrics.java.threadCountMax": "Nombre max", + "xpack.apm.aggregatedTransactions.fallback.badge": "Basé sur les transactions échantillonnées", + "xpack.apm.aggregatedTransactions.fallback.tooltip": "Cette page utilise les données d'événements de transactions lorsqu'aucun événement d'indicateur n'a été trouvé dans la plage temporelle actuelle, ou lorsqu'un filtre a été appliqué en fonction des champs indisponibles dans les documents des événements d'indicateurs.", + "xpack.apm.alertAnnotationButtonAriaLabel": "Afficher les détails de l'alerte", + "xpack.apm.alertAnnotationCriticalTitle": "Alerte critique", + "xpack.apm.alertAnnotationNoSeverityTitle": "Alerte", + "xpack.apm.alertAnnotationWarningTitle": "Alerte d'avertissement", + "xpack.apm.alerting.fields.environment": "Environnement", + "xpack.apm.alerting.fields.service": "Service", + "xpack.apm.alerting.fields.type": "Type", + "xpack.apm.alerts.action_variables.environment": "Type de transaction pour lequel l'alerte est créée", + "xpack.apm.alerts.action_variables.intervalSize": "La longueur et l'unité de la période à laquelle les conditions de l'alerte ont été remplies", + "xpack.apm.alerts.action_variables.serviceName": "Service pour lequel l'alerte est créée", + "xpack.apm.alerts.action_variables.threshold": "Toute valeur de déclenchement dépassant cette valeur lancera l'alerte", + "xpack.apm.alerts.action_variables.transactionType": "Type de transaction pour lequel l'alerte est créée", + "xpack.apm.alerts.action_variables.triggerValue": "Valeur ayant dépassé le seuil et déclenché l'alerte", + "xpack.apm.alerts.anomalySeverity.criticalLabel": "critique", + "xpack.apm.alerts.anomalySeverity.majorLabel": "majeur", + "xpack.apm.alerts.anomalySeverity.minor": "mineur", + "xpack.apm.alerts.anomalySeverity.scoreDetailsDescription": "score {value} {value, select, critical {} other {et plus}}", + "xpack.apm.alerts.anomalySeverity.warningLabel": "avertissement", + "xpack.apm.alertTypes.errorCount.defaultActionMessage": "L'alerte \\{\\{alertName\\}\\} se déclenche en raison des conditions suivantes :\n\n- Nom de service : \\{\\{context.serviceName\\}\\}\n- Environnement : \\{\\{context.environment\\}\\}\n- Seuil : \\{\\{context.threshold\\}\\} erreurs\n- Valeur de déclenchement : \\{\\{context.triggerValue\\}\\} erreurs sur la dernière période de \\{\\{context.interval\\}\\}", + "xpack.apm.alertTypes.errorCount.description": "Alerte lorsque le nombre d'erreurs d'un service dépasse un seuil défini.", + "xpack.apm.alertTypes.transactionDuration.defaultActionMessage": "L'alerte \\{\\{alertName\\}\\} se déclenche en raison des conditions suivantes :\n\n- Nom de service : \\{\\{context.serviceName\\}\\}\n- Type : \\{\\{context.transactionType\\}\\}\n- Environnement : \\{\\{context.environment\\}\\}\n- Seuil de latence : \\{\\{context.threshold\\}\\} ms\n- Latence observée : \\{\\{context.triggerValue\\}\\} sur la dernière période de \\{\\{context.interval\\}\\}", + "xpack.apm.alertTypes.transactionDuration.description": "Alerte lorsque la latence d'un type de transaction spécifique dans un service dépasse le seuil défini.", + "xpack.apm.alertTypes.transactionDurationAnomaly.defaultActionMessage": "L'alerte \\{\\{alertName\\}\\} se déclenche en raison des conditions suivantes :\n\n- Nom de service : \\{\\{context.serviceName\\}\\}\n- Type : \\{\\{context.transactionType\\}\\}\n- Environnement : \\{\\{context.environment\\}\\}\n- Seuil de sévérité : \\{\\{context.threshold\\}\\}\n- Valeur de sévérité : \\{\\{context.triggerValue\\}\\}\n", + "xpack.apm.alertTypes.transactionDurationAnomaly.description": "Alerte lorsque la latence d'un service est anormale.", + "xpack.apm.alertTypes.transactionErrorRate.defaultActionMessage": "L'alerte \\{\\{alertName\\}\\} se déclenche en raison des conditions suivantes :\n\n- Nom de service : \\{\\{context.serviceName\\}\\}\n- Type : \\{\\{context.transactionType\\}\\}\n- Environnement : \\{\\{context.environment\\}\\}\n- Seuil : \\{\\{context.threshold\\}\\} %\n- Valeur de déclenchement : \\{\\{context.triggerValue\\}\\} % des erreurs sur la dernière période de \\{\\{context.interval\\}\\}", + "xpack.apm.alertTypes.transactionErrorRate.description": "Alerte lorsque le taux d'erreurs de transaction d'un service dépasse un seuil défini.", + "xpack.apm.analyzeDataButton.label": "Analyser les données", + "xpack.apm.analyzeDataButton.tooltip": "EXPÉRIMENTAL - La fonctionnalité Analyser les données vous permet de sélectionner et de filtrer les données de résultat dans toute dimension et de rechercher la cause ou l'impact des problèmes de performances", + "xpack.apm.anomaly_detection.error.invalid_license": "Pour utiliser la détection des anomalies, vous devez disposer d'une licence Elastic Platinum. Cette licence vous permet de monitorer vos services à l'aide du Machine Learning.", + "xpack.apm.anomaly_detection.error.missing_read_privileges": "Vous devez disposer des privilèges \"read\" (lecture) pour le Machine Learning et l'APM pour consulter les tâches de détection des anomalies", + "xpack.apm.anomaly_detection.error.missing_write_privileges": "Vous devez disposer des privilèges \"write\" (écriture) pour le Machine Learning et l'APM pour créer des tâches de détection des anomalies", + "xpack.apm.anomaly_detection.error.not_available": "Le Machine Learning est indisponible", + "xpack.apm.anomaly_detection.error.not_available_in_space": "Le Machine Learning est indisponible dans l'espace sélectionné", + "xpack.apm.anomalyDetection.createJobs.failed.text": "Une erreur est survenue lors de la création d'une ou de plusieurs tâches de détection des anomalies pour les environnements de service APM [{environments}]. Erreur : \"{errorMessage}\"", + "xpack.apm.anomalyDetection.createJobs.failed.title": "Les tâches de détection des anomalies n'ont pas pu être créées", + "xpack.apm.anomalyDetection.createJobs.succeeded.text": "Tâches de détection des anomalies créées avec succès pour les environnements de service APM [{environments}]. Le démarrage de l'analyse du trafic à la recherche d'anomalies par le Machine Learning va prendre un certain temps.", + "xpack.apm.anomalyDetection.createJobs.succeeded.title": "Tâches de détection des anomalies créées", + "xpack.apm.anomalyDetectionSetup.linkLabel": "Détection des anomalies", + "xpack.apm.anomalyDetectionSetup.notEnabledForEnvironmentText": "La détection des anomalies n'est pas encore activée pour l'environnement \"{currentEnvironment}\". Cliquez pour continuer la configuration.", + "xpack.apm.anomalyDetectionSetup.notEnabledText": "La détection des anomalies n'est pas encore activée. Cliquez pour continuer la configuration.", + "xpack.apm.api.fleet.cloud_apm_package_policy.requiredRoleOnCloud": "Opération autorisée uniquement pour les utilisateurs Elastic Cloud disposant du rôle de superutilisateur.", + "xpack.apm.api.fleet.fleetSecurityRequired": "Les plug-ins Fleet et Security sont requis", + "xpack.apm.apmDescription": "Collecte automatiquement les indicateurs et les erreurs de performances détaillés depuis vos applications.", + "xpack.apm.apmSchema.index": "Schéma du serveur APM - Index", + "xpack.apm.apmSettings.index": "Paramètres APM - Index", + "xpack.apm.backendDetail.dependenciesTableColumnBackend": "Service", + "xpack.apm.backendDetail.dependenciesTableTitle": "Services en amont", + "xpack.apm.backendDetailFailedTransactionRateChartTitle": "Taux de transactions ayant échoué", + "xpack.apm.backendDetailLatencyChartTitle": "Latence", + "xpack.apm.backendDetailThroughputChartTitle": "Rendement", + "xpack.apm.backendErrorRateChart.chartTitle": "Taux de transactions ayant échoué", + "xpack.apm.backendErrorRateChart.previousPeriodLabel": "Période précédente", + "xpack.apm.backendLatencyChart.chartTitle": "Latence", + "xpack.apm.backendLatencyChart.previousPeriodLabel": "Période précédente", + "xpack.apm.backendThroughputChart.chartTitle": "Rendement", + "xpack.apm.backendThroughputChart.previousPeriodLabel": "Période précédente", + "xpack.apm.chart.annotation.version": "Version", + "xpack.apm.chart.cpuSeries.processAverageLabel": "Moyenne de processus", + "xpack.apm.chart.cpuSeries.processMaxLabel": "Max de processus", + "xpack.apm.chart.cpuSeries.systemAverageLabel": "Moyenne du système", + "xpack.apm.chart.cpuSeries.systemMaxLabel": "Max du système", + "xpack.apm.chart.error": "Une erreur est survenue lors de la tentative de récupération des données. Réessayez plus tard", + "xpack.apm.chart.memorySeries.systemAverageLabel": "Moyenne", + "xpack.apm.chart.memorySeries.systemMaxLabel": "Max", + "xpack.apm.compositeSpanCallsLabel": ", {count} appels, sur une moyenne de {duration}", + "xpack.apm.compositeSpanDurationLabel": "Durée moyenne", + "xpack.apm.correlations.correlationsTable.excludeDescription": "Filtrer la valeur", + "xpack.apm.correlations.correlationsTable.excludeLabel": "Exclure", + "xpack.apm.correlations.correlationsTable.filterDescription": "Filtrer par valeur", + "xpack.apm.correlations.correlationsTable.filterLabel": "Filtre", + "xpack.apm.correlations.correlationsTable.loadingText": "Chargement", + "xpack.apm.correlations.correlationsTable.noDataText": "Aucune donnée", + "xpack.apm.correlations.failedTransactions.correlationsTable.fieldNameLabel": "Nom du champ", + "xpack.apm.correlations.failedTransactions.correlationsTable.fieldValueLabel": "Valeur du champ", + "xpack.apm.correlations.failedTransactions.correlationsTable.impactLabel": "Impact", + "xpack.apm.correlations.failedTransactions.correlationsTable.pValueLabel": "Score", + "xpack.apm.correlations.failedTransactions.errorTitle": "Une erreur est survenue lors de l'exécution de corrélations sur les transactions ayant échoué", + "xpack.apm.correlations.failedTransactions.highImpactText": "Élevé", + "xpack.apm.correlations.failedTransactions.lowImpactText": "Bas", + "xpack.apm.correlations.failedTransactions.mediumImpactText": "Moyen", + "xpack.apm.correlations.failedTransactions.panelTitle": "Transactions ayant échoué", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.actionsLabel": "Filtre", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.correlationColumnDescription": "Score de corrélation [0-1] d'un attribut ; plus le score est élevé, plus un attribut augmente la latence.", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.correlationLabel": "Corrélation", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.excludeDescription": "Filtrer la valeur", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.excludeLabel": "Exclure", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.fieldNameLabel": "Nom du champ", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.fieldValueLabel": "Valeur du champ", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.filterDescription": "Filtrer par valeur", + "xpack.apm.correlations.latencyCorrelations.correlationsTable.filterLabel": "Filtre", + "xpack.apm.correlations.latencyCorrelations.errorTitle": "Une erreur est survenue lors de la récupération des corrélations", + "xpack.apm.correlations.latencyCorrelations.panelTitle": "Distribution de la latence", + "xpack.apm.correlations.latencyCorrelations.tableTitle": "Corrélations", + "xpack.apm.correlations.latencyPopoverBasicExplanation": "Les corrélations vous aident à découvrir quels attributs contribuent à l'augmentation des temps de réponse des transactions ou de la latence.", + "xpack.apm.correlations.latencyPopoverChartExplanation": "Le graphique de distribution de la latence permet de visualiser la latence globale des transactions dans le service. Lorsque vous passez votre souris sur des attributs du tableau, leur distribution de latence est ajoutée au graphique.", + "xpack.apm.correlations.latencyPopoverFilterExplanation": "Vous pouvez également ajouter ou retirer des filtres pour modifier les requêtes dans l'application APM.", + "xpack.apm.correlations.latencyPopoverPerformanceExplanation": "Cette analyse réalise des recherches statistiques sur un grand nombre d'attributs. Pour les plages temporelles étendues et les services ayant un rendement de transactions élevé, cela peut prendre un certain temps. Réduisez la plage temporelle pour améliorer les performances.", + "xpack.apm.correlations.latencyPopoverTableExplanation": "Le tableau est trié par coefficient de corrélation, de 0 à 1. Les attributs ayant des valeurs de corrélation plus élevées sont plus susceptibles de contribuer à des transactions à haute latence.", + "xpack.apm.correlations.latencyPopoverTitle": "Corrélations de latence", + "xpack.apm.customLink.buttom.create": "Créer un lien personnalisé", + "xpack.apm.customLink.buttom.create.title": "Créer", + "xpack.apm.customLink.buttom.manage": "Gérer des liens personnalisés", + "xpack.apm.customLink.empty": "Aucun lien personnalisé trouvé. Configurez vos propres liens personnalisés, par ex. un lien vers un tableau de bord spécifique ou un lien externe.", + "xpack.apm.dependenciesTable.columnErrorRate": "Taux de transactions ayant échoué", + "xpack.apm.dependenciesTable.columnImpact": "Impact", + "xpack.apm.dependenciesTable.columnLatency": "Latence (moy.)", + "xpack.apm.dependenciesTable.columnThroughput": "Rendement", + "xpack.apm.dependenciesTable.serviceMapLinkText": "Afficher la carte des services", + "xpack.apm.emptyMessage.noDataFoundDescription": "Essayez avec une autre plage temporelle ou réinitialisez le filtre de recherche.", + "xpack.apm.emptyMessage.noDataFoundLabel": "Aucune donnée trouvée.", + "xpack.apm.error.prompt.body": "Veuillez consulter la console de développeur de votre navigateur pour plus de détails.", + "xpack.apm.error.prompt.title": "Désolé, une erreur s'est produite :(", + "xpack.apm.errorCountAlert.name": "Seuil de nombre d'erreurs", + "xpack.apm.errorCountAlertTrigger.errors": " erreurs", + "xpack.apm.errorGroupDetails.culpritLabel": "Coupable", + "xpack.apm.errorGroupDetails.errorGroupTitle": "Groupe d'erreurs {errorGroupId}", + "xpack.apm.errorGroupDetails.errorOccurrenceTitle": "Occurrence d'erreur", + "xpack.apm.errorGroupDetails.exceptionMessageLabel": "Message d'exception", + "xpack.apm.errorGroupDetails.logMessageLabel": "Message log", + "xpack.apm.errorGroupDetails.occurrencesChartLabel": "Occurrences", + "xpack.apm.errorGroupDetails.relatedTransactionSample": "Échantillon de transaction associée", + "xpack.apm.errorGroupDetails.unhandledLabel": "Non géré", + "xpack.apm.errorGroupDetails.viewOccurrencesInDiscoverButtonLabel": "Visualisez {occurrencesCount} {occurrencesCount, plural, one {occurrence} other {occurrences}} dans Discover.", + "xpack.apm.errorRate": "Taux de transactions ayant échoué", + "xpack.apm.errorRate.chart.errorRate": "Taux de transactions ayant échoué (moy.)", + "xpack.apm.errorRate.chart.errorRate.previousPeriodLabel": "Période précédente", + "xpack.apm.errorsTable.errorMessageAndCulpritColumnLabel": "Message d'erreur et coupable", + "xpack.apm.errorsTable.groupIdColumnDescription": "Hachage de la trace de pile. Regroupe les erreurs similaires, même lorsque le message d'erreur est différent en raison des paramètres dynamiques.", + "xpack.apm.errorsTable.groupIdColumnLabel": "ID du groupe", + "xpack.apm.errorsTable.noErrorsLabel": "Aucune erreur n'a été trouvée", + "xpack.apm.errorsTable.occurrencesColumnLabel": "Occurrences", + "xpack.apm.errorsTable.typeColumnLabel": "Type", + "xpack.apm.errorsTable.unhandledLabel": "Non géré", + "xpack.apm.failedTransactionsCorrelations.licenseCheckText": "Pour utiliser la fonctionnalité de corrélation des transactions ayant échoué, vous devez disposer d'une licence Elastic Platinum.", + "xpack.apm.featureRegistry.apmFeatureName": "APM et expérience utilisateur", + "xpack.apm.feedbackMenu.appName": "APM", + "xpack.apm.fetcher.error.status": "Erreur", + "xpack.apm.fetcher.error.title": "Erreur lors de la récupération des ressources", + "xpack.apm.fetcher.error.url": "URL", + "xpack.apm.filter.environment.allLabel": "Tous", + "xpack.apm.filter.environment.label": "Environnement", + "xpack.apm.filter.environment.notDefinedLabel": "Non défini", + "xpack.apm.filter.environment.selectEnvironmentLabel": "Sélectionner l'environnement", + "xpack.apm.fleet_integration.settings.advancedOptionsLavel": "Options avancées", + "xpack.apm.fleet_integration.settings.apm.capturePersonalDataDescription": "Capturer des données personnelles, telles que l'IP ou l'agent utilisateur", + "xpack.apm.fleet_integration.settings.apm.capturePersonalDataTitle": "Capture des données personnelles", + "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentDescription": "Environnement de service par défaut pour l'enregistrement des événements n'ayant aucun environnement de service défini.", + "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentLabel": "Environnement de service par défaut", + "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentTitle": "Configuration de service", + "xpack.apm.fleet_integration.settings.apm.expvarEnabledDescription": "Exposé sous /debug/vars", + "xpack.apm.fleet_integration.settings.apm.expvarEnabledTitle": "Activer la prise en charge d'expvar de Golang pour le serveur APM", + "xpack.apm.fleet_integration.settings.apm.hostDescription": "Choisissez un nom et une description pour identifier facilement le type d'utilisation de cette intégration.", + "xpack.apm.fleet_integration.settings.apm.hostLabel": "Hôte", + "xpack.apm.fleet_integration.settings.apm.hostTitle": "Configuration du serveur", + "xpack.apm.fleet_integration.settings.apm.idleTimeoutLabel": "Temps d'inactivité avant la fermeture de la connexion sous-jacente", + "xpack.apm.fleet_integration.settings.apm.maxConnectionsLabel": "Connexions acceptées simultanément", + "xpack.apm.fleet_integration.settings.apm.maxEventBytesLabel": "Taille maximale par événement (octets)", + "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesDescription": "Définissez des limites pour la taille des en-têtes de requêtes et les configurations de temporisation.", + "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesLabel": "Taille maximale de l'en-tête d'une requête (octets)", + "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesTitle": "Limites", + "xpack.apm.fleet_integration.settings.apm.readTimeoutLabel": "Durée maximale pour la lecture d'une requête intégrale", + "xpack.apm.fleet_integration.settings.apm.responseHeadersDescription": "Définissez des limites pour la taille des en-têtes de requêtes et les configurations de temporisation.", + "xpack.apm.fleet_integration.settings.apm.responseHeadersHelpText": "Peut être utilisé pour la conformité à la politique de sécurité.", + "xpack.apm.fleet_integration.settings.apm.responseHeadersLabel": "En-têtes HTTP personnalisés ajoutés aux réponses HTTP", + "xpack.apm.fleet_integration.settings.apm.responseHeadersTitle": "En-têtes personnalisés", + "xpack.apm.fleet_integration.settings.apm.settings.subtitle": "Paramètres de l'intégration APM.", + "xpack.apm.fleet_integration.settings.apm.settings.title": "Général", + "xpack.apm.fleet_integration.settings.apm.shutdownTimeoutLabel": "Durée maximale avant la libération des ressources lors de l'arrêt", + "xpack.apm.fleet_integration.settings.apm.urlLabel": "URL", + "xpack.apm.fleet_integration.settings.apm.writeTimeoutLabel": "Durée maximale pour la rédaction d'une réponse", + "xpack.apm.fleet_integration.settings.apmAgent.description": "Configurez l'instrumentation pour les applications {title}.", + "xpack.apm.fleet_integration.settings.disabledLabel": "Désactivé", + "xpack.apm.fleet_integration.settings.enabledLabel": "Activé", + "xpack.apm.fleet_integration.settings.optionalLabel": "Facultatif", + "xpack.apm.fleet_integration.settings.requiredFieldLabel": "Champ requis", + "xpack.apm.fleet_integration.settings.requiredLabel": "Requis", + "xpack.apm.fleet_integration.settings.rum.enableRumDescription": "Activer le monitoring des utilisateurs réels (RUM)", + "xpack.apm.fleet_integration.settings.rum.enableRumTitle": "Activer RUM", + "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderDescription": "Configurer l'authentification pour l'agent", + "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderHelpText": "En-têtes Origin autorisés pouvant être envoyés par les agents utilisateurs.", + "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderLabel": "En-têtes Origin autorisés", + "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderTitle": "En-têtes personnalisés", + "xpack.apm.fleet_integration.settings.rum.rumAllowOriginsHelpText": "Access-Control-Allow-Headers pris en charge en plus de \"Content-Type\", \"Content-Encoding\" et \"Accept\".", + "xpack.apm.fleet_integration.settings.rum.rumAllowOriginsLabel": "Access-Control-Allow-Headers", + "xpack.apm.fleet_integration.settings.rum.rumLibraryPatternHelpText": "Identifiez les cadres de la bibliothèque en faisant correspondre le file_name et le abs_path du cadre de la trace de pile avec ce regexp.", + "xpack.apm.fleet_integration.settings.rum.rumLibraryPatternLabel": "Modèle du cadre de la bibliothèque", + "xpack.apm.fleet_integration.settings.rum.rumResponseHeadersHelpText": "Ajouté aux réponses RUM, par ex. à des fins de conformité à la politique de sécurité.", + "xpack.apm.fleet_integration.settings.rum.rumResponseHeadersLabel": "En-têtes de réponse HTTP personnalisés", + "xpack.apm.fleet_integration.settings.rum.settings.subtitle": "Gérez la configuration de l'agent RUM JS.", + "xpack.apm.fleet_integration.settings.rum.settings.title": "Real User Monitoring (monitoring des utilisateurs réels)", + "xpack.apm.fleet_integration.settings.selectOrCreateOptions": "Sélectionner ou créer des options", + "xpack.apm.fleet_integration.settings.tls.settings.subtitle": "Paramètres pour la certification TLS.", + "xpack.apm.fleet_integration.settings.tls.settings.title": "Paramètres TLS", + "xpack.apm.fleet_integration.settings.tls.tlsCertificateLabel": "Chemin d'accès au certificat du serveur", + "xpack.apm.fleet_integration.settings.tls.tlsCertificateTitle": "Certificat TLS", + "xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesHelpText": "Ne peut pas être configuré pour TLS 1.3.", + "xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesLabel": "Suites de chiffrement pour les connexions TLS", + "xpack.apm.fleet_integration.settings.tls.tlsCurveTypesLabel": "Types de courbes pour les suites de chiffrement ECDHE", + "xpack.apm.fleet_integration.settings.tls.tlsEnabledTitle": "Activer TLS", + "xpack.apm.fleet_integration.settings.tls.tlsKeyLabel": "Chemin d'accès à la clé de certificat du serveur", + "xpack.apm.fleet_integration.settings.tls.tlsSupportedProtocolsLabel": "Versions de protocoles prises en charge", + "xpack.apm.fleetIntegration.assets.description": "Consulter les traces de l'application et les cartes de service dans APM", + "xpack.apm.fleetIntegration.assets.name": "Services", + "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText": "Installer l'agent APM", + "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentDescription": "Une fois l'agent lancé, vous pouvez installer des agents APM sur vos hôtes pour collecter des données depuis vos applications et services.", + "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentTitle": "Installer l'agent APM", + "xpack.apm.formatters.hoursTimeUnitLabel": "h", + "xpack.apm.formatters.microsTimeUnitLabel": "μs", + "xpack.apm.formatters.millisTimeUnitLabel": "ms", + "xpack.apm.formatters.minutesTimeUnitLabel": "min", + "xpack.apm.formatters.secondsTimeUnitLabel": "s", + "xpack.apm.header.badge.readOnly.text": "Lecture seule", + "xpack.apm.header.badge.readOnly.tooltip": "Enregistrement impossible", + "xpack.apm.helpMenu.upgradeAssistantLink": "Assistant de mise à niveau", + "xpack.apm.helpPopover.ariaLabel": "Aide", + "xpack.apm.home.alertsMenu.alerts": "Alertes et règles", + "xpack.apm.home.alertsMenu.createAnomalyAlert": "Créer une règle d'anomalie", + "xpack.apm.home.alertsMenu.createThresholdAlert": "Créer une règle de seuil", + "xpack.apm.home.alertsMenu.errorCount": "Nombre d'erreurs", + "xpack.apm.home.alertsMenu.transactionDuration": "Latence", + "xpack.apm.home.alertsMenu.transactionErrorRate": "Taux de transactions ayant échoué", + "xpack.apm.home.alertsMenu.viewActiveAlerts": "Gérer les règles", + "xpack.apm.home.serviceLogsTabLabel": "Logs", + "xpack.apm.home.serviceMapTabLabel": "Carte des services", + "xpack.apm.instancesLatencyDistributionChartLegend": "Instances", + "xpack.apm.instancesLatencyDistributionChartLegend.previousPeriod": "Période précédente", + "xpack.apm.instancesLatencyDistributionChartTitle": "Distribution de la latence des instances", + "xpack.apm.instancesLatencyDistributionChartTooltipClickToFilterDescription": "Cliquer pour filtrer par instance", + "xpack.apm.instancesLatencyDistributionChartTooltipInstancesTitle": "{instancesCount} {instancesCount, plural, one {instance} other {instances}}", + "xpack.apm.instancesLatencyDistributionChartTooltipLatencyLabel": "Latence", + "xpack.apm.instancesLatencyDistributionChartTooltipThroughputLabel": "Rendement", + "xpack.apm.invalidLicense.licenseManagementLink": "Gérer votre licence", + "xpack.apm.invalidLicense.message": "L'interface utilisateur d'APM n'est pas disponible car votre licence actuelle a expiré ou n'est plus valide.", + "xpack.apm.invalidLicense.title": "Licence non valide", + "xpack.apm.jvmsTable.cpuColumnLabel": "Moy. CPU", + "xpack.apm.jvmsTable.explainServiceNodeNameMissing": "Nous n'avons pas pu déterminer à quelles JVM ces indicateurs correspondent. Cela provient probablement du fait que vous exécutez une version du serveur APM antérieure à 7.5. La mise à niveau du serveur APM vers la version 7.5 ou supérieure devrait résoudre le problème.", + "xpack.apm.jvmsTable.heapMemoryColumnLabel": "Moy. segment de mémoire", + "xpack.apm.jvmsTable.nameColumnLabel": "Nom", + "xpack.apm.jvmsTable.nameExplanation": "Par défaut, le nom de la JVM est l'ID du conteneur (le cas échéant) ou le nom d'hôte. Vous pouvez néanmoins le configurer manuellement via la configuration \"service_node_name\" de l'agent.", + "xpack.apm.jvmsTable.noJvmsLabel": "Aucune JVM n'a été trouvée", + "xpack.apm.jvmsTable.nonHeapMemoryColumnLabel": "Moy. segment de mémoire sans tas", + "xpack.apm.jvmsTable.threadCountColumnLabel": "Nombre de threads max", + "xpack.apm.keyValueFilterList.actionFilterLabel": "Filtrer par valeur", + "xpack.apm.kueryBar.placeholder": "Rechercher {event, select,\n transaction {des transactions}\n metric {des indicateurs}\n error {des erreurs}\n other {des transactions, des erreurs et des indicateurs}\n } (par ex. {queryExample})", + "xpack.apm.latencyCorrelations.licenseCheckText": "Pour utiliser les corrélations de latence, vous devez disposer d'une licence Elastic Platinum. Elle vous permettra de découvrir quels champs sont corrélés à de faibles performances.", + "xpack.apm.license.betaBadge": "Version bêta", + "xpack.apm.license.betaTooltipMessage": "Cette fonctionnalité est actuellement en version bêta. Si vous rencontrez des bugs ou si vous souhaitez apporter des commentaires, ouvrez un ticket de problème ou visitez notre forum de discussion.", + "xpack.apm.license.button": "Commencer l'essai", + "xpack.apm.license.title": "Commencer un essai gratuit de 30 jours", + "xpack.apm.localFilters.titles.browser": "Navigateur", + "xpack.apm.localFilters.titles.device": "Appareil", + "xpack.apm.localFilters.titles.location": "Lieu", + "xpack.apm.localFilters.titles.os": "Système d'exploitation", + "xpack.apm.localFilters.titles.serviceName": "Nom de service", + "xpack.apm.localFilters.titles.transactionUrl": "URL", + "xpack.apm.metrics.transactionChart.machineLearningLabel": "Machine Learning :", + "xpack.apm.metrics.transactionChart.machineLearningTooltip": "Le flux affiche les limites attendues de la latence moyenne. Une annotation verticale rouge signale des anomalies avec un score d'anomalie de 75 ou plus.", + "xpack.apm.metrics.transactionChart.machineLearningTooltip.withKuery": "Les résultats de Machine Learning sont masqués lorsque la barre de recherche est utilisée comme filtre", + "xpack.apm.metrics.transactionChart.viewJob": "Afficher la tâche", + "xpack.apm.navigation.serviceMapTitle": "Carte des services", + "xpack.apm.navigation.servicesTitle": "Services", + "xpack.apm.navigation.tracesTitle": "Traces", + "xpack.apm.notAvailableLabel": "N/A", + "xpack.apm.percentOfParent": "({value} de {parentType, select, transaction { transaction } trace {trace} })", + "xpack.apm.profiling.collapseSimilarFrames": "Réduire les éléments similaires", + "xpack.apm.profiling.highlightFrames": "Rechercher", + "xpack.apm.profiling.table.name": "Nom", + "xpack.apm.profiling.table.value": "Auto", + "xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel": "Pas de données disponibles", + "xpack.apm.propertiesTable.agentFeature.noResultFound": "Pas de résultats pour \"{value}\".", + "xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel": "Trace de pile d'exception", + "xpack.apm.propertiesTable.tabs.logs.serviceName": "Nom de service", + "xpack.apm.propertiesTable.tabs.logsLabel": "Logs", + "xpack.apm.propertiesTable.tabs.logStacktraceLabel": "Trace de pile des logs", + "xpack.apm.propertiesTable.tabs.metadataLabel": "Métadonnées", + "xpack.apm.propertiesTable.tabs.timelineLabel": "Chronologie", + "xpack.apm.searchInput.filter": "Filtrer…", + "xpack.apm.selectPlaceholder": "Sélectionner une option :", + "xpack.apm.serviceDependencies.breakdownChartTitle": "Temps consacré par dépendance", + "xpack.apm.serviceDetails.dependenciesTabLabel": "Dépendances", + "xpack.apm.serviceDetails.errorsTabLabel": "Erreurs", + "xpack.apm.serviceDetails.metrics.cpuUsageChartTitle": "Utilisation CPU", + "xpack.apm.serviceDetails.metrics.errorOccurrencesChart.title": "Occurrences d'erreurs", + "xpack.apm.serviceDetails.metrics.errorsList.title": "Erreurs", + "xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "Utilisation mémoire système", + "xpack.apm.serviceDetails.metricsTabLabel": "Indicateurs", + "xpack.apm.serviceDetails.nodesTabLabel": "JVM", + "xpack.apm.serviceDetails.overviewTabLabel": "Aperçu", + "xpack.apm.serviceDetails.profilingTabExperimentalDescription": "Le profilage est à un stade hautement expérimental, dédié uniquement à une utilisation interne.", + "xpack.apm.serviceDetails.profilingTabExperimentalLabel": "Expérimental", + "xpack.apm.serviceDetails.profilingTabLabel": "Profilage", + "xpack.apm.serviceDetails.transactionsTabLabel": "Transactions", + "xpack.apm.serviceHealthStatus.critical": "Critique", + "xpack.apm.serviceHealthStatus.healthy": "Intègre", + "xpack.apm.serviceHealthStatus.unknown": "Inconnu", + "xpack.apm.serviceHealthStatus.warning": "Avertissement", + "xpack.apm.serviceIcons.cloud": "Cloud", + "xpack.apm.serviceIcons.container": "Conteneur", + "xpack.apm.serviceIcons.service": "Service", + "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, =0 {Zone de disponibilité} one {Zone de disponibilité} other {Zones de disponibilité}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, =0{Type de machine} one {Type de machine} other {Types de machines}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "ID projet", + "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "Fournisseur cloud", + "xpack.apm.serviceIcons.serviceDetails.container.containerizedLabel": "Conteneurisé", + "xpack.apm.serviceIcons.serviceDetails.container.noLabel": "Non", + "xpack.apm.serviceIcons.serviceDetails.container.orchestrationLabel": "Orchestration", + "xpack.apm.serviceIcons.serviceDetails.container.osLabel": "Système d'exploitation", + "xpack.apm.serviceIcons.serviceDetails.container.totalNumberInstancesLabel": "Nombre total d'instances", + "xpack.apm.serviceIcons.serviceDetails.container.yesLabel": "Oui", + "xpack.apm.serviceIcons.serviceDetails.service.agentLabel": "Nom et version de l'agent", + "xpack.apm.serviceIcons.serviceDetails.service.frameworkLabel": "Nom du framework", + "xpack.apm.serviceIcons.serviceDetails.service.runtimeLabel": "Nom et version de l'exécution", + "xpack.apm.serviceIcons.serviceDetails.service.versionLabel": "Version du service", + "xpack.apm.serviceLogs.noInfrastructureMessage": "Il n'y a aucun message log à afficher.", + "xpack.apm.serviceMap.anomalyDetectionPopoverDisabled": "Affichez les indicateurs d'intégrité du service en activant la détection des anomalies dans les paramètres APM.", + "xpack.apm.serviceMap.anomalyDetectionPopoverLink": "Afficher les anomalies", + "xpack.apm.serviceMap.anomalyDetectionPopoverNoData": "Nous n'avons pas trouvé de score d'anomalie dans la plage temporelle sélectionnée. Consultez les détails dans l'explorateur d'anomalies.", + "xpack.apm.serviceMap.anomalyDetectionPopoverScoreMetric": "Score (max.)", + "xpack.apm.serviceMap.anomalyDetectionPopoverTitle": "Détection des anomalies", + "xpack.apm.serviceMap.anomalyDetectionPopoverTooltip": "Les indicateurs d'intégrité du service sont soutenus par la fonctionnalité de détection des anomalies dans le Machine Learning", + "xpack.apm.serviceMap.avgCpuUsagePopoverStat": "Utilisation CPU (moy.)", + "xpack.apm.serviceMap.avgMemoryUsagePopoverStat": "Utilisation de la mémoire (moy.)", + "xpack.apm.serviceMap.avgReqPerMinutePopoverMetric": "Rendement (moy.)", + "xpack.apm.serviceMap.avgTransDurationPopoverStat": "Latence (moy.)", + "xpack.apm.serviceMap.center": "Centre", + "xpack.apm.serviceMap.download": "Télécharger", + "xpack.apm.serviceMap.emptyBanner.docsLink": "En savoir plus dans la documentation", + "xpack.apm.serviceMap.emptyBanner.message": "Nous démapperons les services connectés et les requêtes externes si nous parvenons à les détecter. Assurez-vous d'exécuter la dernière version de l'agent APM.", + "xpack.apm.serviceMap.emptyBanner.title": "Il semblerait qu'il n'y ait qu'un seul service.", + "xpack.apm.serviceMap.errorRatePopoverStat": "Taux de transactions ayant échoué (moy.)", + "xpack.apm.serviceMap.focusMapButtonText": "Centrer la carte", + "xpack.apm.serviceMap.invalidLicenseMessage": "Pour accéder aux cartes de service, vous devez disposer d'une licence Elastic Platinum. Elle vous permettra de visualiser l'intégralité de la suite d'applications ainsi que vos données APM.", + "xpack.apm.serviceMap.noServicesPromptDescription": "Nous ne parvenons pas à trouver des services à mapper dans la plage temporelle et l'environnement actuellement sélectionnés. Veuillez essayer une autre plage ou vérifier l'environnement sélectionné. Si vous ne disposez d'aucun service, utilisez nos instructions de configuration pour vous aider à vous lancer.", + "xpack.apm.serviceMap.noServicesPromptTitle": "Aucun service disponible", + "xpack.apm.serviceMap.popover.noDataText": "Aucune donnée pour l'environnement sélectionné. Essayez de passer à un autre environnement.", + "xpack.apm.serviceMap.resourceCountLabel": "{count} ressources", + "xpack.apm.serviceMap.serviceDetailsButtonText": "Détails du service", + "xpack.apm.serviceMap.subtypePopoverStat": "Sous-type", + "xpack.apm.serviceMap.timeoutPrompt.docsLink": "En savoir plus sur les paramètres APM dans la documentation", + "xpack.apm.serviceMap.timeoutPromptDescription": "Délai expiré lors de la récupération des données pour la carte de services. Limitez la portée en sélectionnant une plage temporelle plus restreinte, ou utilisez le paramètre de configuration \"{configName}\" avec une valeur réduite.", + "xpack.apm.serviceMap.timeoutPromptTitle": "Expiration de la carte de services", + "xpack.apm.serviceMap.typePopoverStat": "Type", + "xpack.apm.serviceMap.viewFullMap": "Afficher la carte de services entière", + "xpack.apm.serviceMap.zoomIn": "Zoom avant", + "xpack.apm.serviceMap.zoomOut": "Zoom arrière", + "xpack.apm.serviceNodeMetrics.containerId": "ID conteneur", + "xpack.apm.serviceNodeMetrics.host": "Hôte", + "xpack.apm.serviceNodeMetrics.serviceName": "Nom de service", + "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningDocumentationLink": "documentation du serveur APM", + "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningText": "Nous n'avons pas pu déterminer à quelles JVM ces indicateurs correspondent. Cela provient probablement du fait que vous exécutez une version du serveur APM antérieure à 7.5. La mise à niveau du serveur APM vers la version 7.5 ou supérieure devrait résoudre le problème. Pour plus d'informations sur la mise à niveau, consultez {link}. Vous pouvez également utiliser la barre de recherche de Kibana pour filtrer par nom d'hôte, par ID de conteneur ou en fonction d'autres champs.", + "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningTitle": "Impossible d'identifier les JVM", + "xpack.apm.serviceNodeNameMissing": "(vide)", + "xpack.apm.serviceOverview.dependenciesTableTabLink": "Afficher les dépendances", + "xpack.apm.serviceOverview.dependenciesTableTitle": "Services en aval et back-ends", + "xpack.apm.serviceOverview.errorsTableColumnLastSeen": "Vu en dernier", + "xpack.apm.serviceOverview.errorsTableColumnName": "Nom", + "xpack.apm.serviceOverview.errorsTableColumnOccurrences": "Occurrences", + "xpack.apm.serviceOverview.errorsTableLinkText": "Afficher les erreurs", + "xpack.apm.serviceOverview.errorsTableTitle": "Erreurs", + "xpack.apm.serviceOverview.instancesTable.actionMenus.container.subtitle": "Affichez les logs et les indicateurs de ce conteneur pour plus de détails.", + "xpack.apm.serviceOverview.instancesTable.actionMenus.container.title": "Détails du conteneur", + "xpack.apm.serviceOverview.instancesTable.actionMenus.containerLogs": "Logs du conteneur", + "xpack.apm.serviceOverview.instancesTable.actionMenus.containerMetrics": "Indicateurs du conteneur", + "xpack.apm.serviceOverview.instancesTable.actionMenus.filterByInstance": "Filtrer l'aperçu par instance", + "xpack.apm.serviceOverview.instancesTable.actionMenus.metrics": "Indicateurs", + "xpack.apm.serviceOverview.instancesTable.actionMenus.pod.subtitle": "Affichez les logs et indicateurs de ce pod pour plus de détails.", + "xpack.apm.serviceOverview.instancesTable.actionMenus.pod.title": "Détails du pod", + "xpack.apm.serviceOverview.instancesTable.actionMenus.podLogs": "Logs du pod", + "xpack.apm.serviceOverview.instancesTable.actionMenus.podMetrics": "Indicateurs du pod", + "xpack.apm.serviceOverview.instancesTableColumnCpuUsage": "Utilisation CPU (moy.)", + "xpack.apm.serviceOverview.instancesTableColumnErrorRate": "Taux de transactions ayant échoué", + "xpack.apm.serviceOverview.instancesTableColumnMemoryUsage": "Utilisation de la mémoire (moy.)", + "xpack.apm.serviceOverview.instancesTableColumnNodeName": "Nom du nœud", + "xpack.apm.serviceOverview.instancesTableColumnThroughput": "Rendement", + "xpack.apm.serviceOverview.instancesTableTitle": "Instances", + "xpack.apm.serviceOverview.instanceTable.details.cloudTitle": "Cloud", + "xpack.apm.serviceOverview.instanceTable.details.containerTitle": "Conteneur", + "xpack.apm.serviceOverview.instanceTable.details.serviceTitle": "Service", + "xpack.apm.serviceOverview.latencyChartTitle": "Latence", + "xpack.apm.serviceOverview.latencyChartTitle.prepend": "Indicateur", + "xpack.apm.serviceOverview.latencyChartTitle.previousPeriodLabel": "Période précédente", + "xpack.apm.serviceOverview.latencyColumnAvgLabel": "Latence (moy.)", + "xpack.apm.serviceOverview.latencyColumnDefaultLabel": "Latence", + "xpack.apm.serviceOverview.latencyColumnP95Label": "Latence (95e)", + "xpack.apm.serviceOverview.latencyColumnP99Label": "Latence (99e)", + "xpack.apm.serviceOverview.throughtputChart.previousPeriodLabel": "Période précédente", + "xpack.apm.serviceOverview.throughtputChartTitle": "Rendement", + "xpack.apm.serviceOverview.tpmHelp": "Le rendement est mesuré en transactions par minute (tpm)", + "xpack.apm.serviceOverview.transactionsTableColumnErrorRate": "Taux de transactions ayant échoué", + "xpack.apm.serviceOverview.transactionsTableColumnImpact": "Impact", + "xpack.apm.serviceOverview.transactionsTableColumnName": "Nom", + "xpack.apm.serviceOverview.transactionsTableColumnThroughput": "Rendement", + "xpack.apm.serviceProfiling.valueTypeLabel.allocObjects": "Objets alloués", + "xpack.apm.serviceProfiling.valueTypeLabel.allocSpace": "Espace alloué", + "xpack.apm.serviceProfiling.valueTypeLabel.cpuTime": "Sur CPU", + "xpack.apm.serviceProfiling.valueTypeLabel.inuseObjects": "Objets utilisés", + "xpack.apm.serviceProfiling.valueTypeLabel.inuseSpace": "Espace utilisé", + "xpack.apm.serviceProfiling.valueTypeLabel.samples": "Échantillons", + "xpack.apm.serviceProfiling.valueTypeLabel.unknown": "Autre", + "xpack.apm.serviceProfiling.valueTypeLabel.wallTime": "Mur", + "xpack.apm.servicesTable.environmentColumnLabel": "Environnement", + "xpack.apm.servicesTable.environmentCount": "{environmentCount, plural, one {1 environnement} other {# environnements}}", + "xpack.apm.servicesTable.healthColumnLabel": "Intégrité", + "xpack.apm.servicesTable.latencyAvgColumnLabel": "Latence (moy.)", + "xpack.apm.servicesTable.metricsExplanationLabel": "Que sont ces indicateurs ?", + "xpack.apm.servicesTable.nameColumnLabel": "Nom", + "xpack.apm.servicesTable.notFoundLabel": "Aucun service trouvé", + "xpack.apm.servicesTable.throughputColumnLabel": "Rendement", + "xpack.apm.servicesTable.tooltip.metricsExplanation": "Les indicateurs des services sont agrégés selon le type de transaction \"request\", \"page-load\", ou en fonction du type de transaction de niveau supérieur disponible.", + "xpack.apm.servicesTable.transactionColumnLabel": "Type de transaction", + "xpack.apm.servicesTable.transactionErrorRate": "Taux de transactions ayant échoué", + "xpack.apm.settings.agentConfig": "Configuration de l'agent", + "xpack.apm.settings.agentConfig.createConfigButton.tooltip": "Vous ne disposez pas d'autorisations pour créer des configurations d'agent", + "xpack.apm.settings.agentConfig.descriptionText": "Affinez votre configuration d'agent depuis l'application APM. Les modifications sont automatiquement propagées à vos agents APM, ce qui vous évite d'effectuer un redéploiement.", + "xpack.apm.settings.anomaly_detection.legacy_jobs.button": "Consulter les tâches", + "xpack.apm.settings.anomalyDetection": "Détection des anomalies", + "xpack.apm.settings.anomalyDetection.addEnvironments.cancelButtonText": "Annuler", + "xpack.apm.settings.anomalyDetection.addEnvironments.createJobsButtonText": "Créer des tâches", + "xpack.apm.settings.anomalyDetection.addEnvironments.descriptionText": "Sélectionnez les environnements de services dans lesquels vous souhaitez activer la détection des anomalies. Les anomalies seront mises en évidence pour tous les services et types de transactions dans les environnements sélectionnés.", + "xpack.apm.settings.anomalyDetection.addEnvironments.selectorLabel": "Environnements", + "xpack.apm.settings.anomalyDetection.addEnvironments.selectorPlaceholder": "Sélectionner ou ajouter des environnements", + "xpack.apm.settings.anomalyDetection.addEnvironments.titleText": "Sélectionner des environnements", + "xpack.apm.settings.anomalyDetection.jobList.actionColumnLabel": "Action", + "xpack.apm.settings.anomalyDetection.jobList.addEnvironments": "Créer une tâche de ML", + "xpack.apm.settings.anomalyDetection.jobList.emptyListText": "Aucune tâche de détection des anomalies.", + "xpack.apm.settings.anomalyDetection.jobList.environmentColumnLabel": "Environnement", + "xpack.apm.settings.anomalyDetection.jobList.environments": "Environnements", + "xpack.apm.settings.anomalyDetection.jobList.failedFetchText": "Impossible de récupérer les tâches de détection des anomalies.", + "xpack.apm.settings.anomalyDetection.jobList.mlDescriptionText": "Pour ajouter la détection des anomalies à un nouvel environnement, créez une tâche de Machine Learning. Vous pouvez gérer les tâches de Machine Learning existantes dans {mlJobsLink}.", + "xpack.apm.settings.anomalyDetection.jobList.mlDescriptionText.mlJobsLinkText": "Machine Learning", + "xpack.apm.settings.anomalyDetection.jobList.mlJobLinkText": "Afficher une tâche dans ML", + "xpack.apm.settings.apmIndices.applyButton": "Appliquer les modifications", + "xpack.apm.settings.apmIndices.applyChanges.failed.text": "Un problème est survenu lors de l'application des index. Erreur : {errorMessage}", + "xpack.apm.settings.apmIndices.applyChanges.failed.title": "Impossible d'appliquer les index.", + "xpack.apm.settings.apmIndices.applyChanges.succeeded.text": "Les modifications apportées aux index ont été correctement appliquées. Ces modifications sont immédiatement appliquées dans l'interface utilisateur APM", + "xpack.apm.settings.apmIndices.applyChanges.succeeded.title": "Index appliqués", + "xpack.apm.settings.apmIndices.cancelButton": "Annuler", + "xpack.apm.settings.apmIndices.description": "L'interface utilisateur APM utilise des modèles d'indexation pour interroger vos index APM. Si vous avez personnalisé les noms des index sur lesquels le serveur APM écrit les événements, vous devrez peut-être mettre à jour ces modèles pour que l'interface utilisateur APM fonctionne. Dans ce cas précis, les paramètres prévalent sur ceux définis dans kibana.yml.", + "xpack.apm.settings.apmIndices.errorIndicesLabel": "Index des erreurs", + "xpack.apm.settings.apmIndices.helpText": "Remplace {configurationName} : {defaultValue}", + "xpack.apm.settings.apmIndices.metricsIndicesLabel": "Index des indicateurs", + "xpack.apm.settings.apmIndices.noPermissionTooltipLabel": "Votre rôle d'utilisateur ne dispose pas d'autorisations pour changer les index APM", + "xpack.apm.settings.apmIndices.onboardingIndicesLabel": "Intégration des index", + "xpack.apm.settings.apmIndices.sourcemapIndicesLabel": "Index des source maps", + "xpack.apm.settings.apmIndices.spanIndicesLabel": "Index des intervalles", + "xpack.apm.settings.apmIndices.title": "Index", + "xpack.apm.settings.apmIndices.transactionIndicesLabel": "Index des transactions", + "xpack.apm.settings.createApmPackagePolicy.errorToast.title": "Impossible de créer une politique de package APM sur la politique d'agent cloud", + "xpack.apm.settings.customizeApp": "Personnaliser l'application", + "xpack.apm.settings.indices": "Index", + "xpack.apm.settings.schema": "Schéma", + "xpack.apm.settings.schema.confirm.apmServerSettingsCloudLinkText": "Accéder aux paramètres du serveur APM dans Elastic Cloud", + "xpack.apm.settings.schema.confirm.cancelText": "Annuler", + "xpack.apm.settings.schema.confirm.checkboxLabel": "Je confirme vouloir basculer vers les flux de données", + "xpack.apm.settings.schema.confirm.irreversibleWarning.message": "Il est possible que cela affecte temporairement votre collecte de données APM pendant la progression de la migration. Le processus de migration ne devrait prendre que quelques minutes.", + "xpack.apm.settings.schema.confirm.irreversibleWarning.title": "Le basculement vers les flux de données est une action irréversible", + "xpack.apm.settings.schema.confirm.switchButtonText": "Basculer vers les flux de données", + "xpack.apm.settings.schema.confirm.title": "Veuillez confirmer votre choix", + "xpack.apm.settings.schema.confirm.unsupportedConfigs.descriptionText": "Les paramètres utilisateur apm-server.yml personnalisés compatibles seront déplacés vers le serveur Fleet à votre place. Nous vous informerons des paramètres incompatibles avant de les supprimer.", + "xpack.apm.settings.schema.confirm.unsupportedConfigs.title": "Les paramètres utilisateur apm-server.yml suivants sont incompatibles et seront supprimés", + "xpack.apm.settings.schema.descriptionText.irreversibleEmphasisText": "irréversible", + "xpack.apm.settings.schema.descriptionText.superuserEmphasisText": "superutilisateur", + "xpack.apm.settings.schema.disabledReason": "L'option Basculer vers les flux de données est indisponible : {reasons}", + "xpack.apm.settings.schema.disabledReason.cloudApmMigrationEnabled": "La migration vers le cloud n'est pas activée", + "xpack.apm.settings.schema.disabledReason.hasCloudAgentPolicy": "La politique d'agent cloud n'existe pas", + "xpack.apm.settings.schema.disabledReason.hasRequiredRole": "L'utilisateur ne dispose pas du rôle de superutilisateur", + "xpack.apm.settings.schema.migrate.classicIndices.currentSetup": "Configuration actuelle", + "xpack.apm.settings.schema.migrate.classicIndices.description": "Vous utilisez actuellement des index APM classiques pour vos données. Ce schéma de données est sur le point de disparaître et sera remplacé par des flux de données dans la version 8.0 d'Elastic Stack.", + "xpack.apm.settings.schema.migrate.classicIndices.title": "Index APM classiques", + "xpack.apm.settings.schema.migrate.dataStreams.buttonText": "Basculer vers les flux de données", + "xpack.apm.settings.schema.migrate.dataStreams.description": "À partir de maintenant, toutes les nouvelles données ingérées seront stockées dans les flux de données. Les données précédemment ingérées restent dans les index APM classiques. Les applications APM et UX continueront à prendre en charge les deux types d'index.", + "xpack.apm.settings.schema.migrate.dataStreams.title": "Flux de données", + "xpack.apm.settings.schema.migrationInProgressPanelDescription": "Nous créons actuellement une instance de serveur Fleet pour contenir le nouveau serveur APM pendant la fermeture de l'ancienne instance du serveur APM. Dans quelques minutes, vous devriez voir vos données réintégrer l'application.", + "xpack.apm.settings.schema.migrationInProgressPanelTitle": "Basculement vers les flux de données…", + "xpack.apm.settings.schema.success.description": "Votre intégration APM est à présent configurée et prête à recevoir des données de vos agents actuellement instrumentés. N'hésitez pas à consulter les politiques appliquées à votre intégration.", + "xpack.apm.settings.schema.success.returnText": "ou revenez simplement à l'{serviceInventoryLink}.", + "xpack.apm.settings.schema.success.returnText.serviceInventoryLink": "Inventaire de service", + "xpack.apm.settings.schema.success.title": "Les flux de données ont été configurés avec succès !", + "xpack.apm.settings.schema.success.viewIntegrationInFleet.buttonText": "Afficher l'intégration APM dans Fleet", + "xpack.apm.settings.title": "Paramètres", + "xpack.apm.settings.unsupportedConfigs.errorToast.title": "Impossible de récupérer les paramètres du serveur APM", + "xpack.apm.settingsLinkLabel": "Paramètres", + "xpack.apm.setupInstructionsButtonLabel": "Instructions de configuration", + "xpack.apm.stacktraceTab.causedByFramesToogleButtonLabel": "Provoqué par", + "xpack.apm.stacktraceTab.libraryFramesToogleButtonLabel": "{count, plural, one {# cadre de bibliothèque} other {# cadres de bibliothèque}}", + "xpack.apm.stacktraceTab.localVariablesToogleButtonLabel": "Variables locales", + "xpack.apm.stacktraceTab.noStacktraceAvailableLabel": "Aucune trace de pile disponible.", + "xpack.apm.timeComparison.label": "Comparaison", + "xpack.apm.timeComparison.select.dayBefore": "Jour précédent", + "xpack.apm.timeComparison.select.weekBefore": "Semaine précédente", + "xpack.apm.toggleHeight.showLessButtonLabel": "Afficher moins de lignes", + "xpack.apm.toggleHeight.showMoreButtonLabel": "Afficher plus de lignes", + "xpack.apm.tracesTable.avgResponseTimeColumnLabel": "Latence (moy.)", + "xpack.apm.tracesTable.impactColumnDescription": "Points de terminaison les plus utilisés et les plus lents de votre service. C'est le résultat de la multiplication de la latence et du rendement", + "xpack.apm.tracesTable.impactColumnLabel": "Impact", + "xpack.apm.tracesTable.nameColumnLabel": "Nom", + "xpack.apm.tracesTable.notFoundLabel": "Aucune trace trouvée pour cette recherche", + "xpack.apm.tracesTable.originatingServiceColumnLabel": "Service d'origine", + "xpack.apm.tracesTable.tracesPerMinuteColumnLabel": "Traces par minute", + "xpack.apm.transactionActionMenu.actionsButtonLabel": "Investiguer", + "xpack.apm.transactionActionMenu.container.subtitle": "Affichez les logs et les indicateurs de ce conteneur pour plus de détails.", + "xpack.apm.transactionActionMenu.container.title": "Détails du conteneur", + "xpack.apm.transactionActionMenu.customLink.section": "Liens personnalisés", + "xpack.apm.transactionActionMenu.customLink.showAll": "Afficher tout", + "xpack.apm.transactionActionMenu.customLink.showFewer": "Afficher moins", + "xpack.apm.transactionActionMenu.customLink.subtitle": "Les liens s'ouvriront dans une nouvelle fenêtre.", + "xpack.apm.transactionActionMenu.host.subtitle": "Affichez les logs et les indicateurs de l'hôte pour plus de détails.", + "xpack.apm.transactionActionMenu.host.title": "Détails de l'hôte", + "xpack.apm.transactionActionMenu.pod.subtitle": "Affichez les logs et indicateurs de ce pod pour plus de détails.", + "xpack.apm.transactionActionMenu.pod.title": "Détails du pod", + "xpack.apm.transactionActionMenu.showContainerLogsLinkLabel": "Logs du conteneur", + "xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel": "Indicateurs du conteneur", + "xpack.apm.transactionActionMenu.showHostLogsLinkLabel": "Logs de l'hôte", + "xpack.apm.transactionActionMenu.showHostMetricsLinkLabel": "Indicateurs de l'hôte", + "xpack.apm.transactionActionMenu.showPodLogsLinkLabel": "Logs du pod", + "xpack.apm.transactionActionMenu.showPodMetricsLinkLabel": "Indicateurs du pod", + "xpack.apm.transactionActionMenu.showTraceLogsLinkLabel": "Logs de trace", + "xpack.apm.transactionActionMenu.status.subtitle": "Affichez le statut pour plus de détails.", + "xpack.apm.transactionActionMenu.status.title": "Détails de statut", + "xpack.apm.transactionActionMenu.trace.subtitle": "Afficher les logs de trace pour plus de détails.", + "xpack.apm.transactionActionMenu.trace.title": "Détails de la trace", + "xpack.apm.transactionActionMenu.viewInUptime": "Statut", + "xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel": "Afficher l'exemple de document", + "xpack.apm.transactionBreakdown.chartTitle": "Temps consacré par type d'intervalle", + "xpack.apm.transactionDetails.clearSelectionAriaLabel": "Effacer la sélection", + "xpack.apm.transactionDetails.distribution.panelTitle": "Distribution de la latence", + "xpack.apm.transactionDetails.emptySelectionText": "Glisser et déposer pour sélectionner une plage", + "xpack.apm.transactionDetails.errorCount": "{errorCount, number} {errorCount, plural, one {erreur} other {erreurs}}", + "xpack.apm.transactionDetails.noTraceParentButtonTooltip": "Le parent de la trace n'a pas pu être trouvé", + "xpack.apm.transactionDetails.percentOfTraceLabelExplanation": "Le % de {parentType, select, transaction {transaction} trace {trace} } dépasse 100 %, car {childType, select, span {cet intervalle} transaction {cette transaction} } prend plus de temps que la transaction racine.", + "xpack.apm.transactionDetails.requestMethodLabel": "Méthode de requête", + "xpack.apm.transactionDetails.resultLabel": "Résultat", + "xpack.apm.transactionDetails.serviceLabel": "Service", + "xpack.apm.transactionDetails.servicesTitle": "Services", + "xpack.apm.transactionDetails.spanFlyout.compositeExampleWarning": "Il s'agit d'un exemple de document pour un groupe d'intervalles similaires consécutifs", + "xpack.apm.transactionDetails.spanFlyout.databaseStatementTitle": "Déclaration de la base de données", + "xpack.apm.transactionDetails.spanFlyout.nameLabel": "Nom", + "xpack.apm.transactionDetails.spanFlyout.spanAction": "Action", + "xpack.apm.transactionDetails.spanFlyout.spanDetailsTitle": "Détails de l'intervalle", + "xpack.apm.transactionDetails.spanFlyout.spanSubtype": "Sous-type", + "xpack.apm.transactionDetails.spanFlyout.spanType": "Type", + "xpack.apm.transactionDetails.spanFlyout.spanType.navigationTimingLabel": "Temporisation de la navigation", + "xpack.apm.transactionDetails.spanFlyout.stackTraceTabLabel": "Trace de pile", + "xpack.apm.transactionDetails.spanFlyout.viewSpanInDiscoverButtonLabel": "Afficher l'intervalle dans Discover", + "xpack.apm.transactionDetails.spanTypeLegendTitle": "Type", + "xpack.apm.transactionDetails.statusCode": "Code du statut", + "xpack.apm.transactionDetails.syncBadgeAsync": "async", + "xpack.apm.transactionDetails.syncBadgeBlocking": "blocage", + "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsLabel": "Corrélations des transactions ayant échoué", + "xpack.apm.transactionDetails.tabs.latencyLabel": "Corrélations de latence", + "xpack.apm.transactionDetails.tabs.traceSamplesLabel": "Échantillons de traces", + "xpack.apm.transactionDetails.traceNotFound": "La trace sélectionnée n'a pas pu être trouvée", + "xpack.apm.transactionDetails.traceSampleTitle": "Échantillon de trace", + "xpack.apm.transactionDetails.transactionLabel": "Transaction", + "xpack.apm.transactionDetails.transFlyout.callout.agentDroppedSpansMessage": "L'agent APM qui a signalé cette transaction a abandonné {dropped} intervalles ou plus, d'après sa configuration.", + "xpack.apm.transactionDetails.transFlyout.callout.learnMoreAboutDroppedSpansLinkText": "Découvrir plus d'informations sur les intervalles abandonnés.", + "xpack.apm.transactionDetails.transFlyout.transactionDetailsTitle": "Détails de la transaction", + "xpack.apm.transactionDetails.userAgentAndVersionLabel": "Agent utilisateur et version", + "xpack.apm.transactionDetails.viewFullTraceButtonLabel": "Afficher la trace complète", + "xpack.apm.transactionDetails.viewingFullTraceButtonTooltip": "Affichage actuel de la trace complète", + "xpack.apm.transactionDistribution.chart.allTransactionsLabel": "Toutes les transactions", + "xpack.apm.transactionDistribution.chart.currentTransactionMarkerLabel": "Échantillon actuel", + "xpack.apm.transactionDistribution.chart.numberOfTransactionsLabel": "Nb de transactions", + "xpack.apm.transactionDistribution.chart.percentileMarkerLabel": "{markerPercentile}e centile", + "xpack.apm.transactionDurationAlert.aggregationType.95th": "95e centile", + "xpack.apm.transactionDurationAlert.aggregationType.99th": "99e centile", + "xpack.apm.transactionDurationAlert.aggregationType.avg": "Moyenne", + "xpack.apm.transactionDurationAlert.name": "Seuil de latence", + "xpack.apm.transactionDurationAlertTrigger.ms": "ms", + "xpack.apm.transactionDurationAlertTrigger.when": "Quand", + "xpack.apm.transactionDurationAnomalyAlert.name": "Anomalie de latence", + "xpack.apm.transactionDurationAnomalyAlertTrigger.anomalySeverity": "Comporte une anomalie avec sévérité", + "xpack.apm.transactionDurationLabel": "Durée", + "xpack.apm.transactionErrorRateAlert.name": "Seuil du taux de transactions ayant échoué", + "xpack.apm.transactionErrorRateAlertTrigger.isAbove": "est supérieur à", + "xpack.apm.transactionRateLabel": "{displayedValue} tpm", + "xpack.apm.transactions.latency.chart.95thPercentileLabel": "95e centile", + "xpack.apm.transactions.latency.chart.99thPercentileLabel": "99e centile", + "xpack.apm.transactions.latency.chart.averageLabel": "Moyenne", + "xpack.apm.tutorial.agent_config.choosePolicy.helper": "Ajoute la configuration de la politique sélectionnée à l'extrait ci-dessous.", + "xpack.apm.tutorial.agent_config.choosePolicyLabel": "Choix de la politique", + "xpack.apm.tutorial.agent_config.defaultStandaloneConfig": "Configuration autonome par défaut", + "xpack.apm.tutorial.agent_config.fleetPoliciesLabel": "Politiques Fleet", + "xpack.apm.tutorial.agent_config.getStartedWithFleet": "Démarrer avec Fleet", + "xpack.apm.tutorial.agent_config.manageFleetPolicies": "Gérer les politiques Fleet", + "xpack.apm.tutorial.apmAgents.statusCheck.btnLabel": "Vérifier le statut de l'agent", + "xpack.apm.tutorial.apmAgents.statusCheck.errorMessage": "Aucune donnée n'a encore été reçue des agents", + "xpack.apm.tutorial.apmAgents.statusCheck.successMessage": "Les données ont été correctement reçues d'un ou de plusieurs agents", + "xpack.apm.tutorial.apmAgents.statusCheck.text": "Vérifiez que votre application est en cours d'exécution et que les agents envoient les données.", + "xpack.apm.tutorial.apmAgents.statusCheck.title": "Statut de l'agent", + "xpack.apm.tutorial.apmAgents.title": "Agents APM", + "xpack.apm.tutorial.apmServer.callOut.message": "Assurez-vous de mettre à jour votre serveur APM vers la version 7.0 ou supérieure. Vous pouvez également migrer vos données 6.x à l'aide de l'assistant de migration disponible dans la section de gestion de Kibana.", + "xpack.apm.tutorial.apmServer.callOut.title": "Important : mise à niveau vers la version 7.0 ou supérieure", + "xpack.apm.tutorial.apmServer.fleet.apmIntegration.button": "Intégration APM", + "xpack.apm.tutorial.apmServer.fleet.manageApmIntegration.button": "Gérer l'intégration APM dans Fleet", + "xpack.apm.tutorial.apmServer.fleet.message": "L'intégration d'APM installe les modèles Elasticsearch et les pipelines de nœuds d'ingestion pour les données APM.", + "xpack.apm.tutorial.apmServer.fleet.title": "Elastic APM (version bêta) est maintenant disponible dans Fleet !", + "xpack.apm.tutorial.apmServer.statusCheck.btnLabel": "Vérifier le statut du serveur APM", + "xpack.apm.tutorial.apmServer.statusCheck.errorMessage": "Aucun serveur APM détecté. Vérifiez qu'il est en cours d'exécution et que vous avez effectué la mise à jour vers la version 7.0 ou supérieure.", + "xpack.apm.tutorial.apmServer.statusCheck.successMessage": "Vous avez correctement configuré le serveur APM", + "xpack.apm.tutorial.apmServer.statusCheck.text": "Vérifiez que le serveur APM est en cours d'exécution avant de commencer à mettre en œuvre les agents APM.", + "xpack.apm.tutorial.apmServer.statusCheck.title": "Statut du serveur APM", + "xpack.apm.tutorial.apmServer.title": "Serveur APM", + "xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment": "Ajouter l'agent aux applications installées", + "xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment": "Pour envoyer les indicateurs de performance, ajoutez notre intergiciel de traçage :", + "xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment": "a-z, A-Z, 0-9, -, _ et espace", + "xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "Définir l'URL personnalisée du serveur APM (par défaut : {defaultApmServerUrl})", + "xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "Définissez le nom de service obligatoire. Caractères autorisés :", + "xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment": "Définir l'environnement de service", + "xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "À utiliser si le serveur APM requiert un token secret", + "xpack.apm.tutorial.djangoClient.configure.textPost": "Consultez la [documentation]({documentationLink}) pour une utilisation avancée.", + "xpack.apm.tutorial.djangoClient.configure.textPre": "Les agents sont des bibliothèques exécutées dans les processus de votre application. Les services APM sont créés par programmation à partir du \"SERVICE_NAME\".", + "xpack.apm.tutorial.djangoClient.configure.title": "Configurer l'agent", + "xpack.apm.tutorial.djangoClient.install.textPre": "Installez l'agent APM pour Python en tant que dépendance.", + "xpack.apm.tutorial.djangoClient.install.title": "Installer l'agent APM", + "xpack.apm.tutorial.dotNetClient.configureAgent.textPost": "Si vous ne transférez pas une instance \"IConfiguration\" à l'agent (par ex., pour les applications non ASP.NET Core) vous pouvez également configurer l'agent par le biais de variables d'environnement. \n Consultez [the documentation]({documentationLink}) pour une utilisation avancée.", + "xpack.apm.tutorial.dotNetClient.configureAgent.title": "Exemple de fichier appsettings.json :", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPost": "La transmission d'une instance \"IConfiguration\" est facultative mais si cette opération est effectuée, l'agent lira les paramètres de configuration depuis cette instance \"IConfiguration\" (par ex. à partir du fichier \"appsettings.json\").", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPre": "Si vous utilisez ASP.NET Core avec le package \"Elastic.Apm.NetCoreAll\", appelez la méthode \"UseAllElasticApm\" dans la méthode \"Configure\" dans le fichier \"Startup.cs\".", + "xpack.apm.tutorial.dotNetClient.configureApplication.title": "Ajouter l'agent à l'application", + "xpack.apm.tutorial.dotNetClient.download.textPre": "Ajoutez le(s) package(s) d'agent depuis [NuGet]({allNuGetPackagesLink}) à votre application .NET. Plusieurs packages NuGet sont disponibles pour différents cas d'utilisation. \n\nPour une application ASP.NET Core avec Entity Framework Core, téléchargez le package [Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}). Ce package ajoutera automatiquement chaque composant d'agent à votre application. \n\n Si vous souhaitez minimiser les dépendances, vous pouvez utiliser le package [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) uniquement pour le monitoring d'ASP.NET Core ou le package [Elastic.Apm.EfCore]({efCorePackageLink}) uniquement pour le monitoring d'Entity Framework Core. \n\n Si vous souhaitez seulement utiliser l'API d'agent publique pour l'instrumentation manuelle, utilisez le package [Elastic.Apm]({elasticApmPackageLink}).", + "xpack.apm.tutorial.dotNetClient.download.title": "Télécharger l'agent APM", + "xpack.apm.tutorial.downloadServer.title": "Télécharger et décompresser le serveur APM", + "xpack.apm.tutorial.downloadServerRpm": "Vous cherchez les packages 32 bits ? Consultez la [Download page]({downloadPageLink}).", + "xpack.apm.tutorial.downloadServerTitle": "Vous cherchez les packages 32 bits ? Consultez la [Download page]({downloadPageLink}).", + "xpack.apm.tutorial.editConfig.textPre": "Si vous utilisez une version sécurisée X-Pack d'Elastic Stack, vous devez spécifier les informations d'identification dans le fichier de configuration \"apm-server.yml\".", + "xpack.apm.tutorial.editConfig.title": "Modifier la configuration", + "xpack.apm.tutorial.elasticCloud.textPre": "Pour activer le serveur APM, accédez à [the Elastic Cloud console](https://cloud.elastic.co/deployments/{deploymentId}/edit) et activez APM dans les paramètres de déploiement. Une fois activé, actualisez la page.", + "xpack.apm.tutorial.elasticCloudInstructions.title": "Agents APM", + "xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment": "a-z, A-Z, 0-9, -, _ et espace", + "xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment": "ou configurer l'utilisation d'ELASTIC_APM dans les paramètres de votre application", + "xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "initialiser à l'aide des variables d'environnement", + "xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "Définir l'URL personnalisée du serveur APM (par défaut : {defaultApmServerUrl})", + "xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "Définissez le nom de service obligatoire. Caractères autorisés :", + "xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment": "Définir l'environnement de service", + "xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "À utiliser si le serveur APM requiert un token secret", + "xpack.apm.tutorial.flaskClient.configure.textPost": "Consultez la [documentation]({documentationLink}) pour une utilisation avancée.", + "xpack.apm.tutorial.flaskClient.configure.textPre": "Les agents sont des bibliothèques exécutées dans les processus de votre application. Les services APM sont créés par programmation à partir du \"SERVICE_NAME\".", + "xpack.apm.tutorial.flaskClient.configure.title": "Configurer l'agent", + "xpack.apm.tutorial.flaskClient.install.textPre": "Installez l'agent APM pour Python en tant que dépendance.", + "xpack.apm.tutorial.flaskClient.install.title": "Installer l'agent APM", + "xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "Initialisez à l'aide des variables d'environnement :", + "xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "Définir l'URL de serveur APM personnalisée (par défaut : {defaultApmServerUrl})", + "xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment": "Définir l'environnement de service", + "xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment": "Configurez le nom de service. Caractères autorisés : # a-z, A-Z, 0-9, -, _ et espace.", + "xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment": "Si ELASTIC_APM_SERVICE_NAME n'est pas spécifié, le nom de l'exécutable sera utilisé.", + "xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "À utiliser si le serveur APM requiert un token secret", + "xpack.apm.tutorial.goClient.configure.textPost": "Consultez la [documentation]({documentationLink}) pour une configuration avancée.", + "xpack.apm.tutorial.goClient.configure.textPre": "Les agents sont des bibliothèques exécutées dans les processus de votre application. Les services APM sont créés par programmation à partir du nom du fichier exécutable, ou de la variable d'environnement \"ELASTIC_APM_SERVICE_NAME\".", + "xpack.apm.tutorial.goClient.configure.title": "Configurer l'agent", + "xpack.apm.tutorial.goClient.install.textPre": "Installez les packages d'agent APM pour Go.", + "xpack.apm.tutorial.goClient.install.title": "Installer l'agent APM", + "xpack.apm.tutorial.goClient.instrument.textPost": "Consultez la [documentation]({documentationLink}) pour obtenir un guide détaillé pour l'instrumentation du code source Go.", + "xpack.apm.tutorial.goClient.instrument.textPre": "Pour instrumenter votre application Go, utilisez l'un des modules d'instrumentation proposés ou directement l'API de traçage.", + "xpack.apm.tutorial.goClient.instrument.title": "Instrumenter votre application", + "xpack.apm.tutorial.introduction": "Collectez les indicateurs et les erreurs de performances approfondies depuis vos applications.", + "xpack.apm.tutorial.javaClient.download.textPre": "Téléchargez le fichier jar de l'agent depuis [Maven Central]({mavenCentralLink}). N'ajoutez **pas** l'agent comme dépendance de votre application.", + "xpack.apm.tutorial.javaClient.download.title": "Télécharger l'agent APM", + "xpack.apm.tutorial.javaClient.startApplication.textPost": "Consultez la [documentation]({documentationLink}) pour découvrir les options de configuration et l'utilisation avancée.", + "xpack.apm.tutorial.javaClient.startApplication.textPre": "Ajoutez l'indicateur \"-javaagent\" et configurez l'agent avec les propriétés du système.\n\n * Définir le nom de service requis (caractères autorisés : a-z, A-Z, 0-9, -, _ et espace)\n * Définir l'URL personnalisée du serveur APM (par défaut : {customApmServerUrl})\n * Définir le token secret du serveur APM\n * Définir l'environnement de service\n * Définir le package de base de votre application", + "xpack.apm.tutorial.javaClient.startApplication.title": "Lancer votre application avec l'indicateur javaagent", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.textPre": "Le serveur APM désactive la prise en charge du RUM par défaut. Consultez la [documentation]({documentationLink}) pour obtenir des détails sur l'activation de la prise en charge du RUM.", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title": "Activer la prise en charge du Real User Monitoring (monitoring des utilisateurs réels) dans le serveur APM", + "xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment": "Définir l'URL de serveur APM personnalisée (par défaut : {defaultApmServerUrl})", + "xpack.apm.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment": "Définir le nom de service requis (caractères autorisés : a-z, A-Z, 0-9, -, _ et espace)", + "xpack.apm.tutorial.jsClient.installDependency.commands.setServiceEnvironmentComment": "Définir l'environnement de service", + "xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment": "Définir la version de service (requis pour la fonctionnalité source map)", + "xpack.apm.tutorial.jsClient.installDependency.textPost": "Les intégrations de framework, tel que React ou Angular, ont des dépendances personnalisées. Consultez la [integration documentation]({docLink}) pour plus d'informations.", + "xpack.apm.tutorial.jsClient.installDependency.textPre": "Vous pouvez installer l'Agent comme dépendance de votre application avec \"npm install @elastic/apm-rum --save\".\n\nVous pouvez ensuite initialiser l'agent et le configurer dans votre application de cette façon :", + "xpack.apm.tutorial.jsClient.installDependency.title": "Configurer l'agent comme dépendance", + "xpack.apm.tutorial.jsClient.scriptTags.textPre": "Vous pouvez également utiliser les balises Script pour configurer l'agent. Ajoutez un indicateur \"