Internationalisation: More automatic markup (#103203)

* easy changes

* couple of tweaks + translations

* update e2e tests

* kick CI
pull/103260/head
Ashley Harrison 3 months ago committed by GitHub
parent d6b71f171d
commit 38aee2dfa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 317
      .betterer.results
  2. 4
      docs/sources/panels-visualizations/query-transform-data/transform-data/index.md
  3. 1
      e2e/dashboards-suite/new-query-variable.spec.ts
  4. 1
      e2e/old-arch/dashboards-suite/new-query-variable.spec.ts
  5. 27
      public/app/features/dashboard-scene/addToDashboard/AddToDashboardForm.tsx
  6. 7
      public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx
  7. 6
      public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx
  8. 27
      public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.tsx
  9. 6
      public/app/features/dashboard-scene/inspect/InspectDataTab.tsx
  10. 4
      public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx
  11. 5
      public/app/features/dashboard-scene/inspect/PanelInspectDrawer.tsx
  12. 2
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/EmptyTransformationsMessage.tsx
  13. 17
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/NewAlertRuleButton.tsx
  14. 19
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx
  15. 2
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx
  16. 14
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.tsx
  17. 3
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/TransformationsDrawer.tsx
  18. 8
      public/app/features/dashboard-scene/panel-edit/PanelEditControls.tsx
  19. 11
      public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx
  20. 5
      public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx
  21. 22
      public/app/features/dashboard-scene/panel-edit/SaveLibraryVizPanelModal.tsx
  22. 15
      public/app/features/dashboard-scene/saving/DashboardPrompt.tsx
  23. 33
      public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx
  24. 79
      public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx
  25. 11
      public/app/features/dashboard-scene/saving/SaveProvisionedDashboardForm.tsx
  26. 5
      public/app/features/dashboard-scene/saving/shared.tsx
  27. 7
      public/app/features/dashboard-scene/scene/PanelLinks.tsx
  28. 3
      public/app/features/dashboard-scene/scene/UnlinkModal.tsx
  29. 12
      public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx
  30. 34
      public/app/features/dashboard-scene/settings/JsonModelEditView.tsx
  31. 50
      public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsEdit.tsx
  32. 18
      public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsList.tsx
  33. 53
      public/app/features/dashboard-scene/settings/links/DashboardLinkForm.tsx
  34. 28
      public/app/features/dashboard-scene/settings/links/DashboardLinkList.tsx
  35. 34
      public/app/features/dashboard-scene/settings/variables/VariableEditorForm.tsx
  36. 10
      public/app/features/dashboard-scene/settings/variables/VariableEditorList.tsx
  37. 17
      public/app/features/dashboard-scene/settings/variables/VariableEditorListRow.tsx
  38. 27
      public/app/features/dashboard-scene/settings/variables/components/AdHocVariableForm.tsx
  39. 7
      public/app/features/dashboard-scene/settings/variables/components/ConstantVariableForm.tsx
  40. 10
      public/app/features/dashboard-scene/settings/variables/components/CustomVariableForm.tsx
  41. 9
      public/app/features/dashboard-scene/settings/variables/components/DataSourceVariableForm.tsx
  42. 27
      public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx
  43. 12
      public/app/features/dashboard-scene/settings/variables/components/IntervalVariableForm.tsx
  44. 9
      public/app/features/dashboard-scene/settings/variables/components/QueryEditor.tsx
  45. 15
      public/app/features/dashboard-scene/settings/variables/components/QueryVariableForm.tsx
  46. 17
      public/app/features/dashboard-scene/settings/variables/components/SelectionOptionsForm.tsx
  47. 7
      public/app/features/dashboard-scene/settings/variables/components/TextBoxVariableForm.tsx
  48. 3
      public/app/features/dashboard-scene/settings/variables/components/VariableHideSelect.tsx
  49. 14
      public/app/features/dashboard-scene/settings/variables/components/VariableValuesPreview.tsx
  50. 3
      public/app/features/dashboard-scene/settings/version-history/RevertDashboardModal.tsx
  51. 5
      public/app/features/dashboard-scene/settings/version-history/VersionHistoryButtons.tsx
  52. 6
      public/app/features/dashboard-scene/settings/version-history/VersionHistoryComparison.tsx
  53. 14
      public/app/features/dashboard-scene/settings/version-history/VersionHistoryHeader.tsx
  54. 19
      public/app/features/dashboard-scene/settings/version-history/VersionHistoryTable.tsx
  55. 2
      public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx
  56. 7
      public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/EmailListConfiguration.tsx
  57. 3
      public/app/features/dashboard-scene/variables/VariableUsagesButton.tsx
  58. 315
      public/locales/en-US/grafana.json

@ -2575,22 +2575,8 @@ 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/dashboard-scene/addToDashboard/AddToDashboardForm.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"],
[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, "No untranslated strings. Wrap text with <Trans />", "7"]
],
"public/app/features/dashboard-scene/edit-pane/DashboardAddPane.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/edit-pane/DashboardEditPane.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, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard-scene/embedding/EmbeddedDashboardTestPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
@ -2598,34 +2584,17 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/inspect/HelpWizard/HelpWizard.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"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "9"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "10"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "11"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "12"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "13"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "14"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "15"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "16"]
[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"]
],
"public/app/features/dashboard-scene/inspect/HelpWizard/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard-scene/inspect/InspectDataTab.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/inspect/PanelInspectDrawer.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 />", "0"]
],
"public/app/features/dashboard-scene/pages/DashboardScenePage.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -2635,40 +2604,20 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/panel-edit/LibraryVizPanelInfo.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/EmptyTransformationsMessage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/NewAlertRuleButton.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.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. Wrap text with <Trans />", "3"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.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/dashboard-scene/panel-edit/PanelDataPane/PanelDataTransformationsTab.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"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/TransformationsDrawer.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/dashboard-scene/panel-edit/PanelEditControls.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 />", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
@ -2679,40 +2628,8 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.test.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.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"]
],
"public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.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/dashboard-scene/panel-edit/SaveLibraryVizPanelModal.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"],
[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"]
],
"public/app/features/dashboard-scene/saving/DashboardPrompt.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"]
],
"public/app/features/dashboard-scene/saving/SaveDashboardAsForm.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"],
[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, "No untranslated strings. Wrap text with <Trans />", "7"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/saving/SaveDashboardDrawer.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
@ -2720,29 +2637,11 @@ exports[`better eslint`] = {
],
"public/app/features/dashboard-scene/saving/SaveDashboardForm.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"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "9"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "10"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "11"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "12"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "13"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "14"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "15"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "16"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "17"]
[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/dashboard-scene/saving/SaveProvisionedDashboardForm.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 />", "0"]
],
"public/app/features/dashboard-scene/saving/getDashboardChanges.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -2754,11 +2653,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
],
"public/app/features/dashboard-scene/saving/shared.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/dashboard-scene/scene/PanelLinks.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 />", "0"]
],
"public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@ -2766,9 +2661,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/scene/PanelSearchLayout.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard-scene/scene/UnlinkModal.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/serialization/angularMigration.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@ -2793,195 +2685,57 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/settings/DeleteDashboardButton.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
[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/dashboard-scene/settings/JsonModelEditView.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. 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 />", "0"]
],
"public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsEdit.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"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "9"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "10"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "11"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "12"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "13"]
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsList.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. 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, "No untranslated strings. Wrap text with <Trans />", "7"]
[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/dashboard-scene/settings/annotations/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsEdit\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsList\`)", "1"]
],
"public/app/features/dashboard-scene/settings/links/DashboardLinkForm.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"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "9"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "10"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "11"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "12"]
],
"public/app/features/dashboard-scene/settings/links/DashboardLinkList.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. 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"]
],
"public/app/features/dashboard-scene/settings/variables/VariableEditorForm.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"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "7"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "8"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "9"]
],
"public/app/features/dashboard-scene/settings/variables/VariableEditorList.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/dashboard-scene/settings/variables/VariableEditorListRow.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/dashboard-scene/settings/variables/components/AdHocVariableForm.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. Wrap text with <Trans />", "4"]
],
"public/app/features/dashboard-scene/settings/variables/components/ConstantVariableForm.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/dashboard-scene/settings/variables/components/CustomVariableForm.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"]
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/settings/variables/components/DataSourceVariableForm.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
],
"public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.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. Wrap text with <Trans />", "4"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/dashboard-scene/settings/variables/components/IntervalVariableForm.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"]
],
"public/app/features/dashboard-scene/settings/variables/components/QueryEditor.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 in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/dashboard-scene/settings/variables/components/QueryVariableForm.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"]
],
"public/app/features/dashboard-scene/settings/variables/components/SelectionOptionsForm.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-scene/settings/variables/components/TextBoxVariableForm.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/dashboard-scene/settings/variables/components/VariableHideSelect.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 />", "0"]
],
"public/app/features/dashboard-scene/settings/variables/components/VariableSelectField.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/settings/variables/components/VariableValuesPreview.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/dashboard-scene/settings/variables/utils.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/settings/version-history/RevertDashboardModal.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/dashboard-scene/settings/version-history/VersionHistoryButtons.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 />", "0"]
],
"public/app/features/dashboard-scene/settings/version-history/VersionHistoryComparison.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 />", "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 />", "2"]
],
"public/app/features/dashboard-scene/settings/version-history/VersionHistoryHeader.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"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/dashboard-scene/settings/version-history/VersionHistoryTable.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"],
[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 in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/settings/version-history/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./HistorySrv\`)", "0"],
@ -2990,12 +2744,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryHeader\`)", "3"],
[0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryTable\`)", "4"]
],
"public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/EmailListConfiguration.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/ShareSnapshot.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
@ -3020,8 +2768,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"public/app/features/dashboard-scene/variables/VariableUsagesButton.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()", "0"]
],
"public/app/features/dashboard/api/ResponseTransformers.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],

@ -1191,7 +1191,7 @@ Use this transformation to address issues when a data source returns time series
##### Wide time series
Select this option to transform the time series data frame from the long format to the wide format.
Select this option to transform the time series data frame from the long format to the wide format. If your data source returns time series data in a long format and your visualization requires a wide format, this transformation simplifies the process.
A wide time series combines data into a single frame with one shared, ascending time field. Time fields do not repeat and multiple values extend in separate columns.
@ -1217,7 +1217,7 @@ Multi-frame time series break data into multiple frames that all contain two fie
##### Long time series
A long time series combines data to one frame, with the first field being an ascending time field. The time field might have duplicates. String values are in separate fields, and there might be more than one.
A long time series combines data into one frame, with the first field being an ascending time field. The time field might have duplicates. String values are in separate fields, and there might be more than one.
**Example: Converting to long format**

@ -157,7 +157,6 @@ describe('Variables - Query - Add variable', () => {
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().within((input) => {
expect(input.attr('placeholder')).equals('blank = auto');
expect(input.val()).equals('');
});

@ -153,7 +153,6 @@ describe('Variables - Query - Add variable', () => {
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().within((input) => {
expect(input.attr('placeholder')).equals('blank = auto');
expect(input.val()).equals('');
});

@ -8,6 +8,7 @@ import { Panel } from '@grafana/schema';
import { Alert, Button, Field, Modal, RadioButtonGroup } from '@grafana/ui';
import { DashboardPicker } from 'app/core/components/Select/DashboardPicker';
import { contextSrv } from 'app/core/core';
import { t, Trans } from 'app/core/internationalization';
import { AccessControlAction } from 'app/types';
import { addToDashboard, SubmissionError } from './addToDashboard';
@ -112,7 +113,13 @@ export function AddToDashboardForm<TOptions = undefined>({
<Controller
control={control}
render={({ field: { ref, ...field } }) => (
<Field label="Target dashboard" description="Choose where to add the panel.">
<Field
label={t('dashboard-scene.add-to-dashboard-form.label-target-dashboard', 'Target dashboard')}
description={t(
'dashboard-scene.add-to-dashboard-form.description-choose-where-to-add-the-panel',
'Choose where to add the panel.'
)}
>
<RadioButtonGroup options={saveTargets} {...field} id="e2d-save-target" />
</Field>
)}
@ -127,8 +134,11 @@ export function AddToDashboardForm<TOptions = undefined>({
<Controller
render={({ field: { ref, value, onChange, ...field } }) => (
<Field
label="Dashboard"
description="Select in which dashboard the panel will be created."
label={t('dashboard-scene.add-to-dashboard-form.label-dashboard', 'Dashboard')}
description={t(
'dashboard-scene.add-to-dashboard-form.description-select-which-dashboard-panel-created',
'Select in which dashboard the panel will be created.'
)}
error={errors.dashboardUid?.message}
invalid={!!errors.dashboardUid}
>
@ -149,14 +159,17 @@ export function AddToDashboardForm<TOptions = undefined>({
})()}
{submissionError && (
<Alert severity="error" title="Error adding the panel">
<Alert
severity="error"
title={t('dashboard-scene.add-to-dashboard-form.title-error-adding-the-panel', 'Error adding the panel')}
>
{submissionError.message}
</Alert>
)}
<Modal.ButtonRow>
<Button type="reset" onClick={onClose} fill="outline" variant="secondary">
Cancel
<Trans i18nKey="dashboard-scene.add-to-dashboard-form.cancel">Cancel</Trans>
</Button>
<Button
type="submit"
@ -164,10 +177,10 @@ export function AddToDashboardForm<TOptions = undefined>({
onClick={handleSubmit(partial(onSubmit, true))}
icon="external-link-alt"
>
Open in new tab
<Trans i18nKey="dashboard-scene.add-to-dashboard-form.open-in-new-tab">Open in new tab</Trans>
</Button>
<Button type="submit" variant="primary" onClick={handleSubmit(partial(onSubmit, false))} icon="apps">
Open dashboard
<Trans i18nKey="dashboard-scene.add-to-dashboard-form.open-dashboard">Open dashboard</Trans>
</Button>
</Modal.ButtonRow>
</form>

@ -87,7 +87,12 @@ export function DashboardAddPane({ editPane }: Props) {
return (
<>
<div className={styles.header}>
<IconButton name="arrow-left" size="lg" onClick={() => editPane.toggleAddPane()} aria-label="Close add pane" />
<IconButton
name="arrow-left"
size="lg"
onClick={() => editPane.toggleAddPane()}
aria-label={t('dashboard-scene.dashboard-add-pane.aria-label-close-add-pane', 'Close add pane')}
/>
{t('dashboard.edit-pane.add.title', 'Add element')}
</div>
<Box display="flex" direction="column" gap={1} padding={2}>

@ -15,7 +15,7 @@ import {
Text,
Icon,
} from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { isInCloneChain } from '../utils/clone';
import { getDashboardSceneFor } from '../utils/utils';
@ -289,7 +289,9 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla
onClick={() => setOutlineCollapsed(!outlineCollapsed)}
className={styles.outlineCollapseButton}
>
<Text weight="medium">Outline</Text>
<Text weight="medium">
<Trans i18nKey="dashboard-scene.dashboard-edit-pane-renderer.outline">Outline</Trans>
</Text>
<Icon name="angle-up" />
</div>
{!outlineCollapsed && (

@ -22,6 +22,7 @@ import {
Icon,
Stack,
} from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types';
@ -69,7 +70,7 @@ export function HelpWizard({ panel, onClose }: Props) {
return (
<Drawer
title="Get help with this panel"
title={t('dashboard-scene.help-wizard.title-get-help-with-this-panel', 'Get help with this panel')}
size="lg"
onClose={onClose}
subtitle={
@ -116,13 +117,13 @@ export function HelpWizard({ panel, onClose }: Props) {
{currentTab === SnapshotTab.Data && (
<div className={styles.code}>
<div className={styles.opts}>
<Field label="Template" className={styles.field}>
<Field label={t('dashboard-scene.help-wizard.label-template', 'Template')} className={styles.field}>
<Select options={options} value={showMessage} onChange={service.onShowMessageChange} />
</Field>
{showMessage === ShowMessage.GithubComment ? (
<ClipboardButton icon="copy" getText={service.onGetMarkdownForClipboard}>
Copy to clipboard
<Trans i18nKey="dashboard-scene.help-wizard.copy-to-clipboard">Copy to clipboard</Trans>
</ClipboardButton>
) : (
<Button icon="download-alt" onClick={service.onDownloadDashboard}>
@ -149,26 +150,26 @@ export function HelpWizard({ panel, onClose }: Props) {
{currentTab === SnapshotTab.Support && (
<>
<Field
label="Randomize data"
label={t('dashboard-scene.help-wizard.label-randomize-data', 'Randomize data')}
description="Modify the original data to hide sensitive information. Note the lengths will stay the same, and duplicate values will be equal."
>
<Stack>
<InlineSwitch
label="Labels"
label={t('dashboard-scene.help-wizard.randomize-labels-label-labels', 'Labels')}
id="randomize-labels"
showLabel={true}
value={Boolean(randomize.labels)}
onChange={() => service.onToggleRandomize('labels')}
/>
<InlineSwitch
label="Field names"
label={t('dashboard-scene.help-wizard.randomize-field-names-label-field-names', 'Field names')}
id="randomize-field-names"
showLabel={true}
value={Boolean(randomize.names)}
onChange={() => service.onToggleRandomize('names')}
/>
<InlineSwitch
label="String values"
label={t('dashboard-scene.help-wizard.randomize-string-values-label-string-values', 'String values')}
id="randomize-string-values"
showLabel={true}
value={Boolean(randomize.values)}
@ -177,7 +178,10 @@ export function HelpWizard({ panel, onClose }: Props) {
</Stack>
</Field>
<Field label="Support snapshot" description={`Panel: ${panelTitle}`}>
<Field
label={t('dashboard-scene.help-wizard.label-support-snapshot', 'Support snapshot')}
description={`Panel: ${panelTitle}`}
>
<Stack>
<Button icon="download-alt" onClick={service.onDownloadDashboard}>
Dashboard ({snapshotSize})
@ -185,9 +189,12 @@ export function HelpWizard({ panel, onClose }: Props) {
<ClipboardButton
icon="github"
getText={service.onGetMarkdownForClipboard}
title="Copy a complete GitHub comment to the clipboard"
title={t(
'dashboard-scene.help-wizard.title-complete-git-hub-comment-clipboard',
'Copy a complete GitHub comment to the clipboard'
)}
>
Copy to clipboard
<Trans i18nKey="dashboard-scene.help-wizard.copy-to-clipboard">Copy to clipboard</Trans>
</ClipboardButton>
</Stack>
</Field>

@ -9,7 +9,7 @@ import {
SceneObjectState,
VizPanel,
} from '@grafana/scenes';
import { t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { InspectTab } from 'app/features/inspector/types';
import { GetDataOptions } from 'app/features/query/state/PanelQueryRunner';
@ -51,7 +51,9 @@ export class InspectDataTab extends SceneObjectBase<InspectDataTabState> {
const timeRange = sceneGraph.getTimeRange(panel);
if (!data) {
<div>No data found</div>;
<div>
<Trans i18nKey="dashboard-scene.inspect-data-tab.no-data-found">No data found</Trans>
</div>;
}
return (

@ -17,7 +17,7 @@ import {
} from '@grafana/scenes';
import { LibraryPanel } from '@grafana/schema/';
import { Button, CodeEditor, Field, Select, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { getPanelDataFrames } from 'app/features/dashboard/components/HelpWizard/utils';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getPanelInspectorStyles2 } from 'app/features/inspector/styles';
@ -177,7 +177,7 @@ export class InspectJsonTab extends SceneObjectBase<InspectJsonTabState> {
</Field>
{model.isEditable() && (
<Button className={styles.toolbarItem} onClick={model.onApplyChange}>
Apply
<Trans i18nKey="dashboard-scene.inspect-json-tab.apply">Apply</Trans>
</Button>
)}
</div>

@ -11,6 +11,7 @@ import {
SceneObjectRef,
} from '@grafana/scenes';
import { Alert, Drawer, Tab, TabsBar } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getDataSourceWithInspector } from 'app/features/dashboard/components/Inspector/hooks';
import { supportsDataQuery } from 'app/features/dashboard/components/PanelEditor/utils';
import { InspectTab } from 'app/features/inspector/types';
@ -135,7 +136,9 @@ function PanelInspectRenderer({ model }: SceneComponentProps<PanelInspectDrawer>
}
>
{pluginNotLoaded && (
<Alert title="Panel plugin not loaded">
<Alert
title={t('dashboard-scene.panel-inspect-renderer.title-panel-plugin-not-loaded', 'Panel plugin not loaded')}
>
Make sure the panel you want to inspect is visible and has been displayed before opening inspect.
</Alert>
)}

@ -27,7 +27,7 @@ export function EmptyTransformationsMessage(props: EmptyTransformationsProps) {
onClick={props.onShowPicker}
data-testid={selectors.components.Transforms.addTransformationButton}
>
Add transformation
<Trans i18nKey="dashboard-scene.empty-transformations-message.add-transformation">Add transformation</Trans>
</Button>
</Stack>
</Box>

@ -5,6 +5,7 @@ import { urlUtil } from '@grafana/data';
import { locationService, logInfo } from '@grafana/runtime';
import { VizPanel } from '@grafana/scenes';
import { Alert, Button } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { LogMessages } from 'app/features/alerting/unified/Analytics';
import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
@ -18,12 +19,22 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
const { loading, value: formValues } = useAsync(() => scenesPanelToRuleFormValues(panel), [panel]);
if (loading) {
return <Button disabled={true}>New alert rule</Button>;
return (
<Button disabled={true}>
<Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
</Button>
);
}
if (!formValues) {
return (
<Alert severity="info" title="No alerting capable query found">
<Alert
severity="info"
title={t(
'dashboard-scene.scenes-new-rule-from-panel-button.title-no-alerting-capable-query-found',
'No alerting capable query found'
)}
>
Cannot create alerts from this panel because no query to an alerting capable datasource is found.
</Alert>
);
@ -44,7 +55,7 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
return (
<Button icon="bell" onClick={onClick} className={className} data-testid="create-alert-rule-button">
New alert rule
<Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
</Button>
);
};

@ -5,7 +5,7 @@ import { config } from '@grafana/runtime';
import { SceneComponentProps, SceneObjectBase, SceneObjectRef, SceneObjectState, VizPanel } from '@grafana/scenes';
import { Alert, LoadingPlaceholder, Tab, useStyles2 } from '@grafana/ui';
import { contextSrv } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { RulesTable } from 'app/features/alerting/unified/components/rules/RulesTable';
import { usePanelCombinedRules } from 'app/features/alerting/unified/hooks/usePanelCombinedRules';
import { getRulesPermissions } from 'app/features/alerting/unified/utils/access-control';
@ -64,7 +64,13 @@ export function PanelDataAlertingTabRendered({ model }: SceneComponentProps<Pane
});
const alert = errors.length ? (
<Alert title="Errors loading rules" severity="error">
<Alert
title={t(
'dashboard-scene.panel-data-alerting-tab-rendered.alert.title-errors-loading-rules',
'Errors loading rules'
)}
severity="error"
>
{errors.map((error, index) => (
<div key={index}>Failed to load Grafana rules state: {stringifyErrorLike(error)}</div>
))}
@ -75,7 +81,9 @@ export function PanelDataAlertingTabRendered({ model }: SceneComponentProps<Pane
return (
<>
{alert}
<LoadingPlaceholder text="Loading rules..." />
<LoadingPlaceholder
text={t('dashboard-scene.panel-data-alerting-tab-rendered.text-loading-rules', 'Loading rules...')}
/>
</>
);
}
@ -108,7 +116,10 @@ export function PanelDataAlertingTabRendered({ model }: SceneComponentProps<Pane
</>
)}
{isNew && !!dashboard.state.meta.canSave && (
<Alert severity="info" title="Dashboard not saved">
<Alert
severity="info"
title={t('dashboard-scene.panel-data-alerting-tab-rendered.title-dashboard-not-saved', 'Dashboard not saved')}
>
<Trans i18nKey="dashboard.panel-edit.alerting-tab.dashboard-not-saved">
Dashboard must be saved before alerts can be added.
</Trans>

@ -377,7 +377,7 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
variant="secondary"
data-testid={selectors.components.QueryTab.addQuery}
>
Add query
<Trans i18nKey="dashboard-scene.panel-data-queries-tab-rendered.add-query">Add query</Trans>
</Button>
{queryLibraryEnabled && (
<Button

@ -14,6 +14,7 @@ import {
SceneObjectState,
} from '@grafana/scenes';
import { Button, ButtonGroup, ConfirmModal, Tab, useStyles2 } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { TransformationOperationRows } from 'app/features/dashboard/components/TransformationsEditor/TransformationOperationRows';
import { getQueryRunnerFor } from '../../utils/utils';
@ -112,7 +113,9 @@ export function PanelDataTransformationsTabRendered({ model }: SceneComponentPro
onClick={openDrawer}
data-testid={selectors.components.Transforms.addTransformationButton}
>
Add another transformation
<Trans i18nKey="dashboard-scene.panel-data-transformations-tab-rendered.add-another-transformation">
Add another transformation
</Trans>
</Button>
<Button
data-testid={selectors.components.Transforms.removeAllTransformationsButton}
@ -121,12 +124,17 @@ export function PanelDataTransformationsTabRendered({ model }: SceneComponentPro
variant="secondary"
onClick={() => setConfirmModalOpen(true)}
>
Delete all transformations
<Trans i18nKey="dashboard-scene.panel-data-transformations-tab-rendered.delete-all-transformations">
Delete all transformations
</Trans>
</Button>
</ButtonGroup>
<ConfirmModal
isOpen={confirmModalOpen}
title="Delete all transformations?"
title={t(
'dashboard-scene.panel-data-transformations-tab-rendered.title-delete-all-transformations',
'Delete all transformations?'
)}
body="By deleting all transformations, you will go back to the main selection screen."
confirmText="Delete all"
onConfirm={() => {

@ -2,6 +2,7 @@ import { FormEvent, useMemo, useState } from 'react';
import { DataFrame, SelectableValue, standardTransformersRegistry } from '@grafana/data';
import { IconButton } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { TransformationPickerNg } from 'app/features/dashboard/components/TransformationsEditor/TransformationPickerNg';
import {
FilterCategory,
@ -65,7 +66,7 @@ export function TransformationsDrawer(props: TransformationsDrawerProps) {
onClick={() => {
setDrawerState({ ...drawerState, ...{ search: '' } });
}}
tooltip="Clear search"
tooltip={t('dashboard-scene.transformations-drawer.search-box-suffix.tooltip-clear-search', 'Clear search')}
/>
</>
);

@ -1,5 +1,6 @@
import { selectors } from '@grafana/e2e-selectors';
import { InlineSwitch } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { PanelEditor } from './PanelEditor';
@ -14,12 +15,15 @@ export function PanelEditControls({ panelEditor }: Props) {
<>
{dataPane && (
<InlineSwitch
label="Table view"
label={t('dashboard-scene.panel-edit-controls.table-view-label-table-view', 'Table view')}
showLabel={true}
id="table-view"
value={tableView ? true : false}
onClick={panelEditor.onToggleTableView}
aria-label="toggle-table-view"
aria-label={t(
'dashboard-scene.panel-edit-controls.table-view-aria-label-toggletableview',
'Toggle table view'
)}
data-testid={selectors.components.PanelEditor.toggleTableView}
/>
)}

@ -32,7 +32,7 @@ import {
ToolbarButton,
useStyles2,
} from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { OptionFilter } from 'app/features/dashboard/components/PanelEditor/OptionsPaneOptions';
import { getPanelPluginNotFound } from 'app/features/panel/components/PanelPluginError';
import { VizTypeChangeDetails } from 'app/features/panel/components/VizTypePicker/types';
@ -149,7 +149,7 @@ export class PanelOptionsPane extends SceneObjectBase<PanelOptionsPaneState> {
<FilterInput
className={styles.searchOptions}
value={searchQuery}
placeholder="Search options"
placeholder={t('dashboard-scene.panel-options-pane.placeholder-search-options', 'Search options')}
onChange={model.onSetSearchQuery}
/>
{showSearchRadioButtons && (
@ -263,11 +263,14 @@ export function VisualizationButton({ pluginId, onOpen }: VisualizationButtonPro
<Stack gap={1}>
<ToolbarButton
className={styles.vizButton}
tooltip="Click to change visualization"
tooltip={t(
'dashboard-scene.visualization-button.tooltip-click-to-change-visualization',
'Click to change visualization'
)}
imgSrc={pluginMeta.info.logos.small}
onClick={onOpen}
data-testid={selectors.components.PanelEditor.toggleVizPicker}
aria-label="Change Visualization"
aria-label={t('dashboard-scene.visualization-button.aria-label-change-visualization', 'Change visualization')}
variant="canvas"
isOpen={false}
fullWidth

@ -9,6 +9,7 @@ import { reportInteraction } from '@grafana/runtime';
import { VizPanel } from '@grafana/scenes';
import { Button, Field, FilterInput, RadioButtonGroup, ScrollContainer, useStyles2 } from '@grafana/ui';
import { LS_VISUALIZATION_SELECT_TAB_KEY } from 'app/core/constants';
import { t } from 'app/core/internationalization';
import { VisualizationSelectPaneTab } from 'app/features/dashboard/components/PanelEditor/types';
import { VisualizationSuggestions } from 'app/features/panel/components/VizTypePicker/VisualizationSuggestions';
import { VizTypePicker } from 'app/features/panel/components/VizTypePicker/VizTypePicker';
@ -86,10 +87,10 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
value={searchQuery}
onChange={handleSearchChange}
autoFocus={true}
placeholder="Search for..."
placeholder={t('dashboard-scene.panel-viz-type-picker.placeholder-search-for', 'Search for...')}
/>
<Button
title="Close"
title={t('dashboard-scene.panel-viz-type-picker.title-close', 'Close')}
variant="secondary"
icon="angle-up"
className={styles.closeButton}

@ -2,6 +2,7 @@ import { useCallback, useState } from 'react';
import { useAsync, useDebounce } from 'react-use';
import { Button, Icon, Input, Modal, useStyles2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { getConnectedDashboards } from 'app/features/library-panels/state/api';
import { getModalStyles } from 'app/features/library-panels/styles';
@ -62,17 +63,26 @@ export const SaveLibraryVizPanelModal = ({ libraryPanel, isUnsavedPrompt, onDism
<Input
className={styles.dashboardSearch}
prefix={<Icon name="search" />}
placeholder="Search affected dashboards"
placeholder={t(
'dashboard-scene.save-library-viz-panel-modal.placeholder-search-affected-dashboards',
'Search affected dashboards'
)}
value={searchString}
onChange={(e) => setSearchString(e.currentTarget.value)}
/>
{dashState.loading ? (
<p>Loading connected dashboards...</p>
<p>
<Trans i18nKey="dashboard-scene.save-library-viz-panel-modal.loading-connected-dashboards">
Loading connected dashboards...
</Trans>
</p>
) : (
<table className={styles.myTable}>
<thead>
<tr>
<th>Dashboard name</th>
<th>
<Trans i18nKey="dashboard-scene.save-library-viz-panel-modal.dashboard-name">Dashboard name</Trans>
</th>
</tr>
</thead>
<tbody>
@ -86,11 +96,11 @@ export const SaveLibraryVizPanelModal = ({ libraryPanel, isUnsavedPrompt, onDism
)}
<Modal.ButtonRow>
<Button variant="secondary" onClick={onDismiss} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.save-library-viz-panel-modal.cancel">Cancel</Trans>
</Button>
{isUnsavedPrompt && (
<Button variant="destructive" onClick={discardAndClose}>
Discard
<Trans i18nKey="dashboard-scene.save-library-viz-panel-modal.discard">Discard</Trans>
</Button>
)}
<Button
@ -98,7 +108,7 @@ export const SaveLibraryVizPanelModal = ({ libraryPanel, isUnsavedPrompt, onDism
onConfirm();
}}
>
Update all
<Trans i18nKey="dashboard-scene.save-library-viz-panel-modal.update-all">Update all</Trans>
</Button>
</Modal.ButtonRow>
</div>

@ -5,6 +5,7 @@ import { memo, useContext, useEffect, useMemo } from 'react';
import { locationService } from '@grafana/runtime';
import { ModalsContext, Modal, Button, useStyles2 } from '@grafana/ui';
import { Prompt } from 'app/core/components/FormPrompt/Prompt';
import { t, Trans } from 'app/core/internationalization';
import { contextSrv } from 'app/core/services/context_srv';
import { SaveLibraryVizPanelModal } from '../panel-edit/SaveLibraryVizPanelModal';
@ -124,20 +125,24 @@ export const UnsavedChangesModal = ({ onDiscard, onDismiss, onSaveDashboardClick
return (
<Modal
isOpen={true}
title="Unsaved changes"
title={t('dashboard-scene.unsaved-changes-modal.title-unsaved-changes', 'Unsaved changes')}
onDismiss={onDismiss}
icon="exclamation-triangle"
className={styles.modal}
>
<h5>Do you want to save your changes?</h5>
<h5>
<Trans i18nKey="dashboard-scene.unsaved-changes-modal.changes">Do you want to save your changes?</Trans>
</h5>
<Modal.ButtonRow>
<Button variant="secondary" onClick={onDismiss} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.unsaved-changes-modal.cancel">Cancel</Trans>
</Button>
<Button variant="destructive" onClick={onDiscard}>
Discard
<Trans i18nKey="dashboard-scene.unsaved-changes-modal.discard">Discard</Trans>
</Button>
<Button onClick={onSaveDashboardClick}>
<Trans i18nKey="dashboard-scene.unsaved-changes-modal.save-dashboard">Save dashboard</Trans>
</Button>
<Button onClick={onSaveDashboardClick}>Save dashboard</Button>
</Modal.ButtonRow>
</Modal>
);

@ -5,6 +5,7 @@ import { UseFormSetValue, useForm } from 'react-hook-form';
import { selectors } from '@grafana/e2e-selectors';
import { Button, Input, Switch, Field, Label, TextArea, Stack, Alert, Box } from '@grafana/ui';
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { Trans, t } from 'app/core/internationalization';
import { validationSrv } from 'app/features/manage-dashboards/services/ValidationSrv';
import { DashboardScene } from '../scene/DashboardScene';
@ -77,7 +78,7 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
const cancelButton = (
<Button variant="secondary" onClick={() => dashboard.closeModal()} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.save-dashboard-as-form.cancel-button.cancel">Cancel</Trans>
</Button>
);
@ -94,7 +95,13 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
return (
<>
{error && formValuesMatchContentSent && (
<Alert title="Failed to save dashboard" severity="error">
<Alert
title={t(
'dashboard-scene.save-dashboard-as-form.render-footer.title-failed-to-save-dashboard',
'Failed to save dashboard'
)}
severity="error"
>
{error.message && <p>{error.message}</p>}
</Alert>
)}
@ -111,7 +118,10 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
<Field label={<TitleFieldLabel onChange={setValue} />} invalid={!!errors.title} error={errors.title?.message}>
<Input
{...register('title', { required: 'Required', validate: validateDashboardName })}
aria-label="Save dashboard title field"
aria-label={t(
'dashboard-scene.save-dashboard-as-form.aria-label-save-dashboard-title-field',
'Save dashboard title field'
)}
data-testid={selectors.components.Drawer.DashboardSaveDrawer.saveAsTitleInput}
onChange={debounce(async (e: ChangeEvent<HTMLInputElement>) => {
setValue('title', e.target.value, { shouldValidate: true });
@ -125,12 +135,15 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
>
<TextArea
{...register('description', { required: false })}
aria-label="Save dashboard description field"
aria-label={t(
'dashboard-scene.save-dashboard-as-form.aria-label-save-dashboard-description-field',
'Save dashboard description field'
)}
autoFocus
/>
</Field>
<Field label="Folder">
<Field label={t('dashboard-scene.save-dashboard-as-form.label-folder', 'Folder')}>
<FolderPicker
onChange={async (uid: string | undefined, title: string | undefined) => {
setValue('folder', { uid, title });
@ -152,7 +165,7 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
/>
</Field>
{!changeInfo.isNew && (
<Field label="Copy tags">
<Field label={t('dashboard-scene.save-dashboard-as-form.label-copy-tags', 'Copy tags')}>
<Switch {...register('copyTags')} />
</Field>
)}
@ -168,7 +181,9 @@ export interface TitleLabelProps {
export function TitleFieldLabel(props: TitleLabelProps) {
return (
<Stack justifyContent="space-between">
<Label htmlFor="description">Title</Label>
<Label htmlFor="description">
<Trans i18nKey="dashboard-scene.title-field-label.title">Title</Trans>
</Label>
{/* {config.featureToggles.dashgpt && isNew && (
<GenAIDashDescriptionButton
onGenerate={(description) => field.onChange(description)}
@ -186,7 +201,9 @@ export interface DescriptionLabelProps {
export function DescriptionLabel(props: DescriptionLabelProps) {
return (
<Stack justifyContent="space-between">
<Label htmlFor="description">Description</Label>
<Label htmlFor="description">
<Trans i18nKey="dashboard-scene.description-label.description">Description</Trans>
</Label>
{/* {config.featureToggles.dashgpt && isNew && (
<GenAIDashDescriptionButton
onGenerate={(description) => field.onChange(description)}

@ -47,7 +47,7 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
const cancelButton = (
<Button variant="secondary" onClick={() => dashboard.closeModal()} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.save-dashboard-form.cancel-button.cancel">Cancel</Trans>
</Button>
);
@ -77,8 +77,18 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
if (isVersionMismatchError(error)) {
return (
<Alert title="Someone else has updated this dashboard" severity="error">
<p>Would you still like to save this dashboard?</p>
<Alert
title={t(
'dashboard-scene.save-dashboard-form.render-footer.title-someone-else-has-updated-this-dashboard',
'Someone else has updated this dashboard'
)}
severity="error"
>
<p>
<Trans i18nKey="dashboard-scene.save-dashboard-form.render-footer.would-still-dashboard">
Would you still like to save this dashboard?
</Trans>
</p>
<Box paddingTop={2}>
<Stack alignItems="center">
{cancelButton}
@ -95,7 +105,10 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
if (isPluginDashboardError(error)) {
return (
<Alert title="Plugin dashboard" severity="error">
<Alert
title={t('dashboard-scene.save-dashboard-form.render-footer.title-plugin-dashboard', 'Plugin dashboard')}
severity="error"
>
<p>
Your changes will be lost when you update the plugin. Use <strong>Save As</strong> to create custom version.
</p>
@ -112,14 +125,26 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
return (
<>
{error && (
<Alert title="Failed to save dashboard" severity="error">
<Alert
title={t(
'dashboard-scene.save-dashboard-form.render-footer.title-failed-to-save-dashboard',
'Failed to save dashboard'
)}
severity="error"
>
<p>{error.message}</p>
</Alert>
)}
<Stack alignItems="center">
{cancelButton}
{saveButton(false)}
{!hasChanges && <div>No changes to save</div>}
{!hasChanges && (
<div>
<Trans i18nKey="dashboard-scene.save-dashboard-form.render-footer.no-changes-to-save">
No changes to save
</Trans>
</div>
)}
</Stack>
</>
);
@ -129,7 +154,13 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
<Stack gap={2} direction="column">
<SaveDashboardFormCommonOptions drawer={drawer} changeInfo={changeInfo} />
{hasMigratedToV2 && (
<Alert title="Dashboard drastically changed" severity="warning">
<Alert
title={t(
'dashboard-scene.save-dashboard-form.title-dashboard-drastically-changed',
'Dashboard drastically changed'
)}
severity="warning"
>
<p>
Because you're using new dashboards features only supported on new Grafana dashboard schema format, the
dashboard will be saved in the new format. Please make sure you want to perform this action or you prefer to
@ -137,9 +168,9 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
</p>
</Alert>
)}
<Field label="Message">
<Field label={t('dashboard-scene.save-dashboard-form.label-message', 'Message')}>
<TextArea
aria-label="message"
aria-label={t('dashboard-scene.save-dashboard-form.aria-label-message', 'message')}
value={options.message ?? ''}
onChange={(e) => {
setOptions({
@ -147,7 +178,10 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) {
message: e.currentTarget.value,
});
}}
placeholder="Add a note to describe your changes (optional)."
placeholder={t(
'dashboard-scene.save-dashboard-form.placeholder-describe-changes-optional',
'Add a note to describe your changes (optional).'
)}
autoFocus
rows={5}
/>
@ -173,7 +207,10 @@ export function SaveDashboardFormCommonOptions({ drawer, changeInfo }: SaveDashb
id="save-timerange"
checked={saveTimeRange}
onChange={drawer.onToggleSaveTimeRange}
label="Update default time range"
label={t(
'dashboard-scene.save-dashboard-form-common-options.save-timerange-label-update-default-time-range',
'Update default time range'
)}
description={'Will make current time range the new default'}
data-testid={selectors.pages.SaveDashboardModal.saveTimerange}
/>
@ -181,8 +218,14 @@ export function SaveDashboardFormCommonOptions({ drawer, changeInfo }: SaveDashb
{hasRefreshChange && (
<Checkbox
id="save-refresh"
label="Update default refresh value"
description="Will make the current refresh the new default"
label={t(
'dashboard-scene.save-dashboard-form-common-options.save-refresh-label-update-default-refresh-value',
'Update default refresh value'
)}
description={t(
'dashboard-scene.save-dashboard-form-common-options.save-refresh-description-current-refresh-default',
'Will make the current refresh the new default'
)}
checked={saveRefresh}
onChange={drawer.onToggleSaveRefresh}
data-testid={selectors.pages.SaveDashboardModal.saveRefresh}
@ -191,8 +234,14 @@ export function SaveDashboardFormCommonOptions({ drawer, changeInfo }: SaveDashb
{hasVariableValueChanges && (
<Checkbox
id="save-variables"
label="Update default variable values"
description="Will make the current values the new default"
label={t(
'dashboard-scene.save-dashboard-form-common-options.save-variables-label-update-default-variable-values',
'Update default variable values'
)}
description={t(
'dashboard-scene.save-dashboard-form-common-options.save-variables-description-current-values-default',
'Will make the current values the new default'
)}
checked={saveVariables}
onChange={drawer.onToggleSaveVariables}
data-testid={selectors.pages.SaveDashboardModal.saveVariables}

@ -4,6 +4,7 @@ import { useCallback, useMemo } from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Button, ClipboardButton, Stack, CodeEditor, Box } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DashboardScene } from '../scene/DashboardScene';
@ -70,13 +71,17 @@ export function SaveProvisionedDashboardForm({ dashboard, drawer, changeInfo }:
<Box paddingTop={2}>
<Stack gap={2}>
<Button variant="secondary" onClick={drawer.onClose} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.save-provisioned-dashboard-form.cancel">Cancel</Trans>
</Button>
<ClipboardButton icon="copy" getText={() => dashboardJSON}>
Copy JSON to clipboard
<Trans i18nKey="dashboard-scene.save-provisioned-dashboard-form.copy-json-to-clipboard">
Copy JSON to clipboard
</Trans>
</ClipboardButton>
<Button type="submit" onClick={saveToFile}>
Save JSON to file
<Trans i18nKey="dashboard-scene.save-provisioned-dashboard-form.save-json-to-file">
Save JSON to file
</Trans>
</Button>
</Stack>
</Box>

@ -56,7 +56,10 @@ export function NameAlreadyExistsError({ cancelButton, saveButton }: NameAlready
</p>
</Alert>
) : (
<Alert title="Name already exists" severity="error">
<Alert
title={t('dashboard-scene.name-already-exists-error.title-name-already-exists', 'Name already exists')}
severity="error"
>
<p>
A dashboard with the same name in selected folder already exists. Would you still like to save this dashboard?
</p>

@ -8,6 +8,7 @@ import {
VizPanel,
} from '@grafana/scenes';
import { Dropdown, Icon, Menu, PanelChrome, ToolbarButton } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getPanelLinks } from './PanelMenuBehavior';
@ -56,7 +57,11 @@ function VizPanelLinksRenderer({ model }: SceneComponentProps<VizPanelLinks>) {
return <menu.Component model={menu} key={menu.state.key} />;
}}
>
<ToolbarButton icon="external-link-alt" iconSize="md" aria-label="panel links" />
<ToolbarButton
icon="external-link-alt"
iconSize="md"
aria-label={t('dashboard-scene.viz-panel-links-renderer.aria-label-panel-links', 'Panel links')}
/>
</Dropdown>
);
}

@ -1,4 +1,5 @@
import { ConfirmModal } from '@grafana/ui';
import { t } from 'app/core/internationalization';
interface Props {
isOpen: boolean;
@ -9,7 +10,7 @@ interface Props {
export const UnlinkModal = ({ isOpen, onConfirm, onDismiss }: Props) => {
return (
<ConfirmModal
title="Do you really want to unlink this panel?"
title={t('dashboard-scene.unlink-modal.title-really-unlink-panel', 'Do you really want to unlink this panel?')}
icon="question-circle"
body="If you unlink this panel, you will be able to edit it without affecting any other dashboards.
However, once you make a change you will not be able to revert to its original reusable panel."

@ -111,7 +111,15 @@ export function DeleteDashboardModal({ dashboardTitle, onConfirm, onClose }: Del
function ProvisionedDeleteModal({ dashboardId, onClose }: ProvisionedDeleteModalProps) {
return (
<Modal isOpen={true} title="Cannot delete provisioned dashboard" icon="trash-alt" onDismiss={onClose}>
<Modal
isOpen={true}
title={t(
'dashboard-scene.provisioned-delete-modal.title-cannot-delete-provisioned-dashboard',
'Cannot delete provisioned dashboard'
)}
icon="trash-alt"
onDismiss={onClose}
>
<p>
This dashboard is managed by Grafana provisioning and cannot be deleted. Remove the dashboard from the config
file to delete it.
@ -134,7 +142,7 @@ function ProvisionedDeleteModal({ dashboardId, onClose }: ProvisionedDeleteModal
</p>
<Modal.ButtonRow>
<Button variant="primary" onClick={onClose}>
OK
<Trans i18nKey="dashboard-scene.provisioned-delete-modal.ok">OK</Trans>
</Button>
</Modal.ButtonRow>
</Modal>

@ -6,7 +6,7 @@ import { SceneComponentProps, SceneObjectBase, sceneUtils } from '@grafana/scene
import { Dashboard } from '@grafana/schema';
import { Alert, Box, Button, CodeEditor, Stack, useStyles2 } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { getPrettyJSON } from 'app/features/inspector/utils/utils';
import { DashboardDTO, SaveDashboardResponseDTO } from 'app/types';
@ -123,7 +123,7 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
const cancelButton = (
<Button variant="secondary" onClick={() => setIsSaving(false)} fill="outline">
Cancel
<Trans i18nKey="dashboard-scene.json-model-edit-view.cancel-button.cancel">Cancel</Trans>
</Button>
);
const styles = useStyles2(getStyles);
@ -132,8 +132,18 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
if (error && isSaving) {
if (isVersionMismatchError(error)) {
return (
<Alert title="Someone else has updated this dashboard" severity="error">
<p>Would you still like to save this dashboard?</p>
<Alert
title={t(
'dashboard-scene.json-model-edit-view.render-save-button-and-error.title-someone-else-has-updated-this-dashboard',
'Someone else has updated this dashboard'
)}
severity="error"
>
<p>
<Trans i18nKey="dashboard-scene.json-model-edit-view.render-save-button-and-error.would-still-dashboard">
Would you still like to save this dashboard?
</Trans>
</p>
<Box paddingTop={2}>
<Stack alignItems="center">
{cancelButton}
@ -150,7 +160,13 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
if (isPluginDashboardError(error)) {
return (
<Alert title="Plugin dashboard" severity="error">
<Alert
title={t(
'dashboard-scene.json-model-edit-view.render-save-button-and-error.title-plugin-dashboard',
'Plugin dashboard'
)}
severity="error"
>
<p>
Your changes will be lost when you update the plugin. Use <strong>Save As</strong> to create custom
version.
@ -166,7 +182,13 @@ export class JsonModelEditView extends SceneObjectBase<JsonModelEditViewState> i
return (
<>
{error && isSaving && (
<Alert title="Failed to save dashboard" severity="error">
<Alert
title={t(
'dashboard-scene.json-model-edit-view.render-save-button-and-error.title-failed-to-save-dashboard',
'Failed to save dashboard'
)}
severity="error"
>
<p>{error.message}</p>
</Alert>
)}

@ -16,7 +16,7 @@ import { VizPanel } from '@grafana/scenes';
import { AnnotationPanelFilter } from '@grafana/schema/src/raw/dashboard/x/dashboard_types.gen';
import { Button, Checkbox, Field, FieldSet, Input, MultiSelect, Select, useStyles2, Stack, Alert } from '@grafana/ui';
import { ColorValueEditor } from 'app/core/components/OptionsUI/color';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import StandardAnnotationQueryEditor from 'app/features/annotations/components/StandardAnnotationQueryEditor';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
@ -171,7 +171,7 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
return (
<div>
<FieldSet className={styles.settingsForm}>
<Field label="Name">
<Field label={t('dashboard-scene.annotation-settings-edit.label-name', 'Name')}>
<Input
data-testid={selectors.pages.Dashboard.Settings.Annotations.Settings.name}
name="name"
@ -181,17 +181,32 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
onChange={onNameChange}
/>
</Field>
<Field label="Data source" htmlFor="data-source-picker">
<Field
label={t('dashboard-scene.annotation-settings-edit.label-data-source', 'Data source')}
htmlFor="data-source-picker"
>
<DataSourcePicker annotations variables current={annotation.datasource} onChange={onDataSourceChange} />
</Field>
{!ds?.meta.annotations && (
<Alert title="No annotation support for this data source" severity="error">
<Alert
title={t(
'dashboard-scene.annotation-settings-edit.title-annotation-support-source',
'No annotation support for this data source'
)}
severity="error"
>
<Trans i18nKey="errors.dashboard-settings.annotations.datasource">
The selected data source does not support annotations. Please select a different data source.
</Trans>
</Alert>
)}
<Field label="Enabled" description="When enabled the annotation query is issued every dashboard refresh">
<Field
label={t('dashboard-scene.annotation-settings-edit.label-enabled', 'Enabled')}
description={t(
'dashboard-scene.annotation-settings-edit.description-enabled-annotation-query-issued-every-dashboard',
'When enabled the annotation query is issued every dashboard refresh'
)}
>
<Checkbox
name="enable"
id="enable"
@ -201,7 +216,7 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
/>
</Field>
<Field
label="Hidden"
label={t('dashboard-scene.annotation-settings-edit.label-hidden', 'Hidden')}
description="Annotation queries can be toggled on or off at the top of the dashboard. With this option checked this toggle will be hidden."
>
<Checkbox
@ -212,12 +227,21 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
data-testid={selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.hide}
/>
</Field>
<Field label="Color" description="Color to use for the annotation event markers">
<Field
label={t('dashboard-scene.annotation-settings-edit.label-color', 'Color')}
description={t(
'dashboard-scene.annotation-settings-edit.description-color-annotation-event-markers',
'Color to use for the annotation event markers'
)}
>
<Stack>
<ColorValueEditor value={annotation?.iconColor} onChange={onColorChange} />
</Stack>
</Field>
<Field label="Show in" data-testid={selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.showInLabel}>
<Field
label={t('dashboard-scene.annotation-settings-edit.label-show-in', 'Show in')}
data-testid={selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.showInLabel}
>
<>
<Select
options={panelFilters}
@ -231,7 +255,7 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
value={selectablePanels.filter((panel) => annotation.filter?.ids.includes(panel.value!))}
onChange={onAddFilterPanelID}
isClearable={true}
placeholder="Choose panels"
placeholder={t('dashboard-scene.annotation-settings-edit.placeholder-choose-panels', 'Choose panels')}
width={100}
closeMenuOnSelect={false}
className={styles.select}
@ -242,7 +266,9 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
</Field>
</FieldSet>
<FieldSet>
<h3 className="page-heading">Query</h3>
<h3 className="page-heading">
<Trans i18nKey="dashboard-scene.annotation-settings-edit.query">Query</Trans>
</h3>
{ds?.annotations && dsi && (
<StandardAnnotationQueryEditor
datasource={ds}
@ -266,7 +292,7 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
onClick={onDeleteAndLeavePage}
data-testid={selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.delete}
>
Delete
<Trans i18nKey="dashboard-scene.annotation-settings-edit.delete">Delete</Trans>
</Button>
)}
<Button
@ -274,7 +300,7 @@ export const AnnotationSettingsEdit = ({ annotation, editIndex, panels, onUpdate
onClick={onBackToList}
data-testid={selectors.pages.Dashboard.Settings.Annotations.NewAnnotation.apply}
>
Back to list
<Trans i18nKey="dashboard-scene.annotation-settings-edit.back-to-list">Back to list</Trans>
</Button>
</Stack>
</div>

@ -44,8 +44,12 @@ export const AnnotationSettingsList = ({ annotations, onNew, onEdit, onMove, onD
<table role="grid" className="filter-table filter-table--hover">
<thead>
<tr>
<th>Query name</th>
<th>Data source</th>
<th>
<Trans i18nKey="dashboard-scene.annotation-settings-list.query-name">Query name</Trans>
</th>
<th>
<Trans i18nKey="dashboard-scene.annotation-settings-list.data-source">Data source</Trans>
</th>
<th colSpan={3}></th>
</tr>
</thead>
@ -70,7 +74,11 @@ export const AnnotationSettingsList = ({ annotations, onNew, onEdit, onMove, onD
</td>
<td role="gridcell" style={{ width: '1%' }}>
{idx !== 0 && (
<IconButton name="arrow-up" onClick={() => onMove(idx, MoveDirection.UP)} tooltip="Move up" />
<IconButton
name="arrow-up"
onClick={() => onMove(idx, MoveDirection.UP)}
tooltip={t('dashboard-scene.annotation-settings-list.tooltip-move-up', 'Move up')}
/>
)}
</td>
<td role="gridcell" style={{ width: '1%' }}>
@ -78,7 +86,7 @@ export const AnnotationSettingsList = ({ annotations, onNew, onEdit, onMove, onD
<IconButton
name="arrow-down"
onClick={() => onMove(idx, MoveDirection.DOWN)}
tooltip="Move down"
tooltip={t('dashboard-scene.annotation-settings-list.tooltip-move-down', 'Move down')}
/>
) : null}
</td>
@ -136,7 +144,7 @@ export const AnnotationSettingsList = ({ annotations, onNew, onEdit, onMove, onD
data-testid={selectors.pages.Dashboard.Settings.Annotations.List.addAnnotationCTAV2}
onClick={onNew}
>
New query
<Trans i18nKey="dashboard-scene.annotation-settings-list.new-query">New query</Trans>
</ListNewButton>
)}
</Stack>

@ -3,6 +3,7 @@ import * as React from 'react';
import { SelectableValue } from '@grafana/data';
import { DashboardLink } from '@grafana/schema';
import { CollapsableSection, TagsInput, Select, Field, Input, Checkbox, Button } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { LINK_ICON_MAP, NEW_LINK } from './utils';
@ -54,55 +55,81 @@ export function DashboardLinkForm({ link, onUpdate, onGoBack }: DashboardLinkFor
return (
<div style={{ maxWidth: '600px' }}>
<Field label="Title">
<Field label={t('dashboard-scene.dashboard-link-form.label-title', 'Title')}>
<Input name="title" id="title" value={link.title} onChange={onChange} autoFocus={isNew} />
</Field>
<Field label="Type">
<Field label={t('dashboard-scene.dashboard-link-form.label-type', 'Type')}>
<Select inputId="link-type-input" value={link.type} options={linkTypeOptions} onChange={onTypeChange} />
</Field>
{link.type === 'dashboards' && (
<>
<Field label="With tags">
<Field label={t('dashboard-scene.dashboard-link-form.label-with-tags', 'With tags')}>
<TagsInput tags={link.tags} onChange={onTagsChange} />
</Field>
</>
)}
{link.type === 'link' && (
<>
<Field label="URL">
<Field label={t('dashboard-scene.dashboard-link-form.label-url', 'URL')}>
<Input name="url" value={link.url} onChange={onChange} />
</Field>
<Field label="Tooltip">
<Input name="tooltip" value={link.tooltip} onChange={onChange} placeholder="Open dashboard" />
<Field label={t('dashboard-scene.dashboard-link-form.label-tooltip', 'Tooltip')}>
<Input
name="tooltip"
value={link.tooltip}
onChange={onChange}
placeholder={t('dashboard-scene.dashboard-link-form.placeholder-open-dashboard', 'Open dashboard')}
/>
</Field>
<Field label="Icon">
<Field label={t('dashboard-scene.dashboard-link-form.label-icon', 'Icon')}>
<Select value={link.icon} options={linkIconOptions} onChange={onIconChange} />
</Field>
</>
)}
<CollapsableSection label="Options" isOpen={true}>
<CollapsableSection label={t('dashboard-scene.dashboard-link-form.label-options', 'Options')} isOpen={true}>
{link.type === 'dashboards' && (
<Field>
<Checkbox label="Show as dropdown" name="asDropdown" value={link.asDropdown} onChange={onChange} />
<Checkbox
label={t('dashboard-scene.dashboard-link-form.label-show-as-dropdown', 'Show as dropdown')}
name="asDropdown"
value={link.asDropdown}
onChange={onChange}
/>
</Field>
)}
<Field>
<Checkbox label="Include current time range" name="keepTime" value={link.keepTime} onChange={onChange} />
<Checkbox
label={t(
'dashboard-scene.dashboard-link-form.label-include-current-time-range',
'Include current time range'
)}
name="keepTime"
value={link.keepTime}
onChange={onChange}
/>
</Field>
<Field>
<Checkbox
label="Include current template variable values"
label={t(
'dashboard-scene.dashboard-link-form.label-include-current-template-variable-values',
'Include current template variable values'
)}
name="includeVars"
value={link.includeVars}
onChange={onChange}
/>
</Field>
<Field>
<Checkbox label="Open link in new tab" name="targetBlank" value={link.targetBlank} onChange={onChange} />
<Checkbox
label={t('dashboard-scene.dashboard-link-form.label-open-link-in-new-tab', 'Open link in new tab')}
name="targetBlank"
value={link.targetBlank}
onChange={onChange}
/>
</Field>
</CollapsableSection>
<Button variant="secondary" onClick={onGoBack}>
Back to list
<Trans i18nKey="dashboard-scene.dashboard-link-form.back-to-list">Back to list</Trans>
</Button>
</div>
);

@ -57,8 +57,12 @@ export function DashboardLinkList({
<table role="grid" className="filter-table filter-table--hover">
<thead>
<tr>
<th>Type</th>
<th>Info</th>
<th>
<Trans i18nKey="dashboard-scene.dashboard-link-list.type">Type</Trans>
</th>
<th>
<Trans i18nKey="dashboard-scene.dashboard-link-list.info">Info</Trans>
</th>
<th colSpan={3} />
</tr>
</thead>
@ -77,16 +81,28 @@ export function DashboardLinkList({
</td>
<td style={{ width: '1%' }} role="gridcell">
{idx !== 0 && (
<IconButton name="arrow-up" onClick={() => onOrderChange(idx, -1)} tooltip="Move link up" />
<IconButton
name="arrow-up"
onClick={() => onOrderChange(idx, -1)}
tooltip={t('dashboard-scene.dashboard-link-list.tooltip-move-link-up', 'Move link up')}
/>
)}
</td>
<td style={{ width: '1%' }} role="gridcell">
{links.length > 1 && idx !== links.length - 1 ? (
<IconButton name="arrow-down" onClick={() => onOrderChange(idx, 1)} tooltip="Move link down" />
<IconButton
name="arrow-down"
onClick={() => onOrderChange(idx, 1)}
tooltip={t('dashboard-scene.dashboard-link-list.tooltip-move-link-down', 'Move link down')}
/>
) : null}
</td>
<td style={{ width: '1%' }} role="gridcell">
<IconButton name="copy" onClick={() => onDuplicate(link)} tooltip="Copy link" />
<IconButton
name="copy"
onClick={() => onDuplicate(link)}
tooltip={t('dashboard-scene.dashboard-link-list.tooltip-copy-link', 'Copy link')}
/>
</td>
<td style={{ width: '1%' }} role="gridcell">
<DeleteButton
@ -100,7 +116,7 @@ export function DashboardLinkList({
</tbody>
</table>
<Button className={styles.newLinkButton} icon="plus" onClick={onNew}>
New link
<Trans i18nKey="dashboard-scene.dashboard-link-list.new-link">New link</Trans>
</Button>
</>
);

@ -9,6 +9,7 @@ import { reportInteraction } from '@grafana/runtime';
import { SceneVariable } from '@grafana/scenes';
import { VariableHide, defaultVariableModel } from '@grafana/schema';
import { Button, LoadingPlaceholder, ConfirmModal, ModalsController, Stack, useStyles2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { VariableHideSelect } from 'app/features/dashboard-scene/settings/variables/components/VariableHideSelect';
import { VariableLegend } from 'app/features/dashboard-scene/settings/variables/components/VariableLegend';
import { VariableTextAreaField } from 'app/features/dashboard-scene/settings/variables/components/VariableTextAreaField';
@ -76,14 +77,21 @@ export function VariableEditorForm({
};
return (
<form aria-label="Variable editor Form">
<form
aria-label={t('dashboard-scene.variable-editor-form.aria-label-variable-editor-form', 'Variable editor form')}
>
<VariableTypeSelect onChange={onVariableTypeChange} type={type} />
<VariableLegend>General</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.variable-editor-form.general">General</Trans>
</VariableLegend>
<VariableTextField
name="Name"
description="The name of the template variable. (Max. 50 characters)"
placeholder="Variable name"
description={t(
'dashboard-scene.variable-editor-form.description-template-variable-characters',
'The name of the template variable. (Max. 50 characters)'
)}
placeholder={t('dashboard-scene.variable-editor-form.placeholder-variable-name', 'Variable name')}
defaultValue={name ?? ''}
onChange={onNameChange}
onBlur={onNameBlur}
@ -95,8 +103,11 @@ export function VariableEditorForm({
/>
<VariableTextField
name="Label"
description="Optional display name"
placeholder="Label name"
description={t(
'dashboard-scene.variable-editor-form.description-optional-display-name',
'Optional display name'
)}
placeholder={t('dashboard-scene.variable-editor-form.placeholder-label-name', 'Label name')}
defaultValue={label ?? ''}
onBlur={onLabelBlur}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2}
@ -104,7 +115,7 @@ export function VariableEditorForm({
<VariableTextAreaField
name="Description"
defaultValue={description ?? ''}
placeholder="Descriptive text"
placeholder={t('dashboard-scene.variable-editor-form.placeholder-descriptive-text', 'Descriptive text')}
onBlur={onDescriptionBlur}
width={52}
/>
@ -133,7 +144,7 @@ export function VariableEditorForm({
});
}}
>
Delete
<Trans i18nKey="dashboard-scene.variable-editor-form.delete">Delete</Trans>
</Button>
)}
</ModalsController>
@ -142,7 +153,7 @@ export function VariableEditorForm({
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.General.applyButton}
onClick={onGoBack}
>
Back to list
<Trans i18nKey="dashboard-scene.variable-editor-form.back-to-list">Back to list</Trans>
</Button>
{isHasVariableOptions && (
@ -153,7 +164,10 @@ export function VariableEditorForm({
onClick={onRunQuery}
>
{runQueryState.loading ? (
<LoadingPlaceholder className={styles.loadingPlaceHolder} text="Running query..." />
<LoadingPlaceholder
className={styles.loadingPlaceHolder}
text={t('dashboard-scene.variable-editor-form.text-running-query', 'Running query...')}
/>
) : (
`Run query`
)}

@ -57,8 +57,12 @@ export function VariableEditorList({
>
<thead>
<tr>
<th>Variable</th>
<th>Definition</th>
<th>
<Trans i18nKey="dashboard-scene.variable-editor-list.variable">Variable</Trans>
</th>
<th>
<Trans i18nKey="dashboard-scene.variable-editor-list.definition">Definition</Trans>
</th>
<th colSpan={5} />
</tr>
</thead>
@ -90,7 +94,7 @@ export function VariableEditorList({
<Stack>
<VariablesDependenciesButton variables={variables} />
<Button data-testid={selectors.pages.Dashboard.Settings.Variables.List.newButton} onClick={onAdd} icon="plus">
New variable
<Trans i18nKey="dashboard-scene.variable-editor-list.new-variable">New variable</Trans>
</Button>
</Stack>
</Stack>

@ -7,6 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { reportInteraction } from '@grafana/runtime';
import { SceneVariable } from '@grafana/scenes';
import { Button, ConfirmModal, Icon, IconButton, Tooltip, useStyles2, useTheme2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { VariableUsagesButton } from '../../variables/VariableUsagesButton';
import { UsagesToNetwork, VariableUsageTree, getVariableUsages } from '../../variables/utils';
@ -101,7 +102,7 @@ export function VariableEditorListRow({
propsOnDuplicate(identifier);
}}
name="copy"
tooltip="Duplicate variable"
tooltip={t('dashboard-scene.variable-editor-list-row.tooltip-duplicate-variable', 'Duplicate variable')}
data-testid={selectors.pages.Dashboard.Settings.Variables.List.tableRowDuplicateButtons(
variableState.name
)}
@ -112,14 +113,14 @@ export function VariableEditorListRow({
setShowDeleteModal(true);
}}
name="trash-alt"
tooltip="Remove variable"
tooltip={t('dashboard-scene.variable-editor-list-row.tooltip-remove-variable', 'Remove variable')}
data-testid={selectors.pages.Dashboard.Settings.Variables.List.tableRowRemoveButtons(
variableState.name
)}
/>
<ConfirmModal
isOpen={showDeleteModal}
title="Delete variable"
title={t('dashboard-scene.variable-editor-list-row.title-delete-variable', 'Delete variable')}
body={`Are you sure you want to delete: ${variableState.name}?`}
confirmText="Delete variable"
onConfirm={onDeleteVariable}
@ -149,7 +150,10 @@ function VariableCheckIndicator({ passed }: VariableCheckIndicatorProps): ReactE
<Icon
name="check"
className={styles.iconPassed}
aria-label="This variable is referenced by other variables or dashboard."
aria-label={t(
'dashboard-scene.variable-check-indicator.aria-label-variable-referenced-other-variables-dashboard',
'This variable is referenced by other variables or dashboard.'
)}
/>
</Tooltip>
);
@ -160,7 +164,10 @@ function VariableCheckIndicator({ passed }: VariableCheckIndicatorProps): ReactE
<Icon
name="exclamation-triangle"
className={styles.iconFailed}
aria-label="This variable is not referenced by any variable or dashboard."
aria-label={t(
'dashboard-scene.variable-check-indicator.aria-label-variable-referenced-dashboard',
'This variable is not referenced by any variable or dashboard.'
)}
/>
</Tooltip>
);

@ -4,6 +4,7 @@ import { DataSourceInstanceSettings, MetricFindValue, readCSV } from '@grafana/d
import { selectors } from '@grafana/e2e-selectors';
import { DataSourceRef } from '@grafana/schema';
import { Alert, CodeEditor, Field, Switch } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { VariableCheckboxField } from './VariableCheckboxField';
@ -43,8 +44,13 @@ export function AdHocVariableForm({
return (
<>
<VariableLegend>Ad-hoc options</VariableLegend>
<Field label="Data source" htmlFor="data-source-picker">
<VariableLegend>
<Trans i18nKey="dashboard-scene.ad-hoc-variable-form.adhoc-options">Ad-hoc options</Trans>
</VariableLegend>
<Field
label={t('dashboard-scene.ad-hoc-variable-form.label-data-source', 'Data source')}
htmlFor="data-source-picker"
>
<DataSourcePicker current={datasource} onChange={onDataSourceChange} width={30} variables={true} noDefault />
</Field>
@ -58,7 +64,17 @@ export function AdHocVariableForm({
{onDefaultKeysChange && (
<>
<Field label="Use static key dimensions" description="Provide dimensions as CSV: dimensionName, dimensionId">
<Field
label={t(
'dashboard-scene.ad-hoc-variable-form.label-use-static-key-dimensions',
'Use static key dimensions'
)}
description={t(
'dashboard-scene.ad-hoc-variable-form.description-provide-dimensions-as-csv-dimension-name-dimension-id',
'Provide dimensions as CSV: {{name}}, {{value}}',
{ name: 'dimensionName', value: 'dimensionId' }
)}
>
<Switch
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.AdHocFiltersVariable.modeToggle}
value={defaultKeys !== undefined}
@ -90,7 +106,10 @@ export function AdHocVariableForm({
<VariableCheckboxField
value={allowCustomValue ?? true}
name="Allow custom values"
description="Enables users to add custom values to the list"
description={t(
'dashboard-scene.ad-hoc-variable-form.description-enables-users-custom-values',
'Enables users to add custom values to the list'
)}
onChange={onAllowCustomValueChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch}
/>

@ -1,6 +1,7 @@
import { FormEvent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from 'app/core/internationalization';
import { VariableLegend } from './VariableLegend';
import { VariableTextField } from './VariableTextField';
@ -13,11 +14,13 @@ interface ConstantVariableFormProps {
export function ConstantVariableForm({ onChange, constantValue }: ConstantVariableFormProps) {
return (
<>
<VariableLegend>Constant options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.constant-variable-form.constant-options">Constant options</Trans>
</VariableLegend>
<VariableTextField
defaultValue={constantValue}
name="Value"
placeholder="your metric prefix"
placeholder={t('dashboard-scene.constant-variable-form.placeholder-your-metric-prefix', 'Your metric prefix')}
onBlur={onChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInputV2}
width={30}

@ -1,6 +1,7 @@
import { FormEvent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Trans } from 'app/core/internationalization';
import { VariableLegend } from '../components/VariableLegend';
import { VariableTextAreaField } from '../components/VariableTextAreaField';
@ -36,18 +37,23 @@ export function CustomVariableForm({
}: CustomVariableFormProps) {
return (
<>
<VariableLegend>Custom options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.custom-variable-form.custom-options">Custom options</Trans>
</VariableLegend>
<VariableTextAreaField
name="Values separated by comma"
defaultValue={query}
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="1, 10, mykey : myvalue, myvalue, escaped\,value"
onBlur={onQueryChange}
required
width={52}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.customValueInput}
/>
<VariableLegend>Selection options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.custom-variable-form.selection-options">Selection options</Trans>
</VariableLegend>
<SelectionOptionsForm
multi={multi}
includeAll={includeAll}

@ -2,6 +2,7 @@ import { FormEvent } from 'react';
import { SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans } from 'app/core/internationalization';
import { SelectionOptionsForm } from './SelectionOptionsForm';
import { VariableLegend } from './VariableLegend';
@ -45,7 +46,9 @@ export function DataSourceVariableForm({
return (
<>
<VariableLegend>Data source options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.data-source-variable-form.data-source-options">Data source options</Trans>
</VariableLegend>
<VariableSelectField
name="Type"
value={typeValue}
@ -69,7 +72,9 @@ export function DataSourceVariableForm({
}
/>
<VariableLegend>Selection options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.data-source-variable-form.selection-options">Selection options</Trans>
</VariableLegend>
<SelectionOptionsForm
multi={multi}
includeAll={includeAll}

@ -4,6 +4,7 @@ import { DataSourceInstanceSettings, MetricFindValue, readCSV } from '@grafana/d
import { selectors } from '@grafana/e2e-selectors';
import { DataSourceRef } from '@grafana/schema';
import { Alert, CodeEditor, Field, Switch } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { VariableCheckboxField } from './VariableCheckboxField';
@ -43,8 +44,13 @@ export function GroupByVariableForm({
return (
<>
<VariableLegend>Group by options</VariableLegend>
<Field label="Data source" htmlFor="data-source-picker">
<VariableLegend>
<Trans i18nKey="dashboard-scene.group-by-variable-form.group-by-options">Group by options</Trans>
</VariableLegend>
<Field
label={t('dashboard-scene.group-by-variable-form.label-data-source', 'Data source')}
htmlFor="data-source-picker"
>
<DataSourcePicker current={datasource} onChange={onDataSourceChange} width={30} variables={true} noDefault />
</Field>
@ -56,7 +62,17 @@ export function GroupByVariableForm({
/>
) : null}
<Field label="Use static Group By dimensions" description="Provide dimensions as CSV: dimensionName, dimensionId">
<Field
label={t(
'dashboard-scene.group-by-variable-form.label-use-static-group-by-dimensions',
'Use static group dimensions'
)}
description={t(
'dashboard-scene.group-by-variable-form.description-provide-dimensions-as-csv-dimension-name-dimension-id',
'Provide dimensions as CSV: {{name}}, {{value}}',
{ name: 'dimensionName', value: 'dimensionId' }
)}
>
<Switch
data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.GroupByVariable.modeToggle}
value={defaultOptions !== undefined}
@ -85,7 +101,10 @@ export function GroupByVariableForm({
<VariableCheckboxField
value={allowCustomValue}
name="Allow custom values"
description="Enables users to add custom values to the list"
description={t(
'dashboard-scene.group-by-variable-form.description-enables-users-custom-values',
'Enables users to add custom values to the list'
)}
onChange={onAllowCustomValueChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch}
/>

@ -4,6 +4,7 @@ import { ChangeEvent, FormEvent } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { VariableCheckboxField } from './VariableCheckboxField';
import { VariableLegend } from './VariableLegend';
@ -41,10 +42,13 @@ export function IntervalVariableForm({
return (
<>
<VariableLegend>Interval options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.interval-variable-form.interval-options">Interval options</Trans>
</VariableLegend>
<VariableTextField
defaultValue={intervals}
name="Values"
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="1m,10m,1h,6h,1d,7d"
onBlur={onIntervalsChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.IntervalVariable.intervalsValueInput}
@ -73,7 +77,11 @@ export function IntervalVariableForm({
<VariableTextField
value={autoMinInterval}
name="Min interval"
description="The calculated value will not go below this threshold"
description={t(
'dashboard-scene.interval-variable-form.description-calculated-value-below-threshold',
'The calculated value will not go below this threshold'
)}
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="10s"
onChange={onAutoMinIntervalChanged}
width={11}

@ -2,6 +2,7 @@ import { DataSourceApi, LoadingState, TimeRange } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { QueryVariable } from '@grafana/scenes';
import { Text, Box } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { isLegacyQueryEditor, isQueryEditor } from 'app/features/variables/guard';
import { VariableQueryEditorType } from 'app/features/variables/types';
@ -37,7 +38,9 @@ export function QueryEditor({
if (VariableQueryEditor && isLegacyQueryEditor(VariableQueryEditor, datasource)) {
return (
<Box marginBottom={2}>
<Text element={'h4'}>Query</Text>
<Text element={'h4'}>
<Trans i18nKey="dashboard-scene.query-editor.query">Query</Trans>
</Text>
<Box marginTop={1}>
<VariableQueryEditor
key={datasource.uid}
@ -54,7 +57,9 @@ export function QueryEditor({
if (VariableQueryEditor && isQueryEditor(VariableQueryEditor, datasource)) {
return (
<Box marginBottom={2}>
<Text element={'h4'}>Query</Text>
<Text element={'h4'}>
<Trans i18nKey="dashboard-scene.query-editor.query">Query</Trans>
</Text>
<Box marginTop={1}>
<VariableQueryEditor
key={datasource.uid}

@ -7,6 +7,7 @@ import { getDataSourceSrv } from '@grafana/runtime';
import { QueryVariable } from '@grafana/scenes';
import { DataSourceRef, VariableRefresh, VariableSort } from '@grafana/schema';
import { Field } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { QueryEditor } from 'app/features/dashboard-scene/settings/variables/components/QueryEditor';
import { SelectionOptionsForm } from 'app/features/dashboard-scene/settings/variables/components/SelectionOptionsForm';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
@ -81,8 +82,13 @@ export function QueryVariableEditorForm({
return (
<>
<VariableLegend>Query options</VariableLegend>
<Field label="Data source" htmlFor="data-source-picker">
<VariableLegend>
<Trans i18nKey="dashboard-scene.query-variable-editor-form.query-options">Query options</Trans>
</VariableLegend>
<Field
label={t('dashboard-scene.query-variable-editor-form.label-data-source', 'Data source')}
htmlFor="data-source-picker"
>
<DataSourcePicker current={datasourceRef} onChange={onDataSourceChange} variables={true} width={30} />
</Field>
@ -115,6 +121,7 @@ export function QueryVariableEditorForm({
).
</div>
}
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="/.*-(?<text>.*)-(?<value>.*)-.*/"
onBlur={onRegExChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2}
@ -133,7 +140,9 @@ export function QueryVariableEditorForm({
refresh={refresh}
/>
<VariableLegend>Selection options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.query-variable-editor-form.selection-options">Selection options</Trans>
</VariableLegend>
<SelectionOptionsForm
multi={!!isMulti}
includeAll={!!includeAll}

@ -2,6 +2,7 @@ import { ChangeEvent, FormEvent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Stack } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { VariableCheckboxField } from 'app/features/dashboard-scene/settings/variables/components/VariableCheckboxField';
import { VariableTextField } from 'app/features/dashboard-scene/settings/variables/components/VariableTextField';
@ -31,7 +32,10 @@ export function SelectionOptionsForm({
<VariableCheckboxField
value={multi}
name="Multi-value"
description="Enables multiple values to be selected at the same time"
description={t(
'dashboard-scene.selection-options-form.description-enables-multiple-values-selected',
'Enables multiple values to be selected at the same time'
)}
onChange={onMultiChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch}
/>
@ -39,7 +43,10 @@ export function SelectionOptionsForm({
<VariableCheckboxField
value={allowCustomValue ?? true}
name="Allow custom values"
description="Enables users to add custom values to the list"
description={t(
'dashboard-scene.selection-options-form.description-enables-users-custom-values',
'Enables users to add custom values to the list'
)}
onChange={onAllowCustomValueChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsAllowCustomValueSwitch}
/>
@ -47,7 +54,10 @@ export function SelectionOptionsForm({
<VariableCheckboxField
value={includeAll}
name="Include All option"
description="Enables an option to include all variables"
description={t(
'dashboard-scene.selection-options-form.description-enables-option-include-variables',
'Enables an option to include all variables'
)}
onChange={onIncludeAllChange}
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch}
/>
@ -56,7 +66,6 @@ export function SelectionOptionsForm({
defaultValue={allValue ?? ''}
onBlur={onAllValueChange}
name="Custom all value"
placeholder="blank = auto"
testId={selectors.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput}
/>
)}

@ -1,6 +1,7 @@
import { FormEvent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from 'app/core/internationalization';
import { VariableLegend } from 'app/features/dashboard-scene/settings/variables/components/VariableLegend';
import { VariableTextField } from 'app/features/dashboard-scene/settings/variables/components/VariableTextField';
@ -14,12 +15,14 @@ interface TextBoxVariableFormProps {
export function TextBoxVariableForm({ defaultValue, value, onChange, onBlur }: TextBoxVariableFormProps) {
return (
<>
<VariableLegend>Text options</VariableLegend>
<VariableLegend>
<Trans i18nKey="dashboard-scene.text-box-variable-form.text-options">Text options</Trans>
</VariableLegend>
<VariableTextField
value={value}
defaultValue={defaultValue}
name="Default value"
placeholder="default value, if any"
placeholder={t('dashboard-scene.text-box-variable-form.placeholder-default-value-if-any', '(optional)')}
onChange={onChange}
onBlur={onBlur}
width={30}

@ -2,6 +2,7 @@ import { PropsWithChildren, useMemo } from 'react';
import { VariableType, VariableHide } from '@grafana/data';
import { Field, RadioButtonGroup } from '@grafana/ui';
import { t } from 'app/core/internationalization';
interface Props {
onChange: (option: VariableHide) => void;
@ -23,7 +24,7 @@ export function VariableHideSelect({ onChange, hide, type }: PropsWithChildren<P
}
return (
<Field label="Show on dashboard">
<Field label={t('dashboard-scene.variable-hide-select.label-show-on-dashboard', 'Show on dashboard')}>
<RadioButtonGroup options={HIDE_OPTIONS} onChange={onChange} value={value} />
</Field>
);

@ -5,6 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { VariableValueOption } from '@grafana/scenes';
import { Button, InlineFieldRow, InlineLabel, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
export interface VariableValuesPreviewProps {
options: VariableValueOption[];
@ -29,7 +30,9 @@ export const VariableValuesPreview = ({ options }: VariableValuesPreviewProps) =
return (
<div style={{ display: 'flex', flexDirection: 'column', marginTop: '16px' }}>
<h5>Preview of values</h5>
<h5>
<Trans i18nKey="dashboard-scene.variable-values-preview.preview-of-values">Preview of values</Trans>
</h5>
<InlineFieldRow>
{previewOptions.map((o, index) => (
<InlineFieldRow key={`${o.value}-${index}`} className={styles.optionContainer}>
@ -41,13 +44,8 @@ export const VariableValuesPreview = ({ options }: VariableValuesPreviewProps) =
</InlineFieldRow>
{options.length > previewLimit && (
<InlineFieldRow className={styles.optionContainer}>
<Button
onClick={showMoreOptions}
variant="secondary"
size="sm"
aria-label="Variable editor Preview of Values Show More link"
>
Show more
<Button onClick={showMoreOptions} variant="secondary" size="sm">
<Trans i18nKey="dashboard-scene.variable-values-preview.show-more">Show more</Trans>
</Button>
</InlineFieldRow>
)}

@ -1,5 +1,6 @@
import { ConfirmModal } from '@grafana/ui';
import { useAppNotification } from 'app/core/copy/appNotification';
import { t } from 'app/core/internationalization';
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
import { DecoratedRevisionModel } from '../VersionsEditView';
@ -29,7 +30,7 @@ export const RevertDashboardModal = ({ hideModal, onRestore, version }: RevertDa
return (
<ConfirmModal
isOpen={true}
title="Restore Version"
title={t('dashboard-scene.revert-dashboard-modal.title-restore-version', 'Restore version')}
icon="history"
onDismiss={hideModal}
onConfirm={onRestoreDashboard}

@ -1,4 +1,5 @@
import { Tooltip, Button, Stack } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
type VersionsButtonsType = {
@ -26,12 +27,12 @@ export const VersionsHistoryButtons = ({
variant="secondary"
disabled={isLastPage}
>
Show more versions
<Trans i18nKey="dashboard-scene.versions-history-buttons.show-more-versions">Show more versions</Trans>
</Button>
)}
<Tooltip content="Select two versions to start comparing" placement="bottom">
<Button type="button" disabled={!canCompare} onClick={getDiff} icon="code-branch">
Compare versions
<Trans i18nKey="dashboard-scene.versions-history-buttons.compare-versions">Compare versions</Trans>
</Button>
</Tooltip>
</Stack>

@ -2,6 +2,7 @@ import { css, cx } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, ModalsController, CollapsableSection, useStyles2, Stack, Icon, Box } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { DecoratedRevisionModel } from '../VersionsEditView';
@ -62,7 +63,10 @@ export const VersionHistoryComparison = ({ baseInfo, newInfo, diffData, isNewLat
))}
<Box paddingTop={2}>
<CollapsableSection isOpen={false} label="View JSON Diff">
<CollapsableSection
isOpen={false}
label={t('dashboard-scene.version-history-comparison.label-view-json-diff', 'View JSON diff')}
>
<DiffViewer
oldValue={JSON.stringify(diffData.lhs, null, 2)}
newValue={JSON.stringify(diffData.rhs, null, 2)}

@ -3,6 +3,7 @@ import { noop } from 'lodash';
import { GrafanaTheme2 } from '@grafana/data';
import { Icon, IconButton, useStyles2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
type VersionHistoryHeaderProps = {
onClick?: () => void;
@ -21,10 +22,19 @@ export const VersionHistoryHeader = ({
return (
<h3 className={styles.header}>
<IconButton name="arrow-left" size="xl" onClick={onClick} tooltip="Reset version" />
<IconButton
name="arrow-left"
size="xl"
onClick={onClick}
tooltip={t('dashboard-scene.version-history-header.tooltip-reset-version', 'Reset version')}
/>
<span>
Comparing {baseVersion} <Icon name="arrows-h" /> {newVersion}{' '}
{isNewLatest && <cite className="muted">(Latest)</cite>}
{isNewLatest && (
<cite className="muted">
<Trans i18nKey="dashboard-scene.version-history-header.latest">(Latest)</Trans>
</cite>
)}
</span>
</h3>
);

@ -3,6 +3,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Checkbox, Button, Tag, ModalsController, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
import { DecoratedRevisionModel } from '../VersionsEditView';
@ -25,10 +26,18 @@ export const VersionHistoryTable = ({ versions, canCompare, onCheck, onRestore }
<thead>
<tr>
<th className="width-4"></th>
<th className="width-4">Version</th>
<th className="width-14">Date</th>
<th className="width-10">Updated by</th>
<th>Notes</th>
<th className="width-4">
<Trans i18nKey="dashboard-scene.version-history-table.version">Version</Trans>
</th>
<th className="width-14">
<Trans i18nKey="dashboard-scene.version-history-table.date">Date</Trans>
</th>
<th className="width-10">
<Trans i18nKey="dashboard-scene.version-history-table.updated-by">Updated by</Trans>
</th>
<th>
<Trans i18nKey="dashboard-scene.version-history-table.notes">Notes</Trans>
</th>
<th></th>
</tr>
</thead>
@ -74,7 +83,7 @@ export const VersionHistoryTable = ({ versions, canCompare, onCheck, onRestore }
});
}}
>
Restore
<Trans i18nKey="dashboard-scene.version-history-table.restore">Restore</Trans>
</Button>
)}
</ModalsController>

@ -47,7 +47,7 @@ export default function ShareButton({ dashboard, panel }: { dashboard: Dashboard
</Button>
<Dropdown overlay={MenuActions} placement="bottom-end" onVisibleChange={onMenuClick}>
<Button
aria-label="share-dropdown-menu"
aria-label={t('dashboard-scene.share-button.aria-label-sharedropdownmenu', 'Toggle share menu')}
data-testid={newShareButtonSelector.arrowMenu}
size="sm"
icon={isOpen ? 'angle-up' : 'angle-down'}

@ -77,7 +77,12 @@ const EmailList = ({
/>
}
>
<IconButton name="ellipsis-v" aria-label="email-menu" variant="secondary" size="lg" />
<IconButton
name="ellipsis-v"
aria-label={t('dashboard-scene.email-list.aria-label-emailmenu', 'Toggle email menu')}
variant="secondary"
size="lg"
/>
</Dropdown>
</td>
</tr>

@ -2,6 +2,7 @@ import { useMemo } from 'react';
import { reportInteraction } from '@grafana/runtime';
import { IconButton } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { NetworkGraphModal } from 'app/features/variables/inspect/NetworkGraphModal';
import { UsagesToNetwork } from './utils';
@ -38,7 +39,7 @@ export const VariableUsagesButton = ({ id, usages, isAdhoc }: Props) => {
showModal();
}}
name="code-branch"
tooltip="Show usages"
tooltip={t('dashboard-scene.variable-usages-button.tooltip-show-usages', 'Show usages')}
/>
);
}}

@ -1849,6 +1849,45 @@
}
},
"dashboard-scene": {
"ad-hoc-variable-form": {
"adhoc-options": "Ad-hoc options",
"description-enables-users-custom-values": "Enables users to add custom values to the list",
"description-provide-dimensions-as-csv-dimension-name-dimension-id": "Provide dimensions as CSV: {{name}}, {{value}}",
"label-data-source": "Data source",
"label-use-static-key-dimensions": "Use static key dimensions"
},
"add-to-dashboard-form": {
"cancel": "Cancel",
"description-choose-where-to-add-the-panel": "Choose where to add the panel.",
"description-select-which-dashboard-panel-created": "Select in which dashboard the panel will be created.",
"label-dashboard": "Dashboard",
"label-target-dashboard": "Target dashboard",
"open-dashboard": "Open dashboard",
"open-in-new-tab": "Open in new tab",
"title-error-adding-the-panel": "Error adding the panel"
},
"annotation-settings-edit": {
"back-to-list": "Back to list",
"delete": "Delete",
"description-color-annotation-event-markers": "Color to use for the annotation event markers",
"description-enabled-annotation-query-issued-every-dashboard": "When enabled the annotation query is issued every dashboard refresh",
"label-color": "Color",
"label-data-source": "Data source",
"label-enabled": "Enabled",
"label-hidden": "Hidden",
"label-name": "Name",
"label-show-in": "Show in",
"placeholder-choose-panels": "Choose panels",
"query": "Query",
"title-annotation-support-source": "No annotation support for this data source"
},
"annotation-settings-list": {
"data-source": "Data source",
"new-query": "New query",
"query-name": "Query name",
"tooltip-move-down": "Move down",
"tooltip-move-up": "Move up"
},
"branch-validation-error": {
"cannot-contain-invalid-characters": "It cannot contain invalid characters: '~', '^', ':', '?', '*', '[', '\\\\', or ']'.",
"cannot-start-with": "It cannot start with '/' or end with '/', '.', or whitespace.",
@ -1856,6 +1895,43 @@
"it-cannot-contain-or": "It cannot contain '//' or '..'.",
"least-valid-character": "It must have at least one valid character."
},
"constant-variable-form": {
"constant-options": "Constant options",
"placeholder-your-metric-prefix": "Your metric prefix"
},
"custom-variable-form": {
"custom-options": "Custom options",
"selection-options": "Selection options"
},
"dashboard-add-pane": {
"aria-label-close-add-pane": "Close add pane"
},
"dashboard-edit-pane-renderer": {
"outline": "Outline"
},
"dashboard-link-form": {
"back-to-list": "Back to list",
"label-icon": "Icon",
"label-include-current-template-variable-values": "Include current template variable values",
"label-include-current-time-range": "Include current time range",
"label-open-link-in-new-tab": "Open link in new tab",
"label-options": "Options",
"label-show-as-dropdown": "Show as dropdown",
"label-title": "Title",
"label-tooltip": "Tooltip",
"label-type": "Type",
"label-url": "URL",
"label-with-tags": "With tags",
"placeholder-open-dashboard": "Open dashboard"
},
"dashboard-link-list": {
"info": "Info",
"new-link": "New link",
"tooltip-copy-link": "Copy link",
"tooltip-move-link-down": "Move link down",
"tooltip-move-link-up": "Move link up",
"type": "Type"
},
"dashboard-preview-banner": {
"not-saved": "The value is not yet saved in the Grafana database",
"not-yet-saved": "The value is not saved in the Grafana database",
@ -1867,17 +1943,160 @@
"value-not-saved": "The value is not yet saved in the Grafana database",
"view-pull-request-in-git-hub": "View pull request in GitHub"
},
"data-source-variable-form": {
"data-source-options": "Data source options",
"selection-options": "Selection options"
},
"description-label": {
"description": "Description"
},
"email-list": {
"aria-label-emailmenu": "Toggle email menu"
},
"empty-transformations-message": {
"add-transformation": "Add transformation"
},
"group-by-variable-form": {
"description-enables-users-custom-values": "Enables users to add custom values to the list",
"description-provide-dimensions-as-csv-dimension-name-dimension-id": "Provide dimensions as CSV: {{name}}, {{value}}",
"group-by-options": "Group by options",
"label-data-source": "Data source",
"label-use-static-group-by-dimensions": "Use static group dimensions"
},
"help-wizard": {
"copy-to-clipboard": "Copy to clipboard",
"label-randomize-data": "Randomize data",
"label-support-snapshot": "Support snapshot",
"label-template": "Template",
"randomize-field-names-label-field-names": "Field names",
"randomize-labels-label-labels": "Labels",
"randomize-string-values-label-string-values": "String values",
"title-complete-git-hub-comment-clipboard": "Copy a complete GitHub comment to the clipboard",
"title-get-help-with-this-panel": "Get help with this panel"
},
"inspect-data-tab": {
"no-data-found": "No data found"
},
"inspect-json-tab": {
"apply": "Apply"
},
"interval-variable-form": {
"description-calculated-value-below-threshold": "The calculated value will not go below this threshold",
"interval-options": "Interval options"
},
"json-model-edit-view": {
"cancel-button": {
"cancel": "Cancel"
},
"render-save-button-and-error": {
"title-failed-to-save-dashboard": "Failed to save dashboard",
"title-plugin-dashboard": "Plugin dashboard",
"title-someone-else-has-updated-this-dashboard": "Someone else has updated this dashboard",
"would-still-dashboard": "Would you still like to save this dashboard?"
}
},
"name-already-exists-error": {
"title-name-already-exists": "Name already exists"
},
"panel-data-alerting-tab-rendered": {
"alert": {
"title-errors-loading-rules": "Errors loading rules"
},
"text-loading-rules": "Loading rules...",
"title-dashboard-not-saved": "Dashboard not saved"
},
"panel-data-queries-tab-rendered": {
"add-query": "Add query"
},
"panel-data-transformations-tab-rendered": {
"add-another-transformation": "Add another transformation",
"delete-all-transformations": "Delete all transformations",
"title-delete-all-transformations": "Delete all transformations?"
},
"panel-edit-controls": {
"table-view-aria-label-toggletableview": "Toggle table view",
"table-view-label-table-view": "Table view"
},
"panel-inspect-renderer": {
"title-panel-plugin-not-loaded": "Panel plugin not loaded"
},
"panel-options-pane": {
"placeholder-search-options": "Search options"
},
"panel-viz-type-picker": {
"placeholder-search-for": "Search for...",
"title-close": "Close"
},
"provisioned-delete-modal": {
"ok": "OK",
"title-cannot-delete-provisioned-dashboard": "Cannot delete provisioned dashboard"
},
"provisioned-resource-delete-modal": {
"file-path": "File path:",
"managed-by-version-control": "This {type} is managed by version control and cannot be deleted. To remove it, delete it from the repository and synchronise to apply the changes.",
"ok": "OK",
"title-cannot-delete-provisioned-resource": "Cannot delete provisioned resource"
},
"query-editor": {
"query": "Query"
},
"query-variable-editor-form": {
"label-data-source": "Data source",
"query-options": "Query options",
"selection-options": "Selection options"
},
"revert-dashboard-modal": {
"title-restore-version": "Restore version"
},
"save-dashboard-as-form": {
"aria-label-save-dashboard-description-field": "Save dashboard description field",
"aria-label-save-dashboard-title-field": "Save dashboard title field",
"cancel-button": {
"cancel": "Cancel"
},
"label-copy-tags": "Copy tags",
"label-folder": "Folder",
"render-footer": {
"title-failed-to-save-dashboard": "Failed to save dashboard"
}
},
"save-dashboard-form": {
"aria-label-message": "message",
"cancel-button": {
"cancel": "Cancel"
},
"label-message": "Message",
"placeholder-describe-changes-optional": "Add a note to describe your changes (optional).",
"render-footer": {
"no-changes-to-save": "No changes to save",
"title-failed-to-save-dashboard": "Failed to save dashboard",
"title-plugin-dashboard": "Plugin dashboard",
"title-someone-else-has-updated-this-dashboard": "Someone else has updated this dashboard",
"would-still-dashboard": "Would you still like to save this dashboard?"
},
"title-dashboard-drastically-changed": "Dashboard drastically changed"
},
"save-dashboard-form-common-options": {
"save-refresh-description-current-refresh-default": "Will make the current refresh the new default",
"save-refresh-label-update-default-refresh-value": "Update default refresh value",
"save-timerange-label-update-default-time-range": "Update default time range",
"save-variables-description-current-values-default": "Will make the current values the new default",
"save-variables-label-update-default-variable-values": "Update default variable values"
},
"save-library-viz-panel-modal": {
"cancel": "Cancel",
"dashboard-name": "Dashboard name",
"discard": "Discard",
"loading-connected-dashboards": "Loading connected dashboards...",
"placeholder-search-affected-dashboards": "Search affected dashboards",
"update-all": "Update all"
},
"save-provisioned-dashboard-form": {
"api-error": "Error saving dashboard",
"api-success": "Dashboard changes saved",
"cancel": "Cancel",
"copy-json-message": "If you have direct access to the target, copy the JSON and paste it there.",
"copy-json-to-clipboard": "Copy JSON to clipboard",
"dashboard-comment-placeholder-describe-changes-optional": "Add a note to describe your changes (optional)",
"description-branch-name-in-git-hub": "Branch name in GitHub",
"description-inside-repository": "File path inside the repository (.json or .yaml)",
@ -1889,11 +2108,107 @@
"label-title": "Title",
"label-workflow": "Workflow",
"save": "Save",
"save-json-to-file": "Save JSON to file",
"saving": "Saving...",
"title-required": "Dashboard title is required",
"title-same-as-folder": "Dashboard name cannot be the same as the folder name",
"title-this-repository-is-read-only": "This repository is read only",
"title-validation-failed": "Dashboard title validation failed."
},
"scenes-new-rule-from-panel-button": {
"new-alert-rule": "New alert rule",
"title-no-alerting-capable-query-found": "No alerting capable query found"
},
"selection-options-form": {
"description-enables-multiple-values-selected": "Enables multiple values to be selected at the same time",
"description-enables-option-include-variables": "Enables an option to include all variables",
"description-enables-users-custom-values": "Enables users to add custom values to the list"
},
"share-button": {
"aria-label-sharedropdownmenu": "Toggle share menu"
},
"text-box-variable-form": {
"placeholder-default-value-if-any": "(optional)",
"text-options": "Text options"
},
"title-field-label": {
"title": "Title"
},
"transformations-drawer": {
"search-box-suffix": {
"tooltip-clear-search": "Clear search"
}
},
"unlink-modal": {
"title-really-unlink-panel": "Do you really want to unlink this panel?"
},
"unsaved-changes-modal": {
"cancel": "Cancel",
"changes": "Do you want to save your changes?",
"discard": "Discard",
"save-dashboard": "Save dashboard",
"title-unsaved-changes": "Unsaved changes"
},
"variable-check-indicator": {
"aria-label-variable-referenced-dashboard": "This variable is not referenced by any variable or dashboard.",
"aria-label-variable-referenced-other-variables-dashboard": "This variable is referenced by other variables or dashboard."
},
"variable-editor-form": {
"aria-label-variable-editor-form": "Variable editor form",
"back-to-list": "Back to list",
"delete": "Delete",
"description-optional-display-name": "Optional display name",
"description-template-variable-characters": "The name of the template variable. (Max. 50 characters)",
"general": "General",
"placeholder-descriptive-text": "Descriptive text",
"placeholder-label-name": "Label name",
"placeholder-variable-name": "Variable name",
"text-running-query": "Running query..."
},
"variable-editor-list": {
"definition": "Definition",
"new-variable": "New variable",
"variable": "Variable"
},
"variable-editor-list-row": {
"title-delete-variable": "Delete variable",
"tooltip-duplicate-variable": "Duplicate variable",
"tooltip-remove-variable": "Remove variable"
},
"variable-hide-select": {
"label-show-on-dashboard": "Show on dashboard"
},
"variable-usages-button": {
"tooltip-show-usages": "Show usages"
},
"variable-values-preview": {
"preview-of-values": "Preview of values",
"show-more": "Show more"
},
"version-history-comparison": {
"label-view-json-diff": "View JSON diff"
},
"version-history-header": {
"latest": "(Latest)",
"tooltip-reset-version": "Reset version"
},
"version-history-table": {
"date": "Date",
"notes": "Notes",
"restore": "Restore",
"updated-by": "Updated by",
"version": "Version"
},
"versions-history-buttons": {
"compare-versions": "Compare versions",
"show-more-versions": "Show more versions"
},
"visualization-button": {
"aria-label-change-visualization": "Change visualization",
"tooltip-click-to-change-visualization": "Click to change visualization"
},
"viz-panel-links-renderer": {
"aria-label-panel-links": "Panel links"
}
},
"dashboard-settings": {

Loading…
Cancel
Save