Chore: More internationalisation markup (#104051)

* More markup

* fix some ternaries

* more alerting markup

* fix unit tests
This commit is contained in:
Ashley Harrison
2025-04-16 09:25:18 +01:00
committed by GitHub
parent 68c6e4b1e7
commit 61cd19c540
84 changed files with 841 additions and 529 deletions
+15 -291
View File
@@ -523,9 +523,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/ColorPicker/ColorSwatch.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -543,10 +540,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/DateTimePickers/TimeSyncButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/Forms/Legacy/Input/Input.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
@@ -564,12 +557,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"packages/grafana-ui/src/components/InteractiveTable/Expander/index.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"]
],
"packages/grafana-ui/src/components/JSONFormatter/json_explorer/json_explorer.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -586,9 +573,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/PanelChrome/PanelContext.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -651,10 +635,6 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/Table/TableCellInspector.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-ui/src/components/Table/TableNG/Cells/RowExpander.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/Table/TableNG/Filter/Filter.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -702,10 +682,6 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/Table/TableRT/HeaderRow.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-ui/src/components/Table/TableRT/RowExpander.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/Table/TableRT/Table.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -731,9 +707,6 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/Tags/Tag.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/UsersIndicator/UsersIndicator.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
@@ -834,9 +807,6 @@ exports[`better eslint`] = {
"public/app/core/components/AccessControl/index.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
],
"public/app/core/components/AppChrome/History/HistoryWrapper.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/core/components/DynamicImports/SafeDynamicImport.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -851,13 +821,6 @@ exports[`better eslint`] = {
"public/app/core/components/LocalStorageValueProvider/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./LocalStorageValueProvider\`)", "0"]
],
"public/app/core/components/PasswordField/PasswordField.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/core/components/RolePicker/RolePickerInput.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/core/components/TagFilter/TagFilter.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -975,17 +938,6 @@ exports[`better eslint`] = {
"public/app/features/actions/ParamsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/admin/AdminFeatureTogglesPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/admin/AdminFeatureTogglesTable.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/admin/UserSessions.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/routes.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -1015,25 +967,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/alerting/unified/AlertGroups.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/GrafanaRuleQueryViewer.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/PanelAlertTabContent.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/RedirectToRuleViewer.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/AlertLabels.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/AnnotationDetailsField.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -1041,32 +978,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/alerting/unified/components/GrafanaAlertmanagerDeliveryWarning.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/InvalidIntervalWarning.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/MoreButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/NoAlertManagerWarning.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/alert-groups/AlertDetails.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/components/alert-groups/AlertGroup.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/alert-groups/AlertGroupAlertsTable.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/alert-groups/AlertGroupFilter.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -1074,93 +985,30 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/alerting/unified/components/alert-groups/AlertStateFilter.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/components/alert-groups/GroupBy.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/alerting/unified/components/alert-groups/MatcherFilter.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/contact-points/ContactPointHeader.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/components/contact-points/components/GlobalConfigAlert.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/components/contact-points/components/Modals.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/export/FileExportPreview.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/alerting/unified/components/export/GrafanaModifyExport.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/expressions/Expression.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/mute-timings/MuteTimingTimeInterval.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/notification-policies/Policy.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"]
],
"public/app/features/alerting/unified/components/notification-policies/PromDurationDocs.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/receivers/AlertInstanceModalSelector.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/receivers/ReceiversSection.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/receivers/TemplateDataDocs.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/receivers/form/ChannelOptions.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/alerting/unified/components/receivers/form/CloudReceiverForm.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/receivers/form/GrafanaReceiverForm.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/receivers/form/ReceiverForm.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"public/app/features/alerting/unified/components/receivers/form/TestContactPointModal.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@@ -1171,9 +1019,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
],
"public/app/features/alerting/unified/components/receivers/form/fields/SubformArrayField.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/alerting/unified/components/receivers/form/fields/SubformField.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@@ -1182,12 +1029,6 @@ exports[`better eslint`] = {
"public/app/features/alerting/unified/components/rule-editor/AnnotationKeyInput.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/AnnotationsStep.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/CloudAlertPreview.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/DashboardAnnotationField.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
@@ -1196,25 +1037,11 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/DurationQuickPick.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/ExpressionEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/NotificationsStep.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "6"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/PreviewRule.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/alerting/unified/components/rule-editor/PreviewRuleResult.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
@@ -1256,18 +1083,10 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/CloudDataSourceSelector.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/QueryAndExpressionsStep.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/SimpleCondition.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/SmartAlertTypeDetector.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
@@ -1420,14 +1239,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/auth-config/ProviderConfigPage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/auth-config/components/ProviderCard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/auth-config/fields.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
@@ -1475,10 +1286,6 @@ exports[`better eslint`] = {
"public/app/features/connections/tabs/ConnectData/ConnectData.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/connections/tabs/ConnectData/NoAccessModal/NoAccessModal.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/connections/tabs/ConnectData/NoAccessModal/index.tsx:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
],
@@ -1777,9 +1584,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard/components/GenAI/MinimalisticPagination.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard/components/Inspector/PanelInspector.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -1794,9 +1598,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
],
"public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard/components/PanelEditor/OverrideCategoryTitle.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
],
@@ -1804,12 +1605,6 @@ exports[`better eslint`] = {
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/dashboard/components/PanelEditor/VisualizationButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"]
],
"public/app/features/dashboard/components/PanelEditor/VisualizationSelectPane.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
@@ -1876,11 +1671,7 @@ exports[`better eslint`] = {
],
"public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/dashboard/components/TransformationsEditor/TransformationPicker.tsx:5381": [
[0, 0, 0, "\'VerticalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
@@ -2067,23 +1858,11 @@ exports[`better eslint`] = {
"public/app/features/datasources/components/ButtonRow.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/datasources/components/CloudInfoBox.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/datasources/components/DataSourcePluginConfigPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/datasources/components/DataSourceTypeCard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
],
"public/app/features/datasources/components/picker/AddNewDataSourceButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/datasources/components/useDataSourceInfo.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/datasources/state/actions.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@@ -2125,8 +1904,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
@@ -2161,27 +1939,12 @@ exports[`better eslint`] = {
"public/app/features/dimensions/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/explore/ContentOutline/ContentOutline.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/explore/CorrelationHelper.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
],
"public/app/features/explore/CorrelationTransformationAddModal.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"]
],
"public/app/features/explore/ExploreRunQueryButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/explore/FeatureTogglePage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@@ -2197,9 +1960,6 @@ exports[`better eslint`] = {
"public/app/features/explore/Logs/LogsSamplePanel.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/explore/Logs/LogsTableAvailableFields.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/explore/Logs/LogsTableMultiSelect.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@@ -2221,18 +1981,10 @@ exports[`better eslint`] = {
"public/app/features/explore/ShortLinkButtonMenu.tsx:5381": [
[0, 0, 0, "Do not use the t() function outside of a component or function", "0"]
],
"public/app/features/explore/TimeSyncButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/explore/TraceView/TraceView.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/explore/TraceView/components/TracePageHeader/SearchBar/NextPrevResult.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
@@ -2516,18 +2268,12 @@ exports[`better eslint`] = {
"public/app/features/org/state/reducers.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/panel/components/PanelPluginError.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/panel/components/PanelRenderer.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/panel/panellinks/linkSuppliers.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -2558,8 +2304,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./PluginUpdateAvailableBadge\`)", "4"]
],
"public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./GetStartedWithPlugin\`)", "0"]
@@ -2593,10 +2338,6 @@ exports[`better eslint`] = {
"public/app/features/plugins/admin/components/PluginDetailsSignature.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/plugins/admin/components/PluginListItem.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/plugins/admin/components/PluginUsage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
@@ -2750,11 +2491,6 @@ exports[`better eslint`] = {
"public/app/features/serviceaccounts/components/ServiceAccountProfileRow.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/serviceaccounts/components/ServiceAccountTokensTable.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/serviceaccounts/state/reducers.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -2824,11 +2560,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/transformers/editors/CalculateFieldTransformerEditor/WindowOptionsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/transformers/editors/CalculateFieldTransformerEditor/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`CalculateFieldTransformerEditor\`)", "0"],
@@ -2851,10 +2583,6 @@ exports[`better eslint`] = {
"public/app/features/transformers/editors/GroupByTransformerEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/transformers/editors/OrganizeFieldsTransformerEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/transformers/editors/ReduceTransformerEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -2864,9 +2592,8 @@ exports[`better eslint`] = {
"public/app/features/transformers/extractFields/ExtractFieldsTransformerEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"public/app/features/transformers/extractFields/components/JSONPathEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
@@ -2916,9 +2643,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/variables/constant/reducer.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -7,6 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useTheme2 } from '../../themes/ThemeContext';
import { t } from '../../utils/i18n';
/** @internal */
export enum ColorSwatchVariant {
@@ -36,7 +37,11 @@ export const ColorSwatch = React.forwardRef<HTMLDivElement, Props>(
<button
className={styles.swatch}
{...focusProps}
aria-label={colorLabel ? `${colorLabel} color` : 'Pick a color'}
aria-label={
colorLabel
? t('grafana-ui.color-swatch.aria-label-selected-color', '{{colorLabel}} color', { colorLabel })
: t('grafana-ui.color-swatch.aria-label-default', 'Pick a color')
}
type="button"
/>
</div>
@@ -87,7 +87,7 @@ describe('TimePicker', () => {
expect(syncButtons.length).toBe(2);
await userEvent.click(syncButtons[0]);
expect(onChange2).toBeCalledWith(value1);
const unsyncButtons = screen.getAllByLabelText('Un sync times');
const unsyncButtons = screen.getAllByLabelText('Unsync times');
expect(unsyncButtons.length).toBe(2);
});
});
@@ -46,7 +46,7 @@ interface InputState {
}
const ERROR_MESSAGES = {
default: () => t('time-picker.range-content.default-error', 'Please enter a past date or "now"'),
default: () => t('time-picker.range-content.default-error', 'Please enter a past date or "{{now}}"', { now: 'now' }),
range: () => t('time-picker.range-content.range-error', '"From" can\'t be after "To"'),
};
@@ -1,3 +1,4 @@
import { t } from '../../utils/i18n';
import { ToolbarButton } from '../ToolbarButton';
import { Tooltip } from '../Tooltip';
@@ -19,7 +20,11 @@ export function TimeSyncButton(props: TimeSyncButtonProps) {
<ToolbarButton
icon="link"
variant={isSynced ? 'active' : 'canvas'}
aria-label={isSynced ? 'Un sync times' : 'Sync times'}
aria-label={
isSynced
? t('grafana-ui.time-sync-button.aria-label-unsync', 'Unsync times')
: t('grafana-ui.time-sync-button.aria-label-sync', 'Sync times')
}
onClick={onClick}
/>
</Tooltip>
@@ -32,11 +32,19 @@ export function ExpanderHeader<K extends object>({ isAllRowsExpanded, toggleAllR
return (
<div className={expanderContainerStyles}>
<IconButton
aria-label={!isAllRowsExpanded ? 'Expand all rows' : 'Collapse all rows'}
aria-label={
!isAllRowsExpanded
? t('grafana-ui.interactive-table.aria-label-expand-all', 'Expand all rows')
: t('grafana-ui.interactive-table.aria-label-collapse-all', 'Collapse all rows')
}
name={!isAllRowsExpanded ? 'table-expand-all' : 'table-collapse-all'}
onClick={() => toggleAllRowsExpanded()}
size={'lg'}
tooltip={!isAllRowsExpanded ? 'Expand all rows' : 'Collapse all rows'}
tooltip={
!isAllRowsExpanded
? t('grafana-ui.interactive-table.tooltip-expand-all', 'Expand all rows')
: t('grafana-ui.interactive-table.tooltip-collapse-all', 'Collapse all rows')
}
variant={'secondary'}
/>
</div>
@@ -10,6 +10,7 @@ import { useStyles2, useTheme2 } from '../../themes';
import { getFocusStyles } from '../../themes/mixins';
import { usePointerDistance } from '../../utils';
import { DelayRender } from '../../utils/DelayRender';
import { t } from '../../utils/i18n';
import { useElementSelection } from '../ElementSelectionContext/ElementSelectionContext';
import { Icon } from '../Icon/Icon';
import { LoadingBar } from '../LoadingBar/LoadingBar';
@@ -275,7 +276,9 @@ export function PanelChrome({
<Icon
name={!collapsed ? 'angle-down' : 'angle-right'}
aria-hidden={!!title}
aria-label={!title ? 'toggle collapse panel' : undefined}
aria-label={
!title ? t('grafana-ui.panel-chrome.aria-label-toggle-collapse', 'toggle collapse panel') : undefined
}
/>
<Text variant="h6" truncate id={panelTitleId}>
{title}
@@ -3,6 +3,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../../../themes';
import { t } from '../../../../utils/i18n';
import { Icon } from '../../../Icon/Icon';
import { RowExpanderNGProps } from '../types';
@@ -17,7 +18,11 @@ export function RowExpander({ height, onCellExpand, isExpanded }: RowExpanderNGP
return (
<div className={styles.expanderCell} onClick={onCellExpand} onKeyDown={handleKeyDown}>
<Icon
aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
aria-label={
isExpanded
? t('grafana-ui.row-expander-ng.aria-label-collapse', 'Collapse row')
: t('grafana-ui.row-expander.aria-label-expand', 'Expand row')
}
name={isExpanded ? 'angle-down' : 'angle-right'}
size="lg"
/>
@@ -1,3 +1,4 @@
import { t } from '../../../utils/i18n';
import { Icon } from '../../Icon/Icon';
import { GrafanaTableRow } from '../types';
@@ -12,7 +13,11 @@ export function RowExpander({ row, tableStyles }: Props) {
return (
<div className={tableStyles.expanderCell} {...row.getToggleRowExpandedProps()}>
<Icon
aria-label={row.isExpanded ? 'Collapse row' : 'Expand row'}
aria-label={
row.isExpanded
? t('grafana-ui.row-expander.collapse', 'Collapse row')
: t('grafana-ui.row-expander.expand', 'Expand row')
}
name={row.isExpanded ? 'angle-down' : 'angle-right'}
size="lg"
/>
@@ -35,7 +35,10 @@ export const UsersIndicator = ({ users, onClick, limit = 4 }: UsersIndicatorProp
>
{limitReached && (
<UserIcon onClick={onClick} userView={{ user: { name: 'Extra users' }, lastActiveAt: '' }} showTooltip={false}>
{tooManyUsers ? '...' : `+${extraUsers}`}
{tooManyUsers
? // eslint-disable-next-line @grafana/no-untranslated-strings
'...'
: `+${extraUsers}`}
</UserIcon>
)}
{users
@@ -135,7 +135,11 @@ function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) {
<div>
{breadcrumbs.map((breadcrumb, index) => (
<Text key={index}>
{breadcrumb.text} {index !== breadcrumbs.length - 1 ? '> ' : ''}
{breadcrumb.text}{' '}
{index !== breadcrumbs.length - 1
? // eslint-disable-next-line @grafana/no-untranslated-strings
'> '
: ''}
</Text>
))}
</div>
@@ -4,6 +4,8 @@ import { selectors } from '@grafana/e2e-selectors';
import { Input, IconButton } from '@grafana/ui';
import { InputProps } from '@grafana/ui/internal';
import { t } from '../../internationalization';
interface Props extends Omit<InputProps, 'type'> {}
export const PasswordField = forwardRef<HTMLInputElement, Props>((props, ref) => {
@@ -24,7 +26,11 @@ export const PasswordField = forwardRef<HTMLInputElement, Props>((props, ref) =>
onClick={() => {
setShowPassword(!showPassword);
}}
tooltip={showPassword ? 'Hide password' : 'Show password'}
tooltip={
showPassword
? t('grafana-ui.password-field.tooltip-hide', 'Hide password')
: t('grafana-ui.password-field.tooltip-show', 'Show password')
}
/>
}
/>
@@ -5,7 +5,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, getInputStyles, sharedInputStyle, Tooltip, Icon, Spinner } from '@grafana/ui';
import { getFocusStyles } from '@grafana/ui/internal';
import { Trans } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { Role } from '../../../types';
@@ -89,7 +89,7 @@ export const RolePickerInput = ({
onMouseDown={stopPropagation}
onChange={onInputChange}
data-testid="role-picker-input"
placeholder={isFocused ? 'Select role' : ''}
placeholder={isFocused ? t('role-picker.input.placeholder-select-role', 'Select role') : undefined}
value={query}
/>
)}
@@ -5,7 +5,7 @@ import { useAsync } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Icon } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { Trans } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { getTogglesAPI } from './AdminFeatureTogglesAPI';
import { AdminFeatureTogglesTable } from './AdminFeatureTogglesTable';
@@ -28,8 +28,14 @@ export default function AdminFeatureTogglesPage() {
</div>
<span className={styles.message}>
{featureState.value?.restartRequired
? 'A restart is pending for your Grafana instance to apply the latest feature toggle changes'
: 'Saving feature toggle changes will prompt a restart of the instance, which may take a few minutes'}
? t(
'admin.feature-toggles.restart-pending',
'A restart is pending for your Grafana instance to apply the latest feature toggle changes'
)
: t(
'admin.feature-toggles.restart-required',
'Saving feature toggle changes will prompt a restart of the instance, which may take a few minutes'
)}
</span>
</div>
);
@@ -155,7 +155,9 @@ export function AdminFeatureTogglesTable({ featureToggles, allowEditing, onUpdat
{allowEditing && (
<div style={{ display: 'flex', justifyContent: 'flex-end', padding: '0 0 5px 0' }}>
<Button disabled={!hasModifications() || isSaving} onClick={showSaveChangesModal(true)} ref={saveButtonRef}>
{isSaving ? 'Saving...' : 'Save Changes'}
{isSaving
? t('admin.admin-feature-toggles-table.saving', 'Saving...')
: t('admin.admin-feature-toggles-table.save-changes', 'Save changes')}
</Button>
<ConfirmModal
isOpen={showSaveModel}
+1 -1
View File
@@ -82,7 +82,7 @@ class BaseUserSessions extends PureComponent<Props, State> {
{sessions &&
sessions.map((session, index) => (
<tr key={`${session.id}-${index}`}>
<td>{session.isActive ? 'Now' : session.seenAt}</td>
<td>{session.isActive ? t('admin.user-sessions.now', 'Now') : session.seenAt}</td>
<td>{formatDate(session.createdAt, { dateStyle: 'long' })}</td>
<td>{session.clientIp}</td>
<td>{`${session.browser} on ${session.os} ${session.osVersion}`}</td>
@@ -75,8 +75,10 @@ const AlertGroups = () => {
'Grafana alerts are not delivered to Grafana Alertmanager'
)}
>
Grafana is configured to send alerts to external alertmanagers only. No alerts are expected to be available
here for the selected Alertmanager.
<Trans i18nKey="alerting.alert-groups.body-grafana-alerted-delivered">
Grafana is configured to send alerts to external alertmanagers only. No alerts are expected to be available
here for the selected Alertmanager.
</Trans>
</Alert>
)}
@@ -88,7 +90,12 @@ const AlertGroups = () => {
(index === 0 && Object.keys(group.labels).length > 0)) && (
<Box paddingY={2}>
<Text element="h2" variant="body">
Grouped by: {Object.keys(group.labels).join(', ')}
<Trans
i18nKey="alerting.alert-groups.grouped-by"
values={{ labels: Object.keys(group.labels).join(', ') }}
>
Grouped by: {'{{labels}}'}
</Trans>
</Text>
</Box>
)}
@@ -123,7 +123,12 @@ export function QueryPreview({
if (relativeTimeRange) {
headerItems.push(
<Text color="secondary" key="timerange">
{rangeUtil.secondsToHms(relativeTimeRange.from)} to now
<Trans
i18nKey="alerting.query-preview.relative-time-range"
values={{ from: rangeUtil.secondsToHms(relativeTimeRange.from) }}
>
{'{{from}}'} to now
</Trans>
</Text>
);
}
@@ -229,7 +234,11 @@ function ExpressionPreview({ refId, model, evalData, isAlertCondition }: Express
return <Preview rawSql={model.expression || ''} datasourceType={model.datasource?.type} />;
default:
return <>Expression not supported: {model.type}</>;
return (
<Trans i18nKey="alerting.expression-preview.expression-not-supported" values={{ type: model.type }}>
Expression not supported: {'{{type}}'}
</Trans>
);
}
}
@@ -344,7 +353,9 @@ function ClassicConditionViewer({ model }: { model: ExpressionQuery }) {
return (
<React.Fragment key={index}>
<div className={styles.blue}>
{index === 0 ? 'WHEN' : !!operator?.type && evalOperators[operator?.type]?.text}
{index === 0
? t('alerting.classic-condition-viewer.when', 'WHEN')
: !!operator?.type && evalOperators[operator?.type]?.text}
</div>
<div className={styles.bold}>{reducer?.type && reducerFunctions[reducer.type]?.text}</div>
<div className={styles.blue}>
@@ -36,7 +36,14 @@ export const PanelAlertTabContent = ({ dashboard, panel }: Props) => {
severity="error"
>
{errors.map((error, index) => (
<div key={index}>Failed to load Grafana rules state: {stringifyErrorLike(error)}</div>
<div key={index}>
<Trans
i18nKey="alerting.panel-alert-tab-content.failed-to-load-error"
values={{ error: stringifyErrorLike(error) }}
>
Failed to load Grafana rules state: {'{{error}}'}
</Trans>
</div>
))}
</Alert>
) : null;
@@ -1,6 +1,5 @@
import { css } from '@emotion/css';
import { chain } from 'lodash';
import pluralize from 'pluralize';
import { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
@@ -56,7 +55,9 @@ export const AlertLabels = ({ labels, commonLabels = {}, size, onClick }: Props)
tooltipPlacement="top"
size="sm"
>
+{commonLabelsCount} common {pluralize('label', commonLabelsCount)}
<Trans i18nKey="alerting.alert-labels.common-labels-count" count={commonLabelsCount}>
+{'{{count}}'} common labels
</Trans>
</Button>
)}
{showCommonLabels && hasCommonLabels && (
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { AlertmanagerChoice } from '../../../../plugins/datasource/alertmanager/types';
import { alertmanagerApi } from '../api/alertmanagerApi';
@@ -47,11 +47,15 @@ export function GrafanaAlertmanagerDeliveryWarning({ currentAlertmanager }: Graf
'Grafana alerts are not delivered to Grafana Alertmanager'
)}
>
Grafana is configured to send alerts to external Alertmanagers only. Changing Grafana Alertmanager configuration
will not affect delivery of your alerts.
<Trans i18nKey="alerting.grafana-alertmanager-delivery-warning.configuration-changes-external">
Grafana is configured to send alerts to external Alertmanagers only. Changing Grafana Alertmanager
configuration will not affect delivery of your alerts.
</Trans>
<div className={styles.adminHint}>
To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your
Administrator.
<Trans i18nKey="alerting.grafana-alertmanager-delivery-warning.admin-hint-external">
To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your
Administrator.
</Trans>
</div>
</Alert>
);
@@ -66,11 +70,15 @@ export function GrafanaAlertmanagerDeliveryWarning({ currentAlertmanager }: Graf
)}
severity="warning"
>
Ensure you make configuration changes in the correct Alertmanagers; both internal and external. Changing one
will not affect the others.
<Trans i18nKey="alerting.grafana-alertmanager-delivery-warning.configuration-changes-all">
Ensure you make configuration changes in the correct Alertmanagers; both internal and external. Changing one
will not affect the others.
</Trans>
<div className={styles.adminHint}>
To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your
Administrator.
<Trans i18nKey="alerting.grafana-alertmanager-delivery-warning.admin-hint-all">
To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your
Administrator.
</Trans>
</div>
</Alert>
);
@@ -1,6 +1,6 @@
import { config } from '@grafana/runtime';
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
const EvaluationIntervalLimitExceeded = () => (
<Alert
@@ -10,10 +10,14 @@ const EvaluationIntervalLimitExceeded = () => (
'Global evaluation interval limit exceeded'
)}
>
A minimum evaluation interval of <strong>{config.unifiedAlerting.minInterval}</strong> has been configured in
Grafana.
<br />
Please contact the administrator to configure a lower interval.
<Trans
i18nKey="alerting.evaluation-interval-limit-exceeded.body-minimum-interval"
values={{ minInterval: config.unifiedAlerting.minInterval }}
>
A minimum evaluation interval of <strong>{'{{minInterval}}'}</strong> has been configured in Grafana.
<br />
Please contact the administrator to configure a lower interval.
</Trans>
</Alert>
);
@@ -2,11 +2,21 @@ import { Ref, forwardRef } from 'react';
import { Button, ButtonProps, Icon, Stack } from '@grafana/ui';
import { Trans, t } from '../../../../core/internationalization';
const MoreButton = forwardRef(function MoreButton(props: ButtonProps, ref: Ref<HTMLButtonElement>) {
return (
<Button variant="secondary" size="sm" type="button" aria-label="More" ref={ref} {...props}>
<Button
variant="secondary"
size="sm"
type="button"
aria-label={t('alerting.more-button.aria-label', 'More')}
ref={ref}
{...props}
>
<Stack direction="row" alignItems="center" gap={0}>
More <Icon name="angle-down" />
<Trans i18nKey="alerting.more-button.button-text">More</Trans>
<Icon name="angle-down" />
</Stack>
</Button>
);
@@ -1,5 +1,5 @@
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { AlertManagerDataSource } from '../utils/datasource';
@@ -12,7 +12,9 @@ const NoAlertManagersAvailable = () => (
title={t('alerting.no-alert-managers-available.title-no-alertmanager-found', 'No Alertmanager found')}
severity="warning"
>
We could not find any external Alertmanagers and you may not have access to the built-in Grafana Alertmanager.
<Trans i18nKey="alerting.no-alert-managers-available.body-no-alertmanager-found">
We could not find any external Alertmanagers and you may not have access to the built-in Grafana Alertmanager.
</Trans>
</Alert>
);
@@ -24,8 +26,10 @@ const OtherAlertManagersAvailable = () => (
)}
severity="warning"
>
The selected Alertmanager no longer exists or you may not have permission to access it. You can select a different
Alertmanager from the dropdown.
<Trans i18nKey="alerting.other-alert-managers-available.body-selected-alertmanager-not-found">
The selected Alertmanager no longer exists or you may not have permission to access it. You can select a different
Alertmanager from the dropdown.
</Trans>
</Alert>
);
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { LinkButton, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { contextSrv } from 'app/core/services/context_srv';
import { AlertState, AlertmanagerAlert } from 'app/plugins/datasource/alertmanager/types';
import { AccessControlAction } from 'app/types';
@@ -60,7 +60,9 @@ export const AlertDetails = ({ alert, alertManagerSourceName }: AmNotificationsA
)}
{isSeeSourceButtonEnabled && alert.generatorURL && (
<LinkButton className={styles.button} href={alert.generatorURL} icon={'chart-line'} size={'sm'}>
{isGrafanaSource ? 'See alert rule' : 'See source'}
{isGrafanaSource
? t('alerting.alert-details.button-see-rule', 'See alert rule')
: t('alerting.alert-details.button-see-source', 'See source')}
</LinkButton>
)}
</div>
@@ -68,11 +70,17 @@ export const AlertDetails = ({ alert, alertManagerSourceName }: AmNotificationsA
<AnnotationDetailsField key={annotationKey} annotationKey={annotationKey} value={annotationValue} />
))}
<div className={styles.receivers}>
Receivers:{' '}
{alert.receivers
.map(({ name }) => name)
.filter((name) => !!name)
.join(', ')}
<Trans
i18nKey="alerting.alert-details.receivers-list"
values={{
receivers: alert.receivers
.map(({ name }) => name)
.filter((name) => !!name)
.join(', '),
}}
>
Receivers: {'{{receivers}}'}
</Trans>
</div>
</>
);
@@ -43,15 +43,17 @@ export const AlertGroup = ({ alertManagerSourceName, group }: Props) => {
{receiverInGroup && (
<MetaText icon="at">
Delivered to{' '}
<TextLink
href={createContactPointSearchLink(contactPoint, alertManagerSourceName)}
variant="bodySmall"
color="primary"
inline={false}
>
{group.receiver.name}
</TextLink>
<Trans i18nKey="alerting.alert-group.delivered-to" values={{ name: group.receiver.name }}>
Delivered to{' '}
<TextLink
href={createContactPointSearchLink(contactPoint, alertManagerSourceName)}
variant="bodySmall"
color="primary"
inline={false}
>
{'{{name}}'}
</TextLink>
</Trans>
</MetaText>
)}
</Stack>
@@ -5,6 +5,7 @@ import { GrafanaTheme2, intervalToAbbreviatedDurationString } from '@grafana/dat
import { useStyles2 } from '@grafana/ui';
import { AlertmanagerAlert } from 'app/plugins/datasource/alertmanager/types';
import { Trans } from '../../../../../core/internationalization';
import { AlertLabels } from '../AlertLabels';
import { DynamicTableColumnProps, DynamicTableItemProps } from '../DynamicTable';
import { DynamicTableWithGuidelines } from '../DynamicTableWithGuidelines';
@@ -33,11 +34,17 @@ export const AlertGroupAlertsTable = ({ alerts, alertManagerSourceName }: Props)
<>
<AmAlertStateTag state={alert.status.state} />
<span className={styles.duration}>
for{' '}
{intervalToAbbreviatedDurationString({
start: new Date(alert.startsAt),
end: new Date(alert.endsAt),
})}
<Trans
i18nKey="alerting.alert-group-alerts-table.duration"
values={{
time: intervalToAbbreviatedDurationString({
start: new Date(alert.startsAt),
end: new Date(alert.endsAt),
}),
}}
>
for {'{{time}}'}
</Trans>
</span>
</>
),
@@ -19,21 +19,29 @@ export const AlertStateFilter = ({ onStateFilterChange, stateFilter }: Props) =>
return (
<div>
<Label>
<span>Notification state&nbsp;</span>
<span>
<Trans i18nKey="alerting.alert-state-filter.notification-state">Notification state</Trans>&nbsp;
</span>
<Tooltip
content={
<div>
<ul>
<li>
Active: The alert notification has been handled. The alert is still firing and continues to be
managed.
<Trans i18nKey="alerting.alert-state-filter.active-the-alert-is-firing">
Active: The alert notification has been handled. The alert is still firing and continues to be
managed.
</Trans>
</li>
<li>
<Trans i18nKey="alerting.alert-state-filter.suppressed-the-alert-has-been-silenced">
Suppressed: The alert has been silenced.
</Trans>
</li>
<li>Unprocessed: The alert is received but its notification has not been processed yet.</li>
<li>
<Trans i18nKey="alerting.alert-state-filter.unprocessed-the-alert-is-received">
Unprocessed: The alert is received but its notification has not been processed yet.
</Trans>
</li>
</ul>
</div>
}
@@ -2,7 +2,7 @@ import { uniq } from 'lodash';
import { SelectableValue } from '@grafana/data';
import { Icon, Label, MultiSelect, Tooltip } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
import { isPrivateLabelKey } from '../../utils/labels';
@@ -24,12 +24,16 @@ export const GroupBy = ({ groups, groupBy, onGroupingChange }: Props) => {
return (
<div data-testid={'group-by-container'}>
<Label>
<span>Custom group by&nbsp;</span>
<span>
<Trans i18nKey="alerting.group-by.custom-group-by">Custom group by</Trans>&nbsp;
</span>
<Tooltip
content={
<div>
Group notifications using a different combination of labels. This option can help validate the grouping
settings of your notification policies.
<Trans i18nKey="alerting.group-by.tooltip-group-by">
Group notifications using a different combination of labels. This option can help validate the grouping
settings of your notification policies.
</Trans>
</div>
}
>
@@ -216,7 +216,14 @@ export const ContactPointHeader = ({ contactPoint, onDelete }: ContactPointHeade
<Spacer />
<LinkButton
tooltipPlacement="top"
tooltip={provisioned ? 'Provisioned contact points cannot be edited in the UI' : undefined}
tooltip={
provisioned
? t(
'alerting.contact-point-header.tooltip-provisioned-contact-points',
'Provisioned contact points cannot be edited in the UI'
)
: undefined
}
variant="secondary"
size="sm"
icon={canEdit ? 'pen' : 'eye'}
@@ -224,7 +231,9 @@ export const ContactPointHeader = ({ contactPoint, onDelete }: ContactPointHeade
data-testid={`${canEdit ? 'edit' : 'view'}-action`}
href={`/alerting/notifications/receivers/${encodeURIComponent(urlId)}/edit`}
>
{canEdit ? 'Edit' : 'View'}
{canEdit
? t('alerting.contact-point-header.button-edit', 'Edit')
: t('alerting.contact-point-header.button-view', 'View')}
</LinkButton>
{menuActions.length > 0 && (
<Dropdown overlay={<Menu>{menuActions}</Menu>}>
@@ -1,5 +1,5 @@
import { Alert, LinkButton } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { AlertmanagerAction } from '../../../hooks/useAbilities';
import { isVanillaPrometheusAlertManagerDataSource } from '../../../utils/datasource';
@@ -23,11 +23,15 @@ export const GlobalConfigAlert = ({ alertManagerName }: GlobalConfigAlertProps)
)}
>
<p>
For each external Alertmanager you can define global settings, like server addresses, usernames and password,
for all the supported contact points.
<Trans i18nKey="alerting.global-config-alert.body">
For each external Alertmanager you can define global settings, like server addresses, usernames and
password, for all the supported contact points.
</Trans>
</p>
<LinkButton href={makeAMLink('alerting/notifications/global-config', alertManagerName)} variant="secondary">
{isVanillaAM ? 'View global config' : 'Edit global config'}
{isVanillaAM
? t('alerting.global-config-alert.view-global-config', 'View global config')
: t('alerting.global-config-alert.edit-global-config', 'Edit global config')}
</LinkButton>
</Alert>
</Authorize>
@@ -72,7 +72,9 @@ export const useDeleteContactPointModal = (
<Modal.ButtonRow>
<Button type="button" variant="destructive" onClick={handleSubmit} disabled={isLoading}>
{isLoading ? 'Deleting...' : 'Yes, delete contact point'}
{isLoading
? t('alerting.use-delete-contact-point-modal.deleting', 'Deleting...')
: t('alerting.use-delete-contact-point-modal.delete-confirm', 'Yes, delete contact point')}
</Button>
<Button type="button" variant="secondary" onClick={handleDismiss} disabled={isLoading}>
<Trans i18nKey="alerting.common.cancel">Cancel</Trans>
@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom-v5-compat';
import { locationService } from '@grafana/runtime';
import { Alert, LoadingPlaceholder } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { RuleIdentifier } from '../../../../../types/unified-alerting';
import { useRuleWithLocation } from '../../hooks/useCombinedRule';
@@ -25,7 +25,9 @@ function GrafanaModifyExport() {
if (!ruleIdentifier) {
return (
<Alert title={t('alerting.grafana-modify-export.title-invalid-rule-id', 'Invalid rule ID')} severity="error">
The rule UID in the page URL is invalid. Please check the URL and try again.
<Trans i18nKey="alerting.grafana-modify-export.body-invalid-rule-id">
The rule UID in the page URL is invalid. Please check the URL and try again.
</Trans>
</Alert>
);
}
@@ -136,7 +136,11 @@ export const Expression: FC<ExpressionProps> = ({
return <SqlExpr onChange={(query) => onChangeQuery(query)} query={query} refIds={availableRefIds} alerting />;
default:
return <>Expression not supported: {query.type}</>;
return (
<Trans i18nKey="alerting.expression.not-supported" values={{ expression: query.type }}>
Expression not supported: {'{{expression}}'}
</Trans>
);
}
},
[onChangeQuery, queries, onQueriesValidationError]
@@ -265,7 +269,9 @@ export const ExpressionResult: FC<ExpressionResultProps> = ({ series, isAlertCon
/>
<Spacer />
<span className={styles.mutedText}>
{pageStart} - {pageEnd} of {series.length}
<Trans i18nKey="" values={{ pageStart, pageEnd, numPages: series.length }}>
{'{{pageStart}}'} - {'{{pageEnd}}'} of {'{{numPages}}'}
</Trans>
</span>
<Spacer />
<Button
@@ -30,10 +30,12 @@ export const MuteTimingTimeInterval = () => {
<FieldSet label={t('alerting.mute-timing-time-interval.label-time-intervals', 'Time intervals')}>
<>
<p>
A time interval is a definition for a moment in time. All fields are lists, and at least one list element must
be satisfied to match the field. If a field is left blank, any moment of time will match the field. For an
instant of time to match a complete time interval, all fields must match. A mute timing can contain multiple
time intervals.
<Trans i18nKey="alerting.mute-timing-time-interval.description">
A time interval is a definition for a moment in time. All fields are lists, and at least one list element
must be satisfied to match the field. If a field is left blank, any moment of time will match the field. For
an instant of time to match a complete time interval, all fields must match. A mute timing can contain
multiple time intervals.
</Trans>
</p>
<Stack direction="column" gap={2}>
{timeIntervals.map((timeInterval, timeIntervalIndex) => {
@@ -230,7 +230,11 @@ const Policy = (props: PolicyComponentProps) => {
<IconButton
name={showPolicyChildren ? 'angle-down' : 'angle-right'}
onClick={togglePolicyChildren}
aria-label={showPolicyChildren ? 'Collapse' : 'Expand'}
aria-label={
showPolicyChildren
? t('alerting.policies.aria-label-collapse', 'Collapse')
: t('alerting.policies.aria-label-expand', 'Expand')
}
/>
) : null}
{isImmutablePolicy ? (
@@ -305,7 +309,11 @@ const Policy = (props: PolicyComponentProps) => {
{dropdownMenuActions.length > 0 && (
<Dropdown overlay={<Menu>{dropdownMenuActions}</Menu>}>
<MoreButton
aria-label={isDefaultPolicy ? 'more actions for default policy' : 'more actions for policy'}
aria-label={
isDefaultPolicy
? t('alerting.policies.aria-label-more-default', 'more actions for default policy')
: t('alerting.policies.aria-label-more', 'more actions for policy')
}
data-testid="more-actions"
/>
</Dropdown>
@@ -894,7 +902,9 @@ function getContactPointErrors(contactPoint: string, contactPointsState: Receive
<Label
icon="at"
key={uniqueId()}
label={`Contact Point › ${status.name}`}
label={t('alerting.contact-point-errors.label-contact-point', 'Contact Point › {{name}}', {
name: status.name,
})}
value={status.lastNotifyAttemptError}
/>
));
@@ -10,9 +10,13 @@ export function PromDurationDocs() {
const styles = useStyles2(getPromDurationStyles);
return (
<div>
Prometheus duration format consist of a number followed by a time unit.
<Trans i18nKey="alerting.prom-duration-docs.explanation">
Prometheus duration format consist of a number followed by a time unit.
</Trans>
<br />
Different units can be combined for more granularity.
<Trans i18nKey="alerting.prom-duration-docs.different-units">
Different units can be combined for more granularity.
</Trans>
<hr />
<div className={styles.list}>
<div className={styles.header}>
@@ -47,7 +47,9 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
'No alerting capable query found'
)}
>
Cannot create alerts from this panel because no query to an alerting capable datasource is found.
<Trans i18nKey="alerting.new-rule-from-panel-button.body-no-alerting-capable-query-found">
Cannot create alerts from this panel because no query to an alerting capable datasource is found.
</Trans>
</Alert>
);
}
@@ -247,7 +247,11 @@ export function AlertInstanceModalSelector({
<div className={styles.column}>
{!selectedRule && !loading && (
<div className={styles.selectedRulePlaceholder}>
<div>Select an alert rule to get a list of available firing instances</div>
<div>
<Trans i18nKey="alerting.alert-instance-modal-selector.select-alert-rule">
Select an alert rule to get a list of available firing instances
</Trans>
</div>
</div>
)}
{loading && (
@@ -5,7 +5,7 @@ import { useToggle } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, Dropdown, Icon, Menu, MenuItem, Stack, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { GrafanaReceiversExporter } from '../export/GrafanaReceiversExporter';
@@ -64,7 +64,7 @@ export const ReceiversSection = ({
{showMore && (
<Dropdown overlay={newMenu}>
<Button variant="secondary">
More
<Trans i18nKey="alerting.receivers-section.button-more">More</Trans>
<Icon name="angle-down" />
</Button>
</Dropdown>
@@ -113,7 +113,9 @@ function KeyValueTemplateDataTable() {
return (
<div>
KeyValue is a set of key/value string pairs that represent labels and annotations.
<Trans i18nKey="alerting.key-value-template-data-table.description">
KeyValue is a set of key/value string pairs that represent labels and annotations.
</Trans>
<pre>
<code>{KeyValueCodeSnippet}</code>
</pre>
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
import { locationService } from '@grafana/runtime';
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { alertmanagerApi } from 'app/features/alerting/unified/api/alertmanagerApi';
import {
useCreateContactPoint,
@@ -76,7 +76,9 @@ export const CloudReceiverForm = ({ contactPoint, alertManagerSourceName, readOn
<>
{!isVanillaAM && (
<Alert title={t('alerting.cloud-receiver-form.title-info', 'Info')} severity="info">
Note that empty string values will be replaced with global defaults where appropriate.
<Trans i18nKey="alerting.cloud-receiver-form.body-info">
Note that empty string values will be replaced with global defaults where appropriate.
</Trans>
</Alert>
)}
<ReceiverForm<CloudChannelValues>
@@ -2,7 +2,7 @@ import { useMemo, useState } from 'react';
import { locationService } from '@grafana/runtime';
import { Alert, LoadingPlaceholder } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import {
useCreateContactPoint,
useUpdateContactPoint,
@@ -168,8 +168,10 @@ export const GrafanaReceiverForm = ({ contactPoint, readOnly = false, editMode }
'Loading OnCall integration failed'
)}
>
Grafana OnCall plugin has been enabled in your Grafana instances but it is not reachable. Please check the
plugin configuration
<Trans i18nKey="alerting.grafana-receiver-form.body-loading-on-call-integration-failed">
Grafana OnCall plugin has been enabled in your Grafana instances but it is not reachable. Please check the
plugin configuration
</Trans>
</Alert>
)}
@@ -129,14 +129,20 @@ export function ReceiverForm<R extends ChannelValues>({
<FormProvider {...formAPI}>
{showDefaultRouteWarning && (
<Alert severity="warning" title={t('alerting.receiver-form.title-attention', 'Attention')}>
Because there is no default policy configured yet, this contact point will automatically be set as default.
<Trans i18nKey="alerting.receiver-form.body-attention">
Because there is no default policy configured yet, this contact point will automatically be set as default.
</Trans>
</Alert>
)}
<form onSubmit={handleSubmit(submitCallback, onInvalid)} className={styles.wrapper}>
<Stack justifyContent="space-between" alignItems="center">
<h2 className={styles.heading}>
{!isEditable ? 'Contact point' : initialValues ? 'Update contact point' : 'Create contact point'}
{!isEditable
? t('alerting.receiver-form.contact-point', 'Contact point')
: initialValues
? t('alerting.receiver-form.contact-point-update', 'Update contact point')
: t('alerting.receiver-form.contact-point-create', 'Create contact point')}
</h2>
{canManagePermissions && contactPointId && (
<ManagePermissions
@@ -86,15 +86,19 @@ export const TestContactPointModal = ({ isOpen, onDismiss, onTest }: Props) => {
<form onSubmit={formMethods.handleSubmit(onSubmit)}>
{notificationType === NotificationType.predefined && (
<div className={styles.section}>
You will send a test notification that uses a predefined alert. If you have defined a custom template or
message, for better results switch to <strong>custom</strong> notification message, from above.
<Trans i18nKey="alerting.test-contact-point-modal.predefined-notification-message">
You will send a test notification that uses a predefined alert. If you have defined a custom template or
message, for better results switch to <strong>custom</strong> notification message, from above.
</Trans>
</div>
)}
{notificationType === NotificationType.custom && (
<>
<div className={styles.section}>
You will send a test notification that uses the annotations defined below. This is a good option if you
use custom templates and messages.
<Trans i18nKey="alerting.test-contact-point-modal.custom-notification-message">
You will send a test notification that uses the annotations defined below. This is a good option if
you use custom templates and messages.
</Trans>
</div>
<div className={styles.section}>
<AnnotationsStep />
@@ -29,6 +29,7 @@ export const SubformArrayField = ({ option, pathPrefix, errors, defaultValues, r
<div className={styles.wrapper}>
<CollapsibleSection
className={styles.collapsibleSection}
// eslint-disable-next-line @grafana/no-untranslated-strings
label={`${option.label} (${fields.length})`}
description={option.description}
>
@@ -181,9 +181,16 @@ const AnnotationsStep = () => {
{...register(`annotations.${index}.value`)}
placeholder={
isUrl
? 'https://'
: (annotationField.key && `Enter a ${annotationField.key}...`) ||
'Enter custom annotation content...'
? // eslint-disable-next-line @grafana/no-untranslated-strings
'https://'
: (annotationField.key &&
t('alerting.annotations-step.placeholder-value-input', 'Enter a {{key}}...', {
key: annotationField.key,
})) ||
t(
'alerting.annotations-step.placeholder-value-input-default',
'Enter custom annotation content...'
)
}
defaultValue={annotationField.value}
/>
@@ -23,7 +23,11 @@ export function CloudAlertPreview({ preview }: CloudAlertPreviewProps) {
<div>
<Trans i18nKey="alerting.cloud-alert-preview.alerts-preview">Alerts preview</Trans>
</div>
<span>Preview based on the result of running the query for this moment.</span>
<span>
<Trans i18nKey="alerting.cloud-alert-preview.running-query-preview">
Preview based on the result of running the query for this moment.
</Trans>
</span>
</caption>
<thead>
<tr>
@@ -1,5 +1,6 @@
import { Button, Stack } from '@grafana/ui';
import { t } from '../../../../../core/internationalization';
import { formatPrometheusDuration, safeParsePrometheusDuration } from '../../utils/time';
interface Props {
@@ -42,7 +43,7 @@ export function DurationQuickPick({ selectedDuration, groupEvaluationInterval, o
onSelect(duration);
}}
>
{duration === '0s' ? 'None' : duration}
{duration === '0s' ? t('alerting.duration-quick-pick.none', 'None') : duration}
</Button>
))}
</Stack>
@@ -62,8 +62,19 @@ export const ExpressionEditor = ({
const dsi = getDataSourceSrv().getInstanceSettings(dataSourceName);
if (error || !dataSource || !dataSource?.components?.QueryEditor || !dsi) {
const errorMessage = error?.message || 'Data source plugin does not export any Query Editor component';
return <div>Could not load query editor due to: {errorMessage}</div>;
const errorMessage =
error?.message ||
t(
'alerting.expression-editor.error-no-component',
'Data source plugin does not export any Query Editor component'
);
return (
<div>
<Trans i18nKey="alerting.expression-editor.could-not-load-editor">
Could not load query editor due to: {{ errorMessage }}
</Trans>
</div>
);
}
const previewLoaded = alertPreview?.data.state === LoadingState.Done;
@@ -4,7 +4,7 @@ import { useFormContext } from 'react-hook-form';
import { GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Icon, RadioButtonGroup, Stack, Text, useStyles2 } from '@grafana/ui';
import { RadioButtonGroup, Stack, Text, TextLink, useStyles2 } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types';
@@ -99,7 +99,9 @@ export const NotificationsStep = ({ alertUid }: NotificationsStepProps) => {
) : (
shouldAllowSimplifiedRouting && (
<Text variant="bodySmall" color="secondary">
Select who should receive a notification when an alert rule fires.
<Trans i18nKey="alerting.notifications-step.recipient-notification-fires">
Select who should receive a notification when an alert rule fires.
</Trans>
</Text>
)
)}
@@ -245,21 +247,24 @@ function NeedHelpInfoForNotificationPolicy() {
contentText={
<Stack gap={1} direction="column">
<Stack direction="column" gap={0}>
Firing alert instances are routed to notification policies based on matching labels. The default
notification policy matches all alert instances.
<Trans i18nKey="alerting.need-help-info-for-notification-policy.notification-policies">
Firing alert instances are routed to notification policies based on matching labels. The default
notification policy matches all alert instances.
</Trans>
</Stack>
<Stack direction="column" gap={0}>
Custom labels change the way your notifications are routed. First, add labels to your alert rule and then
connect them to your notification policy by adding label matchers.
<a
<Trans i18nKey="alerting.need-help-info-for-notification-policy.custom-labels">
Custom labels change the way your notifications are routed. First, add labels to your alert rule and then
connect them to your notification policy by adding label matchers.
</Trans>
<TextLink
href={`https://grafana.com/docs/grafana/latest/alerting/fundamentals/notifications/notification-policies/`}
target="_blank"
rel="noreferrer"
external
>
<Text color="link">
Read about notification policies. <Icon name="external-link-alt" />
</Text>
</a>
<Trans i18nKey="alerting.need-help-info-for-notification-policy.read-more">
Read about notification policies.
</Trans>
</TextLink>
</Stack>
</Stack>
}
@@ -273,13 +278,19 @@ function NeedHelpInfoForContactpoint() {
<NeedHelpInfo
contentText={
<>
Select a contact point to notify all recipients in it.
<Trans i18nKey="alerting.need-help-info-for-contactpoint.select-contact-point">
Select a contact point to notify all recipients in it.
</Trans>
<br />
Muting, grouping, and timings options allow you to customize how notifications are sent.
<Trans i18nKey="alerting.need-help-info-for-contactpoint.customize-notifications">
Muting, grouping, and timings options allow you to customize how notifications are sent.
</Trans>
<br />
<br />
Alternatively, toggle the <b>Advanced options</b> button to route notifications using notification policies
for greater flexibility.
<Trans i18nKey="alerting.need-help-info-for-contactpoint.notification-policies">
Alternatively, toggle the <b>Advanced options</b> button to route notifications using notification policies
for greater flexibility.
</Trans>
</>
}
externalLink="https://grafana.com/docs/grafana/latest/alerting/fundamentals/notifications/"
@@ -300,8 +311,14 @@ export const RoutingOptionDescription = ({ manualRouting }: NotificationsStepDes
<Stack alignItems="center">
<Text variant="bodySmall" color="secondary">
{manualRouting
? 'Notifications for firing alerts are routed to a selected contact point.'
: 'Notifications for firing alerts are routed to contact points based on matching labels and the notification policy tree.'}
? t(
'alerting.routing-option-description.manual',
'Notifications for firing alerts are routed to a selected contact point.'
)
: t(
'alerting.routing-option-description.matching-labels',
'Notifications for firing alerts are routed to contact points based on matching labels and the notification policy tree.'
)}
</Text>
{manualRouting ? <NeedHelpInfoForContactpoint /> : <NeedHelpInfoForNotificationPolicy />}
</Stack>
@@ -46,7 +46,9 @@ export function PreviewRule(): React.ReactElement | null {
title={t('alerting.preview-rule.title-preview-is-not-available', 'Preview is not available')}
severity="warning"
>
Cannot display the query preview. Some of the data sources used in the queries are not available.
<Trans i18nKey="alerting.preview-rule.body-preview-is-not-available">
Cannot display the query preview. Some of the data sources used in the queries are not available.
</Trans>
</Alert>
)}
</Stack>
@@ -4,6 +4,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
import { Field, useStyles2 } from '@grafana/ui';
import { t } from '../../../../../../core/internationalization';
import { RuleFormType, RuleFormValues } from '../../../types/rule-form';
import { CloudRulesSourcePicker } from '../CloudRulesSourcePicker';
@@ -27,7 +28,11 @@ export const CloudDataSourceSelector = ({ disabled, onChangeCloudDatasource }: C
{(ruleFormType === RuleFormType.cloudAlerting || ruleFormType === RuleFormType.cloudRecording) && (
<Field
className={styles.formInput}
label={disabled ? 'Data source' : 'Select data source'}
label={
disabled
? t('alerting.cloud-data-source-selector.label-disabled', 'Data source')
: t('alerting.cloud-data-source-selector.label', 'Select data source')
}
error={errors.dataSourceName?.message}
invalid={!!errors.dataSourceName?.message}
>
@@ -103,7 +103,13 @@ export const SimpleConditionEditor = ({
/>
</InlineField>
)}
<InlineField label={simpleCondition.whenField ? 'OF QUERY' : 'WHEN QUERY'}>
<InlineField
label={
simpleCondition.whenField
? t('alerting.simple-condition-editor.label-of-query', 'OF QUERY')
: t('alerting.simple-condition-editor.label-when-query', 'WHEN QUERY')
}
>
<Stack direction="row" gap={1} alignItems="center">
<ThresholdSelect onChange={onEvalFunctionChange} value={thresholdFunction} />
{isRange ? (
@@ -7,6 +7,8 @@ import { Page } from 'app/core/components/Page/Page';
import { PageNotFound } from 'app/core/components/PageNotFound/PageNotFound';
import { useDispatch, useSelector } from 'app/types';
import { t } from '../../core/internationalization';
import { ProviderConfigForm } from './ProviderConfigForm';
import { UIMap } from './constants';
import { loadProviders } from './state/actions';
@@ -59,7 +61,11 @@ export const ProviderConfigPage = () => {
<Stack gap={2} alignItems="center">
<Text variant={'h1'}>{title}</Text>
<Badge
text={config.settings.enabled ? 'Enabled' : 'Not enabled'}
text={
config.settings.enabled
? t('auth-config.provider-config-page.text-badge-enabled', 'Enabled')
: t('auth-config.provider-config-page.text-badge-not-enabled', 'Not enabled')
}
color={config.settings.enabled ? 'green' : 'blue'}
icon={config.settings.enabled ? 'check' : undefined}
/>
@@ -1,6 +1,7 @@
import { isIconName } from '@grafana/data';
import { Badge, Card, Icon } from '@grafana/ui';
import { t } from '../../../core/internationalization';
import { UIMap } from '../constants';
import { getProviderUrl } from '../utils/url';
@@ -26,7 +27,14 @@ export function ProviderCard({ providerId, enabled, configPath, authType, onClic
</Card.Figure>
)}
<Card.Actions>
<Badge text={enabled ? 'Enabled' : 'Not enabled'} color={enabled ? 'green' : 'blue'} />
<Badge
text={
enabled
? t('auth-config.provider-card.text-badge-enabled', 'Enabled')
: t('auth-config.provider-card.text-badge-not-enabled', 'Not enabled')
}
color={enabled ? 'green' : 'blue'}
/>
</Card.Actions>
</Card>
);
@@ -1,7 +1,7 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Modal, Icon, Button } from '@grafana/ui';
import { useStyles2, Modal, Icon, Button, TextLink } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { type CardGridItem } from '../CardGrid';
@@ -72,16 +72,11 @@ export function NoAccessModal({ item, isOpen, onDismiss }: NoAccessModalProps) {
<div>
{item.description && <div className={styles.description}>{item.description}</div>}
<div>
Links
<Trans i18nKey="connections.no-access-modal.links">Links</Trans>
<br />
<a
href={`https://grafana.com/grafana/plugins/${item.id}`}
title={`${item.name} on Grafana.com`}
target="_blank"
rel="noopener noreferrer"
>
<TextLink href={`https://grafana.com/grafana/plugins/${item.id}`} external>
{item.name}
</a>
</TextLink>
</div>
</div>
<div className={styles.bottomSection}>
@@ -180,7 +180,9 @@ export function HelpWizard({ panel, plugin, onClose }: Props) {
<Field
label={t('dashboard.help-wizard.label-support-snapshot', 'Support snapshot')}
description={`Panel: ${panelTitle}`}
description={t('dashboard.help-wizard.description-support-snapshot', 'Panel: {{panelTitle}}', {
panelTitle,
})}
>
<Stack>
<Button icon="download-alt" onClick={service.onDownloadDashboard}>
@@ -145,7 +145,10 @@ export function renderSearchHits(
<div key="search results">
<OptionsPaneCategory
id="Found options"
title={`Matched ${optionHits.length}/${totalCount} options`}
title={t('dashboard.options-pane-options.title-matched', 'Matched {{count}}/{{totalCount}} options', {
count: optionHits.length,
totalCount,
})}
key="Normal options"
forceOpen={true}
>
@@ -53,12 +53,20 @@ export const VisualizationButton = ({ panel }: Props) => {
{plugin.meta.name}
</ToolbarButton>
<ToolbarButton
tooltip={isPanelOptionsVisible ? 'Close options pane' : 'Show options pane'}
tooltip={
isPanelOptionsVisible
? t('dashboard.visualization-button.tooltip-close', 'Close options pane')
: t('dashboard.visualization-button.tooltip-show', 'Show options pane')
}
icon={isPanelOptionsVisible ? 'angle-right' : 'angle-left'}
onClick={onToggleOptionsPane}
variant="canvas"
data-testid={selectors.components.PanelEditor.toggleVizOptions}
aria-label={isPanelOptionsVisible ? 'Close options pane' : 'Show options pane'}
aria-label={
isPanelOptionsVisible
? t('dashboard.visualization-button.aria-label-close', 'Close options pane')
: t('dashboard.visualization-button.aria-label-show', 'Show options pane')
}
/>
</ButtonGroup>
</div>
@@ -11,6 +11,7 @@ import { ButtonLinkProps } from '@grafana/ui/internal';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { DashboardSearchItem } from 'app/features/search/types';
import { t } from '../../../../core/internationalization';
import { getLinkSrv } from '../../../panel/panellinks/link_srv';
interface Props {
@@ -45,7 +46,11 @@ function DashboardLinksMenu({ dashboardUID, link }: DashboardLinksMenuProps) {
key={`dashlinks-dropdown-item-${resolvedLink.uid}-${index}`}
label={resolvedLink.title}
testId={selectors.components.DashboardLinks.link}
aria-label={`${resolvedLink.title} dashboard`}
aria-label={t(
'dashboard.dashboard-links-menu.aria-label-dashboard-name',
'{{dashboardName}} dashboard',
{ dashboardName: resolvedLink.title }
)}
/>
);
})}
@@ -215,6 +215,7 @@ export const TransformationOperationRow = ({
<QueryOperationRow
id={id}
index={index}
// eslint-disable-next-line @grafana/no-untranslated-strings
title={`${index + 1} - ${uiConfig.name}`}
draggable
actions={renderActions}
@@ -1,9 +1,9 @@
import { DataSourceSettings } from '@grafana/data';
import { GrafanaEdition } from '@grafana/data/internal';
import { Alert } from '@grafana/ui';
import { Alert, TextLink } from '@grafana/ui';
import { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';
import { config } from 'app/core/config';
import { t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
const LOCAL_STORAGE_KEY = 'datasources.settings.cloudInfoBox.isDismissed';
@@ -46,28 +46,26 @@ export function CloudInfoBox({ dataSource }: Props) {
}
return (
<Alert
title={`Configure your ${mainDS} data source below`}
title={t('datasources.cloud-info-box.title-alert', 'Configure your {{mainDS}} data source below', {
mainDS,
})}
severity="info"
bottomSpacing={4}
onRemove={() => {
onDismiss(true);
}}
>
Or skip the effort and get {mainDS} (and {extraDS}) as fully-managed, scalable, and hosted data sources from
Grafana Labs with the{' '}
<a
className="external-link"
href={`https://grafana.com/signup/cloud/connect-account?src=grafana-oss&cnt=${dataSource.type}-settings`}
target="_blank"
rel="noreferrer"
title={t(
'datasources.cloud-info-box.title-includes-active-metrics-storage',
'The free plan includes 10k active metrics and 50gb storage.'
)}
>
free-forever Grafana Cloud plan
</a>
.
<Trans i18nKey="datasources.cloud-info-box.body-alert">
Or skip the effort and get {{ mainDS }} (and {{ extraDS }}) as fully-managed, scalable, and hosted data
sources from Grafana Labs with the{' '}
<TextLink
href={`https://grafana.com/signup/cloud/connect-account?src=grafana-oss&cnt=${dataSource.type}-settings`}
external
>
free-forever Grafana Cloud plan
</TextLink>
.
</Trans>
</Alert>
);
}}
@@ -4,6 +4,8 @@ import { DataSourcePluginMeta, GrafanaTheme2 } from '@grafana/data';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { Card, LinkButton, PluginSignatureBadge, useStyles2 } from '@grafana/ui';
import { t } from '../../../core/internationalization';
export type Props = {
dataSourcePlugin: DataSourcePluginMeta;
onClick: () => void;
@@ -45,7 +47,11 @@ export function DataSourceTypeCard({ onClick, dataSourcePlugin }: Props) {
<Card.Actions className={styles.actions}>
{learnMoreLink && (
<LinkButton
aria-label={`${dataSourcePlugin.name}, learn more.`}
aria-label={t(
'datasources.data-source-type-card.aria-label-learn-more',
'{{dataSourcePluginName}}, learn more.',
{ dataSourcePluginName: dataSourcePlugin.name }
)}
href={`${learnMoreLink.url}?utm_source=grafana_add_ds`}
onClick={(e) => e.stopPropagation()}
rel="noopener"
@@ -1,7 +1,7 @@
import { locationUtil } from '@grafana/data';
import { LinkButton, ButtonVariant } from '@grafana/ui';
import { contextSrv } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants';
import { AccessControlAction } from 'app/types';
@@ -19,7 +19,14 @@ export function AddNewDataSourceButton({ variant, onClick }: AddNewDataSourceBut
variant={variant || 'primary'}
href={newDataSourceURL}
disabled={!hasCreateRights}
tooltip={!hasCreateRights ? 'You do not have permission to configure new data sources' : undefined}
tooltip={
!hasCreateRights
? t(
'datasources.add-new-data-source-button.tooltip-no-permission',
'You do not have permission to configure new data sources'
)
: undefined
}
onClick={onClick}
target="_blank"
>
@@ -1,6 +1,8 @@
import { Badge } from '@grafana/ui';
import { PageInfoItem } from 'app/core/components/Page/types';
import { t } from '../../../core/internationalization';
type DataSourceInfo = {
dataSourcePluginName: string;
alertingSupported: boolean;
@@ -18,7 +20,14 @@ export const useDataSourceInfo = (dataSourceInfo: DataSourceInfo): PageInfoItem[
info.push({
label: 'Alerting',
value: (
<Badge color={alertingEnabled ? 'green' : 'red'} text={alertingEnabled ? 'Supported' : 'Not supported'}></Badge>
<Badge
color={alertingEnabled ? 'green' : 'red'}
text={
alertingEnabled
? t('datasources.use-data-source-info.badge-text-supported', 'Supported')
: t('datasources.use-data-source-info.badge-text-not-supported', 'Not supported')
}
></Badge>
),
});
@@ -115,7 +115,7 @@ describe('ThresholdsEditor', () => {
expect(baseThreshold).toBeDisabled();
expect(baseThreshold).toHaveValue('Base');
await userEvent.click(screen.getByRole('button', { name: 'Remove Threshold 1' }));
await userEvent.click(screen.getByRole('button', { name: 'Remove threshold 1' }));
expect(screen.getAllByRole('spinbutton')).toHaveLength(1);
@@ -129,7 +129,7 @@ describe('ThresholdsEditor', () => {
expect(baseThreshold).toBeDisabled();
expect(baseThreshold).toHaveValue('Base');
await userEvent.click(screen.getByRole('button', { name: 'Remove Threshold 1' }));
await userEvent.click(screen.getByRole('button', { name: 'Remove threshold 1' }));
expect(screen.queryAllByRole('spinbutton')).toHaveLength(0);
@@ -146,8 +146,11 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
renderInput(threshold: ThresholdWithKey, styles: ThresholdStyles, idx: number) {
const isPercent = this.props.thresholds.mode === ThresholdsMode.Percentage;
const thresholdNumber = idx + 1;
const ariaLabel = `Threshold ${idx + 1}`;
const ariaLabel = t('dimensions.thresholds-editor.aria-label-threshold', 'Threshold {{thresholdNumber}}', {
thresholdNumber,
});
if (!isFinite(threshold.value)) {
return (
<Input
@@ -187,7 +190,10 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
enableNamedColors={true}
/>
</div>
{isPercent && <div className={styles.percentIcon}>%</div>}
{isPercent && (
// eslint-disable-next-line @grafana/no-untranslated-strings
<div className={styles.percentIcon}>%</div>
)}
</div>
}
suffix={
@@ -195,7 +201,9 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
className={styles.trashIcon}
name="trash-alt"
onClick={() => this.onRemoveThreshold(threshold)}
tooltip={`Remove ${ariaLabel}`}
tooltip={t('dimensions.threshold-editor.tooltip-remove-threshold', 'Remove threshold {{thresholdNumber}}', {
thresholdNumber,
})}
/>
}
/>
@@ -6,6 +6,8 @@ import { GrafanaTheme2, store } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { useStyles2, PanelContainer, ScrollContainer } from '@grafana/ui';
import { t } from '../../../core/internationalization';
import { ContentOutlineItemContextProps, useContentOutlineContext } from './ContentOutlineContext';
import { ContentOutlineItemButton } from './ContentOutlineItemButton';
@@ -158,7 +160,11 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
<div className={styles.content}>
<ContentOutlineItemButton
icon={'arrow-from-right'}
tooltip={contentOutlineExpanded ? 'Collapse outline' : 'Expand outline'}
tooltip={
contentOutlineExpanded
? t('explore.content-outline.tooltip-collapse-outline', 'Collapse outline')
: t('explore.content-outline.tooltip-expand-outline', 'Expand outline')
}
tooltipPlacement={contentOutlineExpanded ? 'right' : 'bottom'}
onClick={toggle}
className={cx(styles.toggleContentOutlineButton, {
@@ -139,8 +139,10 @@ export const CorrelationTransformationAddModal = ({
className={css({ width: '700px' })}
>
<p>
A transformation extracts variables out of a single field. These variables will be available along with your
field variables.
<Trans i18nKey="explore.correlation-transformation-add-modal.body">
A transformation extracts variables out of a single field. These variables will be available along with your
field variables.
</Trans>
</p>
<Field label={t('explore.correlation-transformation-add-modal.label-field', 'Field')}>
<Controller
@@ -203,7 +205,7 @@ export const CorrelationTransformationAddModal = ({
tooltipText={formFieldsVis.expressionDetails.helpText}
/>
) : (
'Expression'
t('explore.correlation-transformation-add-modal.label-expression-without-tooltip', 'Expression')
)
}
htmlFor={`${id}-expression`}
@@ -221,7 +223,7 @@ export const CorrelationTransformationAddModal = ({
tooltipText={formFieldsVis.mapValueDetails.helpText}
/>
) : (
'Variable name'
t('explore.correlation-transformation-add-modal.label-variable-name-without-tooltip', 'Variable name')
)
}
htmlFor={`${id}-mapValue`}
@@ -231,7 +233,9 @@ export const CorrelationTransformationAddModal = ({
)}
{Object.entries(transformationVars).length > 0 && (
<>
This transformation will add the following variables:
<Trans i18nKey="explore.correlation-transformation-add-modal.added-variables">
This transformation will add the following variables:
</Trans>
<pre>
{Object.entries(transformationVars).map((entry) => {
return `\$\{${entry[0]}\} = ${entry[1]?.value}\n`;
@@ -246,7 +250,9 @@ export const CorrelationTransformationAddModal = ({
<Trans i18nKey="explore.correlation-transformation-add-modal.cancel">Cancel</Trans>
</Button>
<Button variant="primary" onClick={() => onSave(getValues())} disabled={!validToSave}>
{transformationToEdit ? 'Edit transformation' : 'Add transformation to correlation'}
{transformationToEdit
? t('explore.correlation-transformation-add-modal.edit-transformation', 'Edit transformation')
: t('explore.correlation-transformation-add-modal.add-transformation', 'Add transformation to correlation')}
</Button>
</Modal.ButtonRow>
</Modal>
@@ -108,6 +108,7 @@ export function ExploreRunQueryButton({
runQuery(pane[0]);
onClick?.();
}}
// eslint-disable-next-line @grafana/no-untranslated-strings
label={`${paneLabel}: ${buttonText.translation}`}
disabled={isInvalid || pane[0] === undefined}
/>
@@ -1,5 +1,7 @@
import { useTheme2 } from '@grafana/ui';
import { t } from '../../../core/internationalization';
import { getLogsFieldsStyles } from './LogsTableActiveFields';
import { LogsTableEmptyFields } from './LogsTableEmptyFields';
import { LogsTableNavField } from './LogsTableNavField';
@@ -43,7 +45,11 @@ export const LogsTableAvailableFields = (props: {
<div
key={labelName}
className={styles.wrap}
title={`${labelName} appears in ${labels[labelName]?.percentOfLinesWithLabel}% of log lines`}
title={t(
'explore.logs-table-available-fields.title-label-percentage',
'{{labelName}} appears in {{percentage}}% of log lines',
{ labelName, percentage: labels[labelName]?.percentOfLinesWithLabel }
)}
>
<LogsTableNavField
showCount={true}
@@ -1,5 +1,7 @@
import { Tooltip, ToolbarButton } from '@grafana/ui';
import { t } from '../../core/internationalization';
interface TimeSyncButtonProps {
isSynced: boolean;
onClick: () => void;
@@ -19,7 +21,11 @@ export function TimeSyncButton(props: TimeSyncButtonProps) {
<ToolbarButton
icon="link"
variant={isSynced ? 'active' : 'canvas'}
aria-label={isSynced ? 'Synced times' : 'Unsynced times'}
aria-label={
isSynced
? t('explore.time-sync-button.aria-label-synced', 'Synced times')
: t('explore.time-sync-button.aria-label-unsynced', 'Unsynced times')
}
onClick={onClick}
/>
</Tooltip>
@@ -88,7 +88,11 @@ export default function TracePageActions(props: TracePageActionsProps) {
<ActionButton
onClick={copyTraceId}
ariaLabel={'Copy Trace ID'}
label={copyTraceIdClicked ? 'Copied!' : 'Trace ID'}
label={
copyTraceIdClicked
? t('explore.trace-page-actions.label-copied', 'Copied!')
: t('explore.trace-page-actions.label-trace-id', 'Trace ID')
}
icon={'copy'}
/>
<ActionButton
@@ -6,6 +6,8 @@ import { PanelProps, PanelPlugin, PluginType, PanelPluginMeta } from '@grafana/d
import { Alert } from '@grafana/ui';
import { AppNotificationSeverity } from 'app/types';
import { t, Trans } from '../../../core/internationalization';
interface Props {
title: string;
text?: ReactNode;
@@ -36,12 +38,17 @@ export function getPanelPluginLoadError(meta: PanelPluginMeta, err: unknown): Pa
const LoadError = class LoadError extends PureComponent<PanelProps> {
render() {
const text = (
<>
<Trans i18nKey="panel.panel-plugin-error.text-load-error">
Check the server startup logs for more information. <br />
If this plugin was loaded from Git, then make sure it was compiled.
</>
</Trans>
);
return (
<PanelPluginError
title={t('panel.panel-plugin-error.title-load-error', 'Error loading: {{panelId}}', { panelId: meta.id })}
text={text}
/>
);
return <PanelPluginError title={`Error loading: ${meta.id}`} text={text} />;
}
};
const plugin = new PanelPlugin(LoadError);
@@ -53,7 +60,11 @@ export function getPanelPluginLoadError(meta: PanelPluginMeta, err: unknown): Pa
export function getPanelPluginNotFound(id: string, silent?: boolean): PanelPlugin {
const NotFound = class NotFound extends PureComponent<PanelProps> {
render() {
return <PanelPluginError title={`Panel plugin not found: ${id}`} />;
return (
<PanelPluginError
title={t('panel.panel-plugin-error.title-not-found', 'Panel plugin not found: {{id}}', { id })}
/>
);
}
};
@@ -50,7 +50,9 @@ const PanelTypeCardComponent = ({
aria-label={selectors.components.PluginVisualization.item(plugin.name)}
data-testid={selectors.components.PluginVisualization.item(plugin.name)}
onClick={isDisabled ? undefined : onClick}
title={isCurrent ? 'Click again to close this section' : plugin.name}
title={
isCurrent ? t('panel.panel-type-card.title-click-to-close', 'Click again to close this section') : plugin.name
}
>
<img className={cx(styles.img, { [styles.disabled]: isDisabled })} src={plugin.info.logos.small} alt="" />
@@ -4,7 +4,7 @@ import * as React from 'react';
import { DataSourcePluginMeta } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Button } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { ROUTES } from 'app/features/connections/constants';
import { addDataSource } from 'app/features/datasources/state';
import { useDispatch } from 'app/types';
@@ -39,7 +39,12 @@ export function GetStartedWithDataSource({ plugin }: Props): React.ReactElement
onClick={onAddDataSource}
disabled={disabledButton}
title={
disabledButton ? "The plugin isn't usable yet, it may take some time to complete the installation." : undefined
disabledButton
? t(
'plugins.get-started-with-data-source.title-button-disabled',
"The plugin isn't usable yet, it may take some time to complete the installation."
)
: undefined
}
>
<Trans i18nKey="plugins.get-started-with-data-source.add-new-data-source">Add new data source</Trans>
@@ -6,6 +6,7 @@ import { locationService, reportInteraction } from '@grafana/runtime';
import { Badge, Icon, Stack, useStyles2 } from '@grafana/ui';
import { SkeletonComponent, attachSkeleton } from '@grafana/ui/unstable';
import { t, Trans } from '../../../../core/internationalization';
import { CatalogPlugin, PluginIconName } from '../types';
import { PluginListItemBadges } from './PluginListItemBadges';
@@ -35,11 +36,22 @@ function PluginListItemComponent({ plugin, pathName }: Props) {
<PluginLogo src={plugin.info.logos.small} className={styles.pluginLogo} height={LOGO_SIZE} alt="" />
<h2 className={cx(styles.name, 'plugin-name')}>{plugin.name}</h2>
<div className={cx(styles.content, 'plugin-content')}>
<p>By {plugin.orgName}</p>
<p>
<Trans i18nKey="plugins.plugin-list-item.label-author" values={{ author: plugin.orgName }}>
By {'{{author}}'}
</Trans>
</p>
<PluginListItemBadges plugin={plugin} />
</div>
<div className={styles.pluginType}>
{plugin.type && <Icon name={PluginIconName[plugin.type]} title={`${plugin.type} plugin`} />}
{plugin.type && (
<Icon
name={PluginIconName[plugin.type]}
title={t('plugins.plugin-list-item.title-icon-plugin-type', '{{pluginType}} plugin', {
pluginType: plugin.type,
})}
/>
)}
</div>
</a>
);
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import { dateTimeFormat, GrafanaTheme2, TimeZone } from '@grafana/data';
import { DeleteButton, Icon, Tooltip, useStyles2, useTheme2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { ApiKey } from 'app/types';
interface Props {
@@ -49,7 +49,11 @@ export const ServiceAccountTokensTable = ({ tokens, timeZone, tokenActionsDisabl
<td className="width-1 text-center">{key.isRevoked && <TokenRevoked />}</td>
<td>
<DeleteButton
aria-label={`Delete service account token ${key.name}`}
aria-label={t(
'serviceaccounts.service-account-tokens-table.aria-label-delete-button',
'Delete service account token {{key}}',
{ key: key.name }
)}
size="sm"
onConfirm={() => onDelete(key)}
disabled={tokenActionsDisabled}
@@ -87,7 +91,7 @@ const TokenRevoked = () => {
const styles = useStyles2(getStyles);
return (
<span className={styles.hasExpired}>
Revoked
<Trans i18nKey="serviceaccounts.token-revoked.revoked-label">Revoked</Trans>
<span className={styles.tooltipContainer}>
<Tooltip content="This token has been publicly exposed. Please rotate this token">
<Icon name="exclamation-triangle" className={styles.toolTipIcon} />
@@ -121,7 +125,7 @@ const TokenExpiration = ({ timeZone, token }: TokenExpirationProps) => {
if (token.hasExpired) {
return (
<span className={styles.hasExpired}>
Expired
<Trans i18nKey="serviceaccounts.token-expiration.expired-label">Expired</Trans>
<span className={styles.tooltipContainer}>
<Tooltip content="This token has expired">
<Icon name="exclamation-triangle" className={styles.toolTipIcon} />
@@ -120,12 +120,19 @@ export const WindowOptionsEditor = (props: {
></RadioButtonGroup>
</InlineField>
<InlineField
label={window?.windowSizeMode === WindowSizeMode.Percentage ? 'Window size %' : 'Window size'}
label={
window?.windowSizeMode === WindowSizeMode.Percentage
? t('transformers.window-options-editor.label-window-size-percent', 'Window size %')
: t('transformers.window-options-editor.label-window-size', 'Window size')
}
labelWidth={LABEL_WIDTH}
tooltip={
window?.windowSizeMode === WindowSizeMode.Percentage
? 'Set the window size as a percentage of the total data'
: 'Window size'
? t(
'transformers.window-options-editor.tooltip-window-size-percent',
'Set the window size as a percentage of the total data'
)
: t('transformers.window-options-editor.tooltip-window-size', 'Window size')
}
>
<NumberInput
@@ -182,7 +182,11 @@ const DraggableFieldName = ({
size="md"
name={visible ? 'eye' : 'eye-slash'}
onClick={() => onToggleVisibility(fieldName, visible)}
tooltip={visible ? 'Disable' : 'Enable'}
tooltip={
visible
? t('transformers.draggable-field-name.tooltip-disable', 'Disable')
: t('transformers.draggable-field-name.tooltip-enable', 'Enable')
}
/>
<Text truncate={true} element="p" variant="bodySmall" weight="bold">
{fieldName}
@@ -120,7 +120,9 @@ export const extractFieldsTransformerEditor = ({
label="RegExp"
labelWidth={16}
interactive={true}
tooltip="Example: /(?<NewField>.*)/"
tooltip={t('transformers.extract-fields-transformer-editor.tooltip-regexp', 'Example: {{regexExample}}', {
regexExample: '/(?<NewField>.*)/',
})}
>
<Input
// eslint-disable-next-line @grafana/no-untranslated-strings
@@ -2,6 +2,7 @@ import { ReactElement } from 'react';
import { AdHocVariableFilter, DataSourceRef, SelectableValue } from '@grafana/data';
import { Icon, SegmentAsync } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getDatasourceSrv } from '../../../plugins/datasource_srv';
@@ -18,6 +19,15 @@ export const AdHocFilterKey = ({ datasource, onChange, disabled, filterKey, allF
const loadKeys = () => fetchFilterKeys(datasource, filterKey, allFilters);
const loadKeysWithRemove = () => fetchFilterKeysWithRemove(datasource, filterKey, allFilters);
const plusSegment: ReactElement = (
<span
className="gf-form-label query-part"
aria-label={t('variables.ad-hoc-filter-key.plus-segment.aria-label-add-filter', 'Add Filter')}
>
<Icon name="plus" />
</span>
);
if (filterKey === null) {
return (
<div className="gf-form" data-testid="AdHocFilterKey-add-key-wrapper">
@@ -51,12 +61,6 @@ export const AdHocFilterKey = ({ datasource, onChange, disabled, filterKey, allF
export const REMOVE_FILTER_KEY = '-- remove filter --';
const REMOVE_VALUE = { label: REMOVE_FILTER_KEY, value: REMOVE_FILTER_KEY };
const plusSegment: ReactElement = (
<span className="gf-form-label query-part" aria-label="Add Filter">
<Icon name="plus" />
</span>
);
const fetchFilterKeys = async (
datasource: DataSourceRef,
currentKey: string | null,
+223 -19
View File
@@ -1,5 +1,6 @@
{
"_comment": "The code is the source of truth for English phrases. They should be updated in the components directly, and additional plurals specified in this file.",
"{{pageStart}} - {{pageEnd}} of {{numPages}}": "{{pageStart}} - {{pageEnd}} of {{numPages}}",
"access-control": {
"add-permission": {
"built-in-aria-label": "Built-in role picker",
@@ -73,6 +74,8 @@
"deprecated": "Deprecated",
"ga": "GA"
},
"save-changes": "Save changes",
"saving": "Saving...",
"title-apply-feature-toggle-changes": "Apply feature toggle changes"
},
"admin-orgs-table": {
@@ -108,6 +111,8 @@
"title-white-labeling": "White labeling"
},
"feature-toggles": {
"restart-pending": "A restart is pending for your Grafana instance to apply the latest feature toggle changes",
"restart-required": "Saving feature toggle changes will prompt a restart of the instance, which may take a few minutes",
"sub-title": "View and edit feature toggles. Read more about feature toggles at <2>grafana.com</2>."
},
"get-enterprise": {
@@ -269,6 +274,7 @@
"ip-column": "IP address",
"last-seen-column": "Last seen",
"logged-on-column": "Logged on",
"now": "Now",
"title": "Sessions"
},
"users-create": {
@@ -322,16 +328,25 @@
"target-datasource-uid": "Target data source"
},
"alert-details": {
"button-see-rule": "See alert rule",
"button-see-source": "See source",
"manage-silences": "Manage silences",
"receivers-list": "Receivers: {{receivers}}",
"silence": "Silence"
},
"alert-group": {
"delivered-to": "Delivered to <2>{{name}}</2>",
"no-grouping": "No grouping"
},
"alert-group-alerts-table": {
"duration": "for {{time}}"
},
"alert-group-filter": {
"clear-filters": "Clear filters"
},
"alert-groups": {
"body-grafana-alerted-delivered": "Grafana is configured to send alerts to external alertmanagers only. No alerts are expected to be available here for the selected Alertmanager.",
"grouped-by": "Grouped by: {{labels}}",
"no-results": "No results.",
"text-loading-notifications": "Loading notifications",
"title-error-loading-notifications": "Error loading notifications",
@@ -354,6 +369,7 @@
"alert-instance-modal-selector": {
"add-alert-data-to-payload": "Add alert data to payload",
"placeholder-search-alert-rule": "Search alert rule",
"select-alert-rule": "Select an alert rule to get a list of available firing instances",
"text-loading-rule": "Loading rule...",
"text-loading-rules": "Loading rules...",
"title-search-alert-rule": "Search alert rule",
@@ -369,7 +385,9 @@
"placeholder-select": "Choose {{type}}"
},
"alert-labels": {
"aria-label-labels": "Labels"
"aria-label-labels": "Labels",
"common-labels-count_one": "+{{count}} common label",
"common-labels-count_other": "+{{count}} common labels"
},
"alert-manager-manual-routing": {
"label-muting-grouping-and-timings-optional": "Muting, grouping and timings (optional)",
@@ -420,7 +438,10 @@
"text-loading-alert-rules": "Loading alert rules"
},
"alert-state-filter": {
"suppressed-the-alert-has-been-silenced": "Suppressed: The alert has been silenced."
"active-the-alert-is-firing": "Active: The alert notification has been handled. The alert is still firing and continues to be managed.",
"notification-state": "Notification state",
"suppressed-the-alert-has-been-silenced": "Suppressed: The alert has been silenced.",
"unprocessed-the-alert-is-received": "Unprocessed: The alert is received but its notification has not been processed yet."
},
"alert-warning": {
"to-rule-list": "To rule list"
@@ -566,7 +587,8 @@
"get-annotations-section-description": {
"title-annotations": "Annotations"
},
"link-dashboard-and-panel": "Link dashboard and panel"
"link-dashboard-and-panel": "Link dashboard and panel",
"placeholder-value-input-default": "Enter custom annotation content..."
},
"central-alert-history": {
"details": {
@@ -620,7 +642,8 @@
"test": "Test"
},
"classic-condition-viewer": {
"of": "OF"
"of": "OF",
"when": "WHEN"
},
"clone-rule-button": {
"title-copy": "Copy"
@@ -634,18 +657,24 @@
"alerts-preview": "Alerts preview",
"info": "Info",
"labels": "Labels",
"running-query-preview": "Preview based on the result of running the query for this moment.",
"state": "State"
},
"cloud-common-channel-settings": {
"description-whether-notify-about-resolved-alerts": "Whether or not to notify about resolved alerts.",
"label-send-resolved": "Send resolved"
},
"cloud-data-source-selector": {
"label": "Select data source",
"label-disabled": "Data source"
},
"cloud-evaluation-behavior": {
"description-pending-period": "Period during which the threshold condition must be met to trigger an alert. Selecting \"None\" triggers the alert immediately once the condition is met.",
"label-pending-period": "Pending period",
"title-set-evaluation-behavior": "Set evaluation behavior"
},
"cloud-receiver-form": {
"body-info": "Note that empty string values will be replaced with global defaults where appropriate.",
"title-info": "Info"
},
"common": {
@@ -666,11 +695,17 @@
"restore": "Restore",
"return": "Return"
},
"contact-point-errors": {
"label-contact-point": "Contact Point › {{name}}"
},
"contact-point-header": {
"aria-label-more-actions": "More actions for contact point \"{{contactPointName}}\"",
"button-edit": "Edit",
"button-view": "View",
"export-label-export": "Export",
"label-delete": "Delete",
"label-manage-permissions": "Manage permissions"
"label-manage-permissions": "Manage permissions",
"tooltip-provisioned-contact-points": "Provisioned contact points cannot be edited in the UI"
},
"contact-point-selector": {
"aria-label-refresh-contact-points": "Refresh contact points",
@@ -833,6 +868,9 @@
"text-loading-notification-template": "Loading notification template",
"title-error-loading-notification-template": "Error loading notification template"
},
"duration-quick-pick": {
"none": "None"
},
"dynamic-table": {
"tooltip-collapse-row": "Collapse row",
"tooltip-expand-row": "Expand row"
@@ -877,6 +915,7 @@
"title-something-wrong-trying-fetch-group-details": "Something went wrong when trying to fetch group details"
},
"evaluation-interval-limit-exceeded": {
"body-minimum-interval": "A minimum evaluation interval of <1>{{minInterval}}</1> has been configured in Grafana.<3></3>Please contact the administrator to configure a lower interval.",
"title-global-evaluation-interval-limit-exceeded": "Global evaluation interval limit exceeded"
},
"existing-rule-editor": {
@@ -902,15 +941,19 @@
"tooltip-export-new-grafana-rule": "Export new grafana rule"
},
"expression": {
"not-supported": "Expression not supported: {{expression}}",
"title-expression-failed": "Expression failed",
"title-expression-warning": "Expression warning"
},
"expression-editor": {
"could-not-load-editor": "Could not load query editor due to: {{errorMessage}}",
"error-no-component": "Data source plugin does not export any Query Editor component",
"preview-alerts": "Preview alerts",
"there-firing-alerts-query": "There are no firing alerts for your query.",
"title-alerts-preview": "Alerts preview"
},
"expression-preview": {
"expression-not-supported": "Expression not supported: {{type}}",
"title-expression-failed": "Expression failed"
},
"expression-result": {
@@ -972,7 +1015,10 @@
"title-failed-to-fetch-notification-template": "Failed to fetch notification template"
},
"global-config-alert": {
"title-global-config-for-contact-points": "Global config for contact points"
"body": "For each external Alertmanager you can define global settings, like server addresses, usernames and password, for all the supported contact points.",
"edit-global-config": "Edit global config",
"title-global-config-for-contact-points": "Global config for contact points",
"view-global-config": "View global config"
},
"global-config-form": {
"save-global-config": "Save global config",
@@ -980,6 +1026,10 @@
"title-error-saving-receiver": "Error saving receiver"
},
"grafana-alertmanager-delivery-warning": {
"admin-hint-all": "To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your Administrator.",
"admin-hint-external": "To change your Alertmanager setup, go to the Alerting Admin page. If you do not have access, contact your Administrator.",
"configuration-changes-all": "Ensure you make configuration changes in the correct Alertmanagers; both internal and external. Changing one will not affect the others.",
"configuration-changes-external": "Grafana is configured to send alerts to external Alertmanagers only. Changing Grafana Alertmanager configuration will not affect delivery of your alerts.",
"title-grafana-alerts-delivered-alertmanager": "Grafana alerts are not delivered to Grafana Alertmanager",
"title-you-have-additional-alertmanagers-to-configure": "You have additional Alertmanagers to configure"
},
@@ -998,6 +1048,7 @@
"title-add-folder-and-labels": "Add folder and labels"
},
"grafana-modify-export": {
"body-invalid-rule-id": "The rule UID in the page URL is invalid. Please check the URL and try again.",
"title-invalid-rule-id": "Invalid rule ID"
},
"grafana-mute-timing-exporter-preview": {
@@ -1013,6 +1064,7 @@
"text-loading": "Loading...."
},
"grafana-receiver-form": {
"body-loading-on-call-integration-failed": "Grafana OnCall plugin has been enabled in your Grafana instances but it is not reachable. Please check the plugin configuration",
"text-loading-notifiers": "Loading notifiers...",
"title-loading-on-call-integration-failed": "Loading OnCall integration failed"
},
@@ -1064,7 +1116,9 @@
},
"group-by": {
"aria-label-group-by-label-keys": "Group by label keys",
"placeholder-group-by": "Group by"
"custom-group-by": "Custom group by",
"placeholder-group-by": "Group by",
"tooltip-group-by": "Group notifications using a different combination of labels. This option can help validate the grouping settings of your notification policies."
},
"group-details": {
"ds-features-error": "Error loading data source details",
@@ -1200,6 +1254,7 @@
},
"key-value-template-data-table": {
"arguments": "Arguments",
"description": "KeyValue is a set of key/value string pairs that represent labels and annotations.",
"keyvalue-methods": "Key-value methods",
"name": "Name",
"notes": "Notes",
@@ -1311,6 +1366,10 @@
"export": "Export"
}
},
"more-button": {
"aria-label": "More",
"button-text": "More"
},
"mute_timings": {
"error-loading": {
"description": "Could not load mute timings. Please try again later.",
@@ -1333,6 +1392,7 @@
},
"mute-timing-time-interval": {
"add-another-time-interval": "Add another time interval",
"description": "A time interval is a definition for a moment in time. All fields are lists, and at least one list element must be satisfied to match the field. If a field is left blank, any moment of time will match the field. For an instant of time to match a complete time interval, all fields must match. A mute timing can contain multiple time intervals.",
"description-dats-of-the-month": "The days of the month, 1:31, of a month. Negative values can be used to represent days which begin at the end of the month",
"description-months": "The months of the year in either numerical or the full calendar month",
"label-days-of-the-month": "Days of the month",
@@ -1384,16 +1444,24 @@
"need-help": "Need help?"
},
"need-help-info-for-contactpoint": {
"customize-notifications": "Muting, grouping, and timings options allow you to customize how notifications are sent.",
"notification-policies": "Alternatively, toggle the <1>Advanced options</1> button to route notifications using notification policies for greater flexibility.",
"select-contact-point": "Select a contact point to notify all recipients in it.",
"title-notify-by-selecting-a-contact-point": "Notify by selecting a contact point"
},
"need-help-info-for-notification-policy": {
"custom-labels": "Custom labels change the way your notifications are routed. First, add labels to your alert rule and then connect them to your notification policy by adding label matchers.",
"notification-policies": "Firing alert instances are routed to notification policies based on matching labels. The default notification policy matches all alert instances.",
"read-more": "Read about notification policies.",
"title-notification-routing": "Notification routing"
},
"new-rule-from-panel-button": {
"body-no-alerting-capable-query-found": "Cannot create alerts from this panel because no query to an alerting capable datasource is found.",
"new-alert-rule": "New alert rule",
"title-no-alerting-capable-query-found": "No alerting capable query found"
},
"no-alert-managers-available": {
"body-no-alertmanager-found": "We could not find any external Alertmanagers and you may not have access to the built-in Grafana Alertmanager.",
"title-no-alertmanager-found": "No Alertmanager found"
},
"notification-policies-filter": {
@@ -1462,18 +1530,21 @@
},
"notifications-step": {
"labels-better-manage-recording-rules": "Add labels to help you better manage your recording rules.",
"recipient": "Recipient"
"recipient": "Recipient",
"recipient-notification-fires": "Select who should receive a notification when an alert rule fires."
},
"option-customfield": {
"label-custom-template": "Custom template"
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "The selected Alertmanager no longer exists or you may not have permission to access it. You can select a different Alertmanager from the dropdown.",
"title-selected-alertmanager-not-found": "Selected Alertmanager not found."
},
"panel-alert-tab-content": {
"alert": {
"title-errors-loading-rules": "Errors loading rules"
},
"failed-to-load-error": "Failed to load Grafana rules state: {{error}}",
"text-loading-rules": "Loading rules...",
"title-dashboard-not-saved": "Dashboard not saved"
},
@@ -1485,6 +1556,10 @@
"reference": "Reference"
},
"policies": {
"aria-label-collapse": "Collapse",
"aria-label-expand": "Expand",
"aria-label-more": "more actions for policy",
"aria-label-more-default": "more actions for default policy",
"default-policy": {
"description": "All alert instances will be handled by the default policy if no other matching policies are found.",
"title": "Default policy",
@@ -1555,6 +1630,7 @@
"no-matchers": "No matchers"
},
"preview-rule": {
"body-preview-is-not-available": "Cannot display the query preview. Some of the data sources used in the queries are not available.",
"preview-alerts": "Preview alerts",
"title-preview-is-not-available": "Preview is not available"
},
@@ -1565,7 +1641,9 @@
"no-series": "No series"
},
"prom-duration-docs": {
"different-units": "Different units can be combined for more granularity.",
"example": "Example",
"explanation": "Prometheus duration format consist of a number followed by a time unit.",
"multiple-units-combined": "Multiple units combined",
"symbol": "Symbol",
"time-unit": "Time unit"
@@ -1598,6 +1676,9 @@
"query-options": {
"label-time-range": "Time Range"
},
"query-preview": {
"relative-time-range": "{{from}} to now"
},
"queryAndExpressionsStep": {
"disableAdvancedOptions": {
"text": "The selected queries and expressions cannot be converted to default. If you deactivate advanced options, your query and condition will be reset to default settings."
@@ -1607,6 +1688,10 @@
},
"receiver-form": {
"add-contact-point-integration": "Add contact point integration",
"body-attention": "Because there is no default policy configured yet, this contact point will automatically be set as default.",
"contact-point": "Contact point",
"contact-point-create": "Create contact point",
"contact-point-update": "Update contact point",
"label-name": "Name",
"name-placeholder-name": "Name",
"save-contact-point": "Save contact point",
@@ -1615,6 +1700,7 @@
"title-manage-contact-point-permissions": "Manage contact point permissions"
},
"receivers-section": {
"button-more": "More",
"new-menu": {
"label-export-all": "Export all"
}
@@ -1652,6 +1738,10 @@
"routing": {
"routing": "Routing"
},
"routing-option-description": {
"manual": "Notifications for firing alerts are routed to a selected contact point.",
"matching-labels": "Notifications for firing alerts are routed to contact points based on matching labels and the notification policy tree."
},
"routing-settings": {
"aria-label-group-by": "Group by",
"description-group-by": "Combine multiple alerts into a single notification by grouping them by the same label values. If empty, it is inherited from the default notification policy.",
@@ -2012,7 +2102,9 @@
"title-the-selected-alertmanager-has-no-configuration": "The selected Alertmanager has no configuration"
},
"simple-condition-editor": {
"label-when": "WHEN"
"label-of-query": "OF QUERY",
"label-when": "WHEN",
"label-when-query": "WHEN QUERY"
},
"simpleCondition": {
"alertCondition": "Alert condition"
@@ -2102,7 +2194,9 @@
"title-delete-template-group": "Delete template group"
},
"test-contact-point-modal": {
"custom-notification-message": "You will send a test notification that uses the annotations defined below. This is a good option if you use custom templates and messages.",
"notification-message": "Notification message",
"predefined-notification-message": "You will send a test notification that uses a predefined alert. If you have defined a custom template or message, for better results switch to <1>custom</1> notification message, from above.",
"send-test-notification": "Send test notification",
"title-test-contact-point": "Test contact point"
},
@@ -2149,6 +2243,8 @@
"label-export": "Export"
},
"use-delete-contact-point-modal": {
"delete-confirm": "Yes, delete contact point",
"deleting": "Deleting...",
"modal-element": {
"delete-contact-point": "Are you sure you want to delete this contact point?",
"deleting-contact-point-permanently-remove": "Deleting this contact point will permanently remove it.",
@@ -2286,6 +2382,10 @@
"configuration-required": "Configuration required",
"refer-documentation-configure-authentication": "Refer to the documentation on how to configure authentication"
},
"provider-card": {
"text-badge-enabled": "Enabled",
"text-badge-not-enabled": "Not enabled"
},
"provider-config-form": {
"additional-actions-menu": {
"label-reset-to-default-values": "Reset to default values"
@@ -2299,6 +2399,10 @@
"title-reset": "Reset",
"tooltip-more-actions": "More actions"
},
"provider-config-page": {
"text-badge-enabled": "Enabled",
"text-badge-not-enabled": "Not enabled"
},
"server-discovery-modal": {
"label-the-wellknownopenidconfiguration-endpoint-for-your-id-p": "The .well-known/openid-configuration endpoint for your IdP",
"title-open-id-connect-discovery-url": "OpenID Connect Discovery URL"
@@ -2528,6 +2632,7 @@
"no-access-modal": {
"connection-contact-grafana-admin": "To add a new connection, contact your Grafana admin.",
"editor-warning": "Editors cannot add new connections. You may check to see if it is already configured in <2>Data sources</2>.",
"links": "Links",
"okay": "Okay"
},
"not-found-datasource": {
@@ -2833,6 +2938,9 @@
"tooltip-view-as-scene": "View as Scene"
}
},
"dashboard-links-menu": {
"aria-label-dashboard-name": "{{dashboardName}} dashboard"
},
"dashboard-loading": {
"cancel-loading-dashboard": "Cancel loading dashboard"
},
@@ -2983,6 +3091,7 @@
"help-wizard": {
"copy-to-clipboard": "Copy to clipboard",
"description-obfuscate-data": "Modify the original data to hide sensitve information. Note the lengths will stay the same, and duplicate values will be equal.",
"description-support-snapshot": "Panel: {{panelTitle}}",
"download-snapshot": "Download ({{snapshotSize}})",
"label-obfuscate-data": "Obfuscate data",
"label-support-snapshot": "Support snapshot",
@@ -3079,7 +3188,9 @@
},
"options-pane-options": {
"placeholder-search-options": "Search options",
"Recent options-title-recent-options": "Recent options"
"Recent options-title-recent-options": "Recent options",
"title-matched_one": "Matched {{count}}/{{totalCount}} options",
"title-matched_other": "Matched {{count}}/{{totalCount}} options"
},
"outline": {
"tree-item": {
@@ -3447,7 +3558,11 @@
},
"visualization-button": {
"aria-label-change-visualization": "Change visualization",
"tooltip-click-to-change-visualization": "Click to change visualization"
"aria-label-close": "Close options pane",
"aria-label-show": "Show options pane",
"tooltip-click-to-change-visualization": "Click to change visualization",
"tooltip-close": "Close options pane",
"tooltip-show": "Show options pane"
},
"visualization-select-pane": {
"placeholder-search-for": "Search for...",
@@ -4015,6 +4130,9 @@
}
},
"datasources": {
"add-new-data-source-button": {
"tooltip-no-permission": "You do not have permission to configure new data sources"
},
"alert-success-message": {
"aria-label-create-a-dashboard": "Create a dashboard",
"aria-label-explore-data": "Explore data"
@@ -4037,7 +4155,8 @@
"test": "Test"
},
"cloud-info-box": {
"title-includes-active-metrics-storage": "The free plan includes 10k active metrics and 50gb storage."
"body-alert": "Or skip the effort and get {{mainDS}} (and {{extraDS}}) as fully-managed, scalable, and hosted data sources from Grafana Labs with the <6>free-forever Grafana Cloud plan</6>.",
"title-alert": "Configure your {{mainDS}} data source below"
},
"dashboards-table": {
"aria-label-delete-dashboard": "Delete dashboard",
@@ -4062,6 +4181,9 @@
"data-source-read-only-message": {
"title-provisioned-data-source": "Provisioned data source"
},
"data-source-type-card": {
"aria-label-learn-more": "{{dataSourcePluginName}}, learn more."
},
"data-sources-list-card": {
"build-a-dashboard": "Build a dashboard",
"explore": "Explore"
@@ -4079,6 +4201,10 @@
"new-data-source-view": {
"cancel": "Cancel",
"placeholder-filter-by-name-or-type": "Filter by name or type"
},
"use-data-source-info": {
"badge-text-not-supported": "Not supported",
"badge-text-supported": "Supported"
}
},
"dimensions": {
@@ -4124,8 +4250,12 @@
"label-template": "Template",
"label-value": "Value"
},
"threshold-editor": {
"tooltip-remove-threshold": "Remove threshold {{thresholdNumber}}"
},
"thresholds-editor": {
"add-threshold": "Add threshold",
"aria-label-threshold": "Threshold {{thresholdNumber}}",
"description-percentage-means-thresholds-relative": "Percentage means thresholds relative to min & max",
"thresholds-mode": "Thresholds mode"
},
@@ -4194,6 +4324,10 @@
"open": "Open",
"open-in-new-tab": "Open in new tab"
},
"content-outline": {
"tooltip-collapse-outline": "Collapse outline",
"tooltip-expand-outline": "Expand outline"
},
"content-outline-item-button": {
"body": {
"aria-label-content-outline-item-collapse-button": "Content outline item collapse button"
@@ -4212,13 +4346,19 @@
"title-correlation-details": "Correlation details"
},
"correlation-transformation-add-modal": {
"add-transformation": "Add transformation to correlation",
"added-variables": "This transformation will add the following variables:",
"aria-label-field": "Field",
"aria-label-type": "Type",
"body": "A transformation extracts variables out of a single field. These variables will be available along with your field variables.",
"cancel": "Cancel",
"edit-transformation": "Edit transformation",
"label-expression": "Expression",
"label-expression-without-tooltip": "Expression",
"label-field": "Field",
"label-type": "Type",
"label-variable-name": "Variable name",
"label-variable-name-without-tooltip": "Variable name",
"title-add": "Add transformation",
"title-edit": "Edit transformation"
},
@@ -4312,6 +4452,9 @@
},
"title-failed-sample-query": "Failed to load logs sample for this query"
},
"logs-table-available-fields": {
"title-label-percentage": "{{labelName}} appears in {{percentage}}% of log lines"
},
"logs-table-empty-fields": {
"no-fields": "No fields"
},
@@ -4547,6 +4690,10 @@
"title": "Table",
"title-with-name": "Table - {{name}}"
},
"time-sync-button": {
"aria-label-synced": "Synced times",
"aria-label-unsynced": "Unsynced times"
},
"timeline-collapser": {
"tooltip-collapse": "Collapse +1",
"tooltip-collapse-all": "Collapse all",
@@ -4576,7 +4723,9 @@
},
"trace-page-actions": {
"give-feedback": "Give feedback",
"label-copied": "Copied!",
"label-export": "Export",
"label-trace-id": "Trace ID",
"title-share-thoughts-about-tracing-grafana": "Share your thoughts about tracing in Grafana."
},
"trace-page-header": {
@@ -4779,6 +4928,10 @@
"palette-tab": "Colors",
"spectrum-tab": "Custom"
},
"color-swatch": {
"aria-label-default": "Pick a color",
"aria-label-selected-color": "{{colorLabel}} color"
},
"confirm-button": {
"cancel": "Cancel"
},
@@ -4915,7 +5068,11 @@
"clear": "Clear"
},
"interactive-table": {
"expand-row-tooltip": "Toggle row expanded"
"aria-label-collapse-all": "Collapse all rows",
"aria-label-expand-all": "Expand all rows",
"expand-row-tooltip": "Toggle row expanded",
"tooltip-collapse-all": "Collapse all rows",
"tooltip-expand-all": "Expand all rows"
},
"menu-item": {
"keyboard-shortcut-label": "Keyboard shortcut"
@@ -4941,10 +5098,25 @@
"next-page": "next page",
"previous-page": "previous page"
},
"panel-chrome": {
"aria-label-toggle-collapse": "toggle collapse panel"
},
"panel-menu": {
"label": "Menu for panel {{ title }}",
"title": "Menu"
},
"password-field": {
"tooltip-hide": "Hide password",
"tooltip-show": "Show password"
},
"row-expander": {
"aria-label-expand": "Expand row",
"collapse": "Collapse row",
"expand": "Expand row"
},
"row-expander-ng": {
"aria-label-collapse": "Collapse row"
},
"secret-form-field": {
"reset": "Reset"
},
@@ -5000,6 +5172,10 @@
"add": "Add",
"remove": "Remove tag: {{name}}"
},
"time-sync-button": {
"aria-label-sync": "Sync times",
"aria-label-unsync": "Unsync times"
},
"toggletip": {
"close": "Close"
},
@@ -6312,12 +6488,18 @@
"open-visualization-suggestions": "Open visualization suggestions",
"switch-to-table": "Switch to table"
},
"panel-plugin-error": {
"text-load-error": "Check the server startup logs for more information. <1></1>If this plugin was loaded from Git, then make sure it was compiled.",
"title-load-error": "Error loading: {{panelId}}",
"title-not-found": "Panel plugin not found: {{id}}"
},
"panel-renderer": {
"loading-plugin-panel": "Loading plugin panel...",
"no-panel-data": "No panel data"
},
"panel-type-card": {
"aria-label-delete-button-on-panel-type-card": "Delete button on panel type card",
"title-click-to-close": "Click again to close this section",
"tooltip-delete": "Delete"
},
"visualization-suggestions": {
@@ -6499,7 +6681,8 @@
"enable": "Enable"
},
"get-started-with-data-source": {
"add-new-data-source": "Add new data source"
"add-new-data-source": "Add new data source",
"title-button-disabled": "The plugin isn't usable yet, it may take some time to complete the installation."
},
"install-controls-button": {
"title-uninstall-modal": "Uninstall {{plugin}}"
@@ -6558,6 +6741,10 @@
"plugin-installed-badge": {
"text-installed": "Installed"
},
"plugin-list-item": {
"label-author": "By {{author}}",
"title-icon-plugin-type": "{{pluginType}} plugin"
},
"plugin-signature-details-badge": {
"signed-by": "Signed by: {{signatureOrg}}"
},
@@ -7287,7 +7474,8 @@
"basic-roles": "Basic roles"
},
"input": {
"no-roles": "No roles assigned"
"no-roles": "No roles assigned",
"placeholder-select-role": "Select role"
},
"menu": {
"clear-button": "Clear all",
@@ -7513,7 +7701,11 @@
"title-disable-service-account": "Disable service account"
},
"token-expiration": {
"expired-label": "Expired",
"never": "Never"
},
"token-revoked": {
"revoked-label": "Revoked"
}
},
"share-dashboard": {
@@ -7917,7 +8109,7 @@
},
"range-content": {
"apply-button": "Apply time range",
"default-error": "Please enter a past date or \"now\"",
"default-error": "Please enter a past date or \"{{now}}\"",
"fiscal-year": "Fiscal year",
"from-input": "From",
"open-input-calendar": "Open calendar",
@@ -8007,7 +8199,9 @@
},
"draggable-field-name": {
"rename-placeholder": "Rename {{fieldName}}",
"title-drag-and-drop-to-reorder": "Drag and drop to reorder"
"title-drag-and-drop-to-reorder": "Drag and drop to reorder",
"tooltip-disable": "Disable",
"tooltip-enable": "Enable"
},
"enum-mapping-editor": {
"add-enum-value": "Add enum value",
@@ -8024,7 +8218,8 @@
"label-replace-all-fields": "Replace all fields",
"label-source": "Source",
"placeholder-auto": "Auto",
"placeholder-select-delimiter": "Select delimiter..."
"placeholder-select-delimiter": "Select delimiter...",
"tooltip-regexp": "Example: {{regexExample}}"
},
"field-config-mapping-handler-arguments-editor": {
"aria-label-threshold-color": "Threshold color"
@@ -8231,9 +8426,13 @@
"label-calculation": "Calculation",
"label-field": "Field",
"label-type": "Type",
"label-window-size": "Window size",
"label-window-size-mode": "Window size mode",
"label-window-size-percent": "Window size %",
"placeholder-auto": "Auto",
"placeholder-field": "Field"
"placeholder-field": "Field",
"tooltip-window-size": "Window size",
"tooltip-window-size-percent": "Set the window size as a percentage of the total data"
}
},
"upgrade-box": {
@@ -8324,6 +8523,11 @@
"ad-hoc-filter": {
"label-and": "AND"
},
"ad-hoc-filter-key": {
"plus-segment": {
"aria-label-add-filter": "Add Filter"
}
},
"confirm-delete-modal": {
"title-delete-variable": "Delete variable"
},