Internationalisation: More automatic markup (#102792)

* more automatic i18n markup

* better labels

* little bit of tidy up

* fix unit tests
pull/102679/head^2
Ashley Harrison 4 months ago committed by GitHub
parent b2d9b3abe6
commit dc5badd9b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 535
      .betterer.results
  2. 6
      public/app/features/actions/ActionEditor.tsx
  3. 18
      public/app/features/actions/ParamsEditor.tsx
  4. 13
      public/app/features/annotations/components/AnnotationResultMapper.tsx
  5. 13
      public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx
  6. 5
      public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx
  7. 12
      public/app/features/correlations/components/EmptyCorrelationsCTA.tsx
  8. 31
      public/app/features/datasources/components/BasicSettings.tsx
  9. 5
      public/app/features/datasources/components/ButtonRow.tsx
  10. 6
      public/app/features/datasources/components/CloudInfoBox.tsx
  11. 5
      public/app/features/datasources/components/DashboardsTable.tsx
  12. 5
      public/app/features/datasources/components/DataSourceCategories.tsx
  13. 5
      public/app/features/datasources/components/DataSourceLoadError.tsx
  14. 6
      public/app/features/datasources/components/DataSourceMissingRightsMessage.tsx
  15. 5
      public/app/features/datasources/components/DataSourcePluginState.tsx
  16. 7
      public/app/features/datasources/components/DataSourceReadOnlyMessage.tsx
  17. 5
      public/app/features/datasources/components/DataSourcesListCard.tsx
  18. 5
      public/app/features/datasources/components/EditDataSourceActions.tsx
  19. 12
      public/app/features/datasources/components/NewDataSource.tsx
  20. 6
      public/app/features/datasources/components/picker/DataSourcePicker.tsx
  21. 5
      public/app/features/dimensions/editors/FileUploader.tsx
  22. 3
      public/app/features/dimensions/editors/FolderPickerTab.tsx
  23. 13
      public/app/features/dimensions/editors/ResourceDimensionEditor.tsx
  24. 3
      public/app/features/dimensions/editors/ResourcePicker.tsx
  25. 9
      public/app/features/dimensions/editors/ResourcePickerPopover.tsx
  26. 9
      public/app/features/dimensions/editors/ScalarDimensionEditor.tsx
  27. 7
      public/app/features/dimensions/editors/ScaleDimensionEditor.tsx
  28. 19
      public/app/features/dimensions/editors/TextDimensionEditor.tsx
  29. 12
      public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.tsx
  30. 3
      public/app/features/dimensions/editors/URLPickerTab.tsx
  31. 65
      public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx
  32. 15
      public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx
  33. 23
      public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx
  34. 7
      public/app/features/explore/TraceView/components/TracePageHeader/SearchBar/TracePageSearchBar.tsx
  35. 6
      public/app/features/expressions/ExpressionQueryEditor.tsx
  36. 3
      public/app/features/expressions/components/ClassicConditions.tsx
  37. 5
      public/app/features/expressions/components/Math.tsx
  38. 11
      public/app/features/expressions/components/Reduce.tsx
  39. 13
      public/app/features/expressions/components/Resample.tsx
  40. 2
      public/app/features/expressions/components/Threshold.tsx
  41. 10
      public/app/features/gops/configuration-tracker/components/ConfigCard.tsx
  42. 5
      public/app/features/gops/configuration-tracker/components/ConfigureIRM.tsx
  43. 7
      public/app/features/gops/configuration-tracker/components/Essentials.tsx
  44. 6
      public/app/features/inspector/InspectDataTab.tsx
  45. 6
      public/app/features/inspector/InspectJSONTab.tsx
  46. 12
      public/app/features/inspector/QueryInspector.tsx
  47. 3
      public/app/features/invites/InviteeRow.tsx
  48. 2
      public/app/features/invites/InviteesTable.test.tsx
  49. 9
      public/app/features/invites/InviteesTable.tsx
  50. 42
      public/app/features/invites/SignupInvited.tsx
  51. 10
      public/app/features/live/LiveConnectionWarning.tsx
  52. 7
      public/app/features/live/dashboard/DashboardChangedModal.tsx
  53. 2
      public/app/features/logs/components/InfiniteScroll.tsx
  54. 24
      public/app/features/logs/components/LogDetails.tsx
  55. 14
      public/app/features/logs/components/LogDetailsBody.tsx
  56. 23
      public/app/features/logs/components/LogDetailsRow.tsx
  57. 21
      public/app/features/logs/components/LogRowMenuCell.tsx
  58. 10
      public/app/features/logs/components/log-context/LogContextButtons.tsx
  59. 33
      public/app/features/logs/components/log-context/LogRowContextModal.tsx
  60. 1
      public/app/features/manage-dashboards/DashboardImportPage.tsx
  61. 34
      public/app/features/manage-dashboards/components/ImportDashboardForm.tsx
  62. 13
      public/app/features/manage-dashboards/components/ImportDashboardOverview.tsx
  63. 2
      public/app/features/manage-dashboards/components/SnapshotListTable.tsx
  64. 4
      public/app/features/migrate-to-cloud/onprem/NameCell.tsx
  65. 2
      public/app/features/notifications/StoredNotifications.tsx
  66. 7
      public/app/features/panel/components/PanelDataErrorView.tsx
  67. 13
      public/app/features/panel/components/PanelRenderer.tsx
  68. 8
      public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx
  69. 11
      public/app/features/panel/components/VizTypePicker/VisualizationSuggestions.tsx
  70. 9
      public/app/features/panel/components/VizTypePicker/VizTypePicker.tsx
  71. 7
      public/app/features/plugins/admin/components/AppConfigWrapper.tsx
  72. 1
      public/app/features/plugins/admin/components/Badges/PluginAngularBadge.tsx
  73. 8
      public/app/features/plugins/admin/components/Badges/PluginDeprecatedBadge.tsx
  74. 10
      public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx
  75. 12
      public/app/features/plugins/admin/components/Badges/PluginEnterpriseBadge.tsx
  76. 9
      public/app/features/plugins/admin/components/Badges/PluginInstallBadge.tsx
  77. 7
      public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx
  78. 5
      public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.tsx
  79. 3
      public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx
  80. 19
      public/app/features/plugins/admin/components/InstallControls/InstallControlsWarning.tsx
  81. 5
      public/app/features/plugins/admin/components/PluginActions.tsx
  82. 15
      public/app/features/plugins/admin/components/PluginDashboards.tsx
  83. 5
      public/app/features/plugins/admin/components/PluginDetailsBody.tsx
  84. 8
      public/app/features/plugins/admin/components/PluginDetailsDeprecatedWarning.tsx
  85. 6
      public/app/features/plugins/admin/components/PluginDetailsPage.tsx
  86. 1
      public/app/features/plugins/admin/components/PluginDetailsPanel.tsx
  87. 7
      public/app/features/plugins/admin/components/PluginDetailsSignature.tsx
  88. 2
      public/app/features/plugins/admin/components/PluginListItemBadges.test.tsx
  89. 7
      public/app/features/plugins/admin/components/PluginSignatureDetailsBadge.tsx
  90. 10
      public/app/features/plugins/admin/components/PluginUsage.tsx
  91. 3
      public/app/features/plugins/admin/components/SearchField.tsx
  92. 9
      public/app/features/plugins/admin/components/VersionInstallButton.tsx
  93. 19
      public/app/features/plugins/admin/components/VersionList.tsx
  94. 11
      public/app/features/plugins/admin/pages/Browse.tsx
  95. 7
      public/app/features/plugins/angularDeprecation/AngularDeprecationNotice.tsx
  96. 16
      public/app/features/plugins/angularDeprecation/AngularDeprecationPluginNotice.tsx
  97. 5
      public/app/features/plugins/angularDeprecation/AngularMigrationNotice.tsx
  98. 13
      public/app/features/plugins/components/AppRootPage.tsx
  99. 7
      public/app/features/plugins/extensions/logs/LogViewFilters.tsx
  100. 8
      public/app/features/profile/UserOrganizations.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,5 +1,5 @@
// BETTERER RESULTS V2.
//
//
// If this file contains merge conflicts, use `betterer merge` to automatically resolve them:
// https://phenomnomnominal.github.io/betterer/docs/results-file/#merge
//
@ -462,7 +462,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"packages/grafana-runtime/src/services/AngularLoader.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@ -1147,17 +1148,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/actions/ActionEditor.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/actions/ParamsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/admin/AdminFeatureTogglesTable.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
@ -2488,17 +2480,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"public/app/features/annotations/components/AnnotationResultMapper.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/annotations/components/StandardAnnotationQueryEditor.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 />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/annotations/events_processing.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -2635,12 +2619,7 @@ exports[`better eslint`] = {
],
"public/app/features/correlations/Forms/ConfigureCorrelationTargetForm.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"]
],
"public/app/features/correlations/components/EmptyCorrelationsCTA.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, "Do not use any type assertions.", "1"]
],
"public/app/features/correlations/components/Wizard/index.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
@ -2660,6 +2639,13 @@ exports[`better eslint`] = {
[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"]
],
"public/app/features/dashboard-scene/embedding/EmbeddedDashboardTestPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@ -3663,47 +3649,18 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"]
],
"public/app/features/datasources/components/BasicSettings.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()", "0"]
],
"public/app/features/datasources/components/ButtonRow.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 />", "0"]
],
"public/app/features/datasources/components/CloudInfoBox.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/datasources/components/DashboardsTable.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/datasources/components/DataSourceCategories.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/datasources/components/DataSourceLoadError.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/datasources/components/DataSourceMissingRightsMessage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/datasources/components/DataSourcePluginConfigPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/datasources/components/DataSourcePluginState.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/datasources/components/DataSourceReadOnlyMessage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/datasources/components/DataSourceTestingStatus.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"],
@ -3713,22 +3670,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
],
"public/app/features/datasources/components/DataSourcesListCard.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/datasources/components/EditDataSourceActions.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/datasources/components/NewDataSource.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/datasources/components/picker/DataSourcePicker.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/datasources/state/actions.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@ -3757,89 +3698,33 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/dimensions/editors/FileUploader.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/dimensions/editors/FolderPickerTab.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dimensions/editors/ResourceDimensionEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/dimensions/editors/ResourcePicker.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/dimensions/editors/ResourcePickerPopover.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
],
"public/app/features/dimensions/editors/ScalarDimensionEditor.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/dimensions/editors/ScaleDimensionEditor.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()", "0"]
],
"public/app/features/dimensions/editors/TextDimensionEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "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()", "2"]
],
"public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "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"]
],
"public/app/features/dimensions/editors/URLPickerTab.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 />", "2"]
],
"public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
[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"]
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
],
"public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx:5381": [
[0, 0, 0, "\'VerticalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "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/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.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"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/dimensions/editors/index.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
@ -3973,10 +3858,7 @@ exports[`better eslint`] = {
"public/app/features/explore/TraceView/components/TracePageHeader/SearchBar/TracePageSearchBar.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 in text props. Wrap text with <Trans /> or use t()", "2"]
],
"public/app/features/explore/TraceView/components/TracePageHeader/SpanFilters/SpanFilters.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
@ -4115,12 +3997,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/expressions/ExpressionQueryEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/expressions/components/ClassicConditions.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/expressions/components/Condition.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
@ -4140,24 +4016,7 @@ exports[`better eslint`] = {
[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"]
],
"public/app/features/expressions/components/Reduce.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/expressions/components/Resample.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/expressions/components/Threshold.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 />", "13"]
],
"public/app/features/expressions/guards.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@ -4177,16 +4036,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/gops/configuration-tracker/components/ConfigCard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/gops/configuration-tracker/components/ConfigureIRM.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/gops/configuration-tracker/components/Essentials.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/gops/configuration-tracker/components/ProgressBar.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
@ -4198,8 +4049,7 @@ exports[`better eslint`] = {
],
"public/app/features/inspector/InspectDataTab.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, "Use data-testid for E2E selectors instead of aria-label", "2"]
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
],
"public/app/features/inspector/InspectErrorTab.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
@ -4212,43 +4062,23 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use the t() function outside of a component or function", "2"],
[0, 0, 0, "Do not use the t() function outside of a component or function", "3"],
[0, 0, 0, "Do not use the t() function outside of a component or function", "4"],
[0, 0, 0, "Do not use the t() function outside of a component or function", "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, "Do not use the t() function outside of a component or function", "5"]
],
"public/app/features/inspector/InspectStatsTab.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/inspector/QueryInspector.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 />", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "6"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "7"]
],
"public/app/features/invites/InviteeRow.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "4"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "5"]
],
"public/app/features/invites/InviteesTable.tsx:5381": [
"public/app/features/invites/SignupInvited.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/invites/SignupInvited.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. Wrap text with <Trans />", "8"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "9"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "10"]
],
"public/app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@ -4261,9 +4091,6 @@ exports[`better eslint`] = {
"public/app/features/library-panels/components/SaveLibraryPanelModal/SaveLibraryPanelModal.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/live/LiveConnectionWarning.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/live/centrifuge/LiveDataStream.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@ -4274,89 +4101,26 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/live/dashboard/DashboardChangedModal.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/logs/components/InfiniteScroll.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/logs/components/LogDetails.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/logs/components/LogDetailsBody.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/logs/components/LogDetailsRow.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()", "0"]
],
"public/app/features/logs/components/LogLabelStats.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/logs/components/LogRowMenuCell.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"]
],
"public/app/features/logs/components/log-context/LogContextButtons.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/logs/components/log-context/LogRowContextModal.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"]
],
"public/app/features/logs/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/manage-dashboards/DashboardImportPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/manage-dashboards/components/ImportDashboardForm.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. Wrap text with <Trans />", "8"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "9"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "10"]
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"public/app/features/manage-dashboards/components/ImportDashboardLibraryPanelsList.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/manage-dashboards/components/ImportDashboardOverview.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/manage-dashboards/components/SnapshotListTable.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/manage-dashboards/state/actions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -4381,12 +4145,10 @@ exports[`better eslint`] = {
],
"public/app/features/migrate-to-cloud/onprem/NameCell.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/notifications/StoredNotifications.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 in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/org/NewOrgPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
@ -4406,32 +4168,17 @@ exports[`better eslint`] = {
"public/app/features/org/state/reducers.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/panel/components/PanelDataErrorView.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/panel/components/PanelPluginError.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/panel/components/PanelRenderer.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[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/panel/components/VizTypePicker/PanelTypeCard.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"]
],
"public/app/features/panel/components/VizTypePicker/VisualizationSuggestions.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/panel/components/VizTypePicker/VizTypePicker.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
"public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/panel/panellinks/linkSuppliers.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -4457,34 +4204,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./remotePlugin.mock\`)", "1"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"]
],
"public/app/features/plugins/admin/components/AppConfigWrapper.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/plugins/admin/components/Badges/PluginAngularBadge.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/plugins/admin/components/Badges/PluginDeprecatedBadge.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/plugins/admin/components/Badges/PluginDisabledBadge.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/plugins/admin/components/Badges/PluginEnterpriseBadge.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/plugins/admin/components/Badges/PluginInstallBadge.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/plugins/admin/components/Badges/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./PluginAngularBadge\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`./PluginDeprecatedBadge\`)", "1"],
@ -4493,13 +4215,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./PluginInstallBadge\`)", "4"],
[0, 0, 0, "Do not re-export imported variable (\`./PluginUpdateAvailableBadge\`)", "5"]
],
"public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithApp.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/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.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/plugins/admin/components/GetStartedWithPlugin/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./GetStartedWithPlugin\`)", "0"]
@ -4511,86 +4228,46 @@ exports[`better eslint`] = {
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
[0, 0, 0, "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 />", "3"]
],
"public/app/features/plugins/admin/components/InstallControls/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./InstallControlsButton\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`./InstallControlsWarning\`)", "1"]
],
"public/app/features/plugins/admin/components/PluginActions.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/plugins/admin/components/PluginDashboards.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/plugins/admin/components/PluginDetailsBody.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/plugins/admin/components/PluginDetailsDeprecatedWarning.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/plugins/admin/components/PluginDetailsHeaderDependencies.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/plugins/admin/components/PluginDetailsPage.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/plugins/admin/components/PluginDetailsPanel.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/plugins/admin/components/PluginDetailsSignature.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/plugins/admin/components/PluginListItem.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/plugins/admin/components/PluginSignatureDetailsBadge.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/plugins/admin/components/PluginUsage.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"]
],
"public/app/features/plugins/admin/components/SearchField.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/plugins/admin/components/VersionInstallButton.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/plugins/admin/components/VersionList.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/plugins/admin/pages/Browse.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "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. Wrap text with <Trans />", "9"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"]
],
"public/app/features/plugins/admin/state/actions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@ -4599,24 +4276,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/plugins/angularDeprecation/AngularDeprecationNotice.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/plugins/angularDeprecation/AngularDeprecationPluginNotice.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/plugins/angularDeprecation/AngularMigrationNotice.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/plugins/components/AppRootPage.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/plugins/components/PluginsErrorsInfo.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
@ -4632,11 +4295,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
],
"public/app/features/plugins/extensions/logs/LogViewFilters.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/plugins/extensions/usePluginComponents.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@ -4668,21 +4326,8 @@ exports[`better eslint`] = {
"public/app/features/profile/FeatureTogglePage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/profile/UserOrganizations.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/profile/UserSessions.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/profile/UserTeams.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/provisioning/Config/ConfigForm.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
@ -4963,53 +4608,31 @@ exports[`better eslint`] = {
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "4"]
],
"public/app/features/query/components/QueryEditorRowHeader.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, "Use data-testid for E2E selectors instead of aria-label", "3"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
],
"public/app/features/query/components/QueryErrorAlert.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/query/components/QueryGroup.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "7"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "8"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "9"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "3"]
],
"public/app/features/query/components/QueryGroupOptions.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 />", "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 />", "8"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "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 />", "17"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "18"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "19"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "20"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "21"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "22"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "23"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "24"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "25"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "11"]
],
"public/app/features/query/state/DashboardQueryRunner/AnnotationsQueryRunner.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@ -5049,21 +4672,11 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
"public/app/features/sandbox/TestStuffPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
],
"public/app/features/search/page/components/ActionRow.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/search/page/components/SearchResultsTable.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/search/page/components/columns.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/search/service/bluge.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -5118,18 +4731,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/support-bundles/SupportBundles.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"]
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
"public/app/features/support-bundles/SupportBundlesCreate.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 />", "0"]
],
"public/app/features/teams/CreateTeam.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
@ -5216,9 +4821,6 @@ exports[`better eslint`] = {
[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/trails/RelatedLogs/RelatedLogsScene.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/trails/TrailStore/utils.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
],
@ -5422,9 +5024,8 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/users/TokenRevokedModal.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"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"]
],
"public/app/features/variables/adapters.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],

@ -161,12 +161,12 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions, showOne
</InlineFieldRow>
<InlineFieldRow>
<InlineField label="URL" labelWidth={LABEL_WIDTH} grow={true}>
<InlineField label={t('actions.action-editor.label-url', 'URL')} labelWidth={LABEL_WIDTH} grow={true}>
<SuggestionsInput
value={value.fetch.url}
onChange={onUrlChange}
suggestions={suggestions}
placeholder="URL"
placeholder={t('actions.action-editor.placeholder-url', 'URL')}
/>
</InlineField>
</InlineFieldRow>
@ -178,7 +178,7 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions, showOne
<ParamsEditor value={value?.fetch.queryParams ?? []} onChange={onQueryParamsChange} suggestions={suggestions} />
</Field>
<Field label="Headers">
<Field label={t('actions.action-editor.label-headers', 'Headers')}>
<ParamsEditor
value={value?.fetch.headers ?? []}
onChange={onHeadersChange}

@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
import { contentTypeOptions, GrafanaTheme2, VariableSuggestion } from '@grafana/data';
import { IconButton, Input, Stack, Select, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { SuggestionsInput } from '../transformers/suggestionsInput/SuggestionsInput';
@ -78,17 +79,22 @@ export const ParamsEditor = ({ value, onChange, suggestions, contentTypeHeader =
value={paramName}
onChange={changeParamName}
suggestions={suggestions}
placeholder="Key"
placeholder={t('actions.params-editor.placeholder-key', 'Key')}
style={{ width: 332 }}
/>
<SuggestionsInput
value={paramValue}
onChange={changeParamValue}
suggestions={suggestions}
placeholder="Value"
placeholder={t('actions.params-editor.placeholder-value', 'Value')}
style={{ width: 332 }}
/>
<IconButton aria-label="add" name="plus-circle" onClick={() => addParam()} disabled={isAddParamsDisabled} />
<IconButton
aria-label={t('actions.params-editor.aria-label-add', 'Add')}
name="plus-circle"
onClick={() => addParam()}
disabled={isAddParamsDisabled}
/>
</Stack>
<Stack direction="column">
@ -96,7 +102,11 @@ export const ParamsEditor = ({ value, onChange, suggestions, contentTypeHeader =
<Stack key={entry[0]} direction="row">
<Input disabled value={entry[0]} />
<Input disabled value={entry[1]} />
<IconButton aria-label="delete" onClick={removeParam(entry[0])} name="trash-alt" />
<IconButton
aria-label={t('actions.params-editor.aria-label-delete', 'Delete')}
onClick={removeParam(entry[0])}
name="trash-alt"
/>
</Stack>
))}
</Stack>

@ -11,6 +11,7 @@ import {
getValueFormat,
} from '@grafana/data';
import { Select, Tooltip, Icon } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { annotationEventNames, AnnotationFieldInfo } from '../standardAnnotationSupport';
import { AnnotationQueryResponse } from '../types';
@ -188,9 +189,15 @@ export class AnnotationFieldMapper extends PureComponent<Props, State> {
<table className="filter-table">
<thead>
<tr>
<th>Annotation</th>
<th>From</th>
<th>First Value</th>
<th>
<Trans i18nKey="annotations.annotation-field-mapper.annotation">Annotation</Trans>
</th>
<th>
<Trans i18nKey="annotations.annotation-field-mapper.from">From</Trans>
</th>
<th>
<Trans i18nKey="annotations.annotation-field-mapper.first-value">First value</Trans>
</th>
</tr>
</thead>
<tbody>

@ -12,6 +12,7 @@ import {
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Alert, AlertVariant, Button, Space, Spinner } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
@ -147,7 +148,11 @@ export default class StandardAnnotationQueryEditor extends PureComponent<Props,
}
if (!events?.length) {
return <p>No events found</p>;
return (
<p>
<Trans i18nKey="annotations.standard-annotation-query-editor.no-events-found">No events found</Trans>
</p>
);
}
const frame = panelData?.series?.[0] ?? panelData?.annotations?.[0];
@ -178,7 +183,9 @@ export default class StandardAnnotationQueryEditor extends PureComponent<Props,
size="xs"
onClick={this.onRunQuery}
>
Test annotation query
<Trans i18nKey="annotations.standard-annotation-query-editor.test-annotation-query">
Test annotation query
</Trans>
</Button>
)}
</div>
@ -186,7 +193,7 @@ export default class StandardAnnotationQueryEditor extends PureComponent<Props,
<Alert
data-testid={selectors.components.Annotations.editor.resultContainer}
severity={this.getStatusSeverity(response)}
title="Query result"
title={t('annotations.standard-annotation-query-editor.title-query-result', 'Query result')}
>
{this.renderStatusText(response, running)}
</Alert>

@ -77,7 +77,10 @@ export const ConfigureCorrelationTargetForm = () => {
value={correlationType}
onChange={(value) => onChange(value.value)}
options={Object.values(CORR_TYPES_SELECT)}
aria-label="correlation type"
aria-label={t(
'correlations.configure-correlation-target-form.aria-label-correlation-type',
'Correlation type'
)}
/>
</Field>
)}

@ -24,8 +24,16 @@ export const EmptyCorrelationsCTA = ({ onClick, canWriteCorrelations }: Props) =
</EmptyState>
) : (
<Card>
<Card.Heading>There are no correlations configured yet.</Card.Heading>
<Card.Description>Please contact your administrator to create new correlations.</Card.Description>
<Card.Heading>
<Trans i18nKey="correlations.empty-correlations-cta.there-are-no-correlations-configured-yet">
There are no correlations configured yet.
</Trans>
</Card.Heading>
<Card.Description>
<Trans i18nKey="correlations.empty-correlations-cta.please-contact-administrator-create-correlations">
Please contact your administrator to create new correlations.
</Trans>
</Card.Description>
</Card>
);
};

@ -4,6 +4,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { InlineField, InlineSwitch, Input, Badge, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export interface Props {
dataSourceName: string;
@ -16,12 +17,18 @@ export interface Props {
export function BasicSettings({ dataSourceName, isDefault, onDefaultChange, onNameChange, disabled }: Props) {
return (
<>
<div className="gf-form-group" aria-label="Datasource settings page basic settings">
<div
className="gf-form-group"
aria-label={t(
'datasources.basic-settings.aria-label-datasource-settings-page-basic',
'Datasource settings page basic settings'
)}
>
<div className="gf-form-inline">
{/* Name */}
<div className="gf-form max-width-30">
<InlineField
label="Name"
label={t('datasources.basic-settings.label-name', 'Name')}
tooltip="The name is used when you select the data source in panels. The default data source is
'preselected in new panels."
grow
@ -32,7 +39,7 @@ export function BasicSettings({ dataSourceName, isDefault, onDefaultChange, onNa
id="basic-settings-name"
type="text"
value={dataSourceName}
placeholder="Name"
placeholder={t('datasources.basic-settings.basic-settings-name-placeholder-name', 'Name')}
onChange={(event) => onNameChange(event.currentTarget.value)}
required
data-testid={selectors.pages.DataSource.name}
@ -41,7 +48,11 @@ export function BasicSettings({ dataSourceName, isDefault, onDefaultChange, onNa
</div>
{/* Is Default */}
<InlineField label="Default" labelWidth={8} disabled={disabled}>
<InlineField
label={t('datasources.basic-settings.label-default', 'Default')}
labelWidth={8}
disabled={disabled}
>
<InlineSwitch
id="basic-settings-default"
value={isDefault}
@ -61,9 +72,17 @@ export function AlertingEnabled({ enabled }: { enabled: boolean }) {
return (
<div className={styles.badge}>
{enabled ? (
<Badge color="green" icon="check-circle" text="Alerting supported" />
<Badge
color="green"
icon="check-circle"
text={t('datasources.alerting-enabled.text-alerting-supported', 'Alerting supported')}
/>
) : (
<Badge color="orange" icon="exclamation-triangle" text="Alerting not supported" />
<Badge
color="orange"
icon="exclamation-triangle"
text={t('datasources.alerting-enabled.text-alerting-not-supported', 'Alerting not supported')}
/>
)}
</div>
);

@ -2,6 +2,7 @@ import * as React from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Button } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
export interface Props {
canSave: boolean;
@ -21,7 +22,7 @@ export function ButtonRow({ canSave, canDelete, onDelete, onSubmit, onTest }: Pr
onClick={onDelete}
data-testid={selectors.pages.DataSource.delete}
>
Delete
<Trans i18nKey="datasources.button-row.delete">Delete</Trans>
</Button>
{canSave && (
<Button
@ -36,7 +37,7 @@ export function ButtonRow({ canSave, canDelete, onDelete, onSubmit, onTest }: Pr
)}
{!canSave && (
<Button variant="primary" onClick={onTest}>
Test
<Trans i18nKey="datasources.button-row.test">Test</Trans>
</Button>
)}
</div>

@ -3,6 +3,7 @@ import { GrafanaEdition } from '@grafana/data/internal';
import { Alert } from '@grafana/ui';
import { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';
import { config } from 'app/core/config';
import { t } from 'app/core/internationalization';
const LOCAL_STORAGE_KEY = 'datasources.settings.cloudInfoBox.isDismissed';
@ -59,7 +60,10 @@ export function CloudInfoBox({ dataSource }: Props) {
href={`https://grafana.com/signup/cloud/connect-account?src=grafana-oss&cnt=${dataSource.type}-settings`}
target="_blank"
rel="noreferrer"
title="The free plan includes 10k active metrics and 50gb storage."
title={t(
'datasources.cloud-info-box.title-includes-active-metrics-storage',
'The free plan includes 10k active metrics and 50gb storage.'
)}
>
free-forever Grafana Cloud plan
</a>

@ -1,4 +1,5 @@
import { Button, Icon } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { PluginDashboard } from 'app/types';
export interface Props {
@ -34,7 +35,7 @@ export function DashboardsTable({ dashboards, onImport, onRemove }: Props) {
<td style={{ textAlign: 'right' }}>
{!dashboard.imported ? (
<Button variant="secondary" size="sm" onClick={() => onImport(dashboard, false)}>
Import
<Trans i18nKey="datasources.dashboards-table.import">Import</Trans>
</Button>
) : (
<Button variant="secondary" size="sm" onClick={() => onImport(dashboard, true)}>
@ -43,7 +44,7 @@ export function DashboardsTable({ dashboards, onImport, onRemove }: Props) {
)}
{dashboard.imported && (
<Button
aria-label="Delete dashboard"
aria-label={t('datasources.dashboards-table.aria-label-delete-dashboard', 'Delete dashboard')}
icon="trash-alt"
variant="destructive"
size="sm"

@ -4,6 +4,7 @@ import { useCallback } from 'react';
import { DataSourcePluginMeta, GrafanaTheme2 } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { LinkButton, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DataSourcePluginCategory } from 'app/types';
import { ROUTES } from '../../connections/constants';
@ -46,7 +47,9 @@ export function DataSourceCategories({ categories, onClickDataSourceType }: Prop
{/* Find more */}
<div className={styles.more}>
<LinkButton variant="secondary" href={moreDataSourcesLink} onClick={handleClick} target="_self" rel="noopener">
Find more data source plugins
<Trans i18nKey="datasources.data-source-categories.find-more-data-source-plugins">
Find more data source plugins
</Trans>
</LinkButton>
</div>
</>

@ -1,4 +1,5 @@
import { Button } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DataSourceRights } from '../types';
@ -21,12 +22,12 @@ export function DataSourceLoadError({ dataSourceRights, onDelete }: Props) {
<div className="gf-form-button-row">
{canDelete && (
<Button type="submit" variant="destructive" onClick={onDelete}>
Delete
<Trans i18nKey="datasources.data-source-load-error.delete">Delete</Trans>
</Button>
)}
<Button variant="secondary" fill="outline" type="button" onClick={navigateBack}>
Back
<Trans i18nKey="datasources.data-source-load-error.back">Back</Trans>
</Button>
</div>
</>

@ -1,11 +1,15 @@
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export const missingRightsMessage =
'You are not allowed to modify this data source. Please contact your server admin to update this data source.';
export function DataSourceMissingRightsMessage() {
return (
<Alert severity="info" title="Missing rights">
<Alert
severity="info"
title={t('datasources.data-source-missing-rights-message.title-missing-rights', 'Missing rights')}
>
{missingRightsMessage}
</Alert>
);

@ -1,4 +1,5 @@
import { PluginState } from '@grafana/data';
import { Trans } from 'app/core/internationalization';
import { PluginStateInfo } from 'app/features/plugins/components/PluginStateInfo';
export type Props = {
@ -8,7 +9,9 @@ export type Props = {
export function DataSourcePluginState({ state }: Props) {
return (
<div className="gf-form">
<div className="gf-form-label width-10">Plugin state</div>
<div className="gf-form-label width-10">
<Trans i18nKey="datasources.data-source-plugin-state.plugin-state">Plugin state</Trans>
</div>
<div className="gf-form-label gf-form-label--transparent">
<PluginStateInfo state={state} />
</div>

@ -1,12 +1,17 @@
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export const readOnlyMessage =
'This data source was added by config and cannot be modified using the UI. Please contact your server admin to update this data source.';
export function DataSourceReadOnlyMessage() {
return (
<Alert data-testid={e2eSelectors.pages.DataSource.readOnly} severity="info" title="Provisioned data source">
<Alert
data-testid={e2eSelectors.pages.DataSource.readOnly}
severity="info"
title={t('datasources.data-source-read-only-message.title-provisioned-data-source', 'Provisioned data source')}
>
{readOnlyMessage}
</Alert>
);

@ -4,6 +4,7 @@ import Skeleton from 'react-loading-skeleton';
import { DataSourceSettings, GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Card, LinkButton, Stack, Tag, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { ROUTES } from '../../connections/constants';
import { trackCreateDashboardClicked, trackExploreClicked } from '../tracking';
@ -48,7 +49,7 @@ export function DataSourcesListCard({ dataSource, hasWriteRights, hasExploreRigh
});
}}
>
Build a dashboard
<Trans i18nKey="datasources.data-sources-list-card.build-a-dashboard">Build a dashboard</Trans>
</LinkButton>
{/* Explore */}
@ -68,7 +69,7 @@ export function DataSourcesListCard({ dataSource, hasWriteRights, hasExploreRigh
});
}}
>
Explore
<Trans i18nKey="datasources.data-sources-list-card.explore">Explore</Trans>
</LinkButton>
)}
</Card.Tags>

@ -1,6 +1,7 @@
import { config } from '@grafana/runtime';
import { LinkButton } from '@grafana/ui';
import { contextSrv } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import { useDataSource } from '../state';
import { trackCreateDashboardClicked, trackDsConfigClicked, trackExploreClicked } from '../tracking';
@ -31,7 +32,7 @@ export function EditDataSourceActions({ uid }: Props) {
});
}}
>
Explore data
<Trans i18nKey="datasources.edit-data-source-actions.explore-data">Explore data</Trans>
</LinkButton>
)}
<LinkButton
@ -48,7 +49,7 @@ export function EditDataSourceActions({ uid }: Props) {
});
}}
>
Build a dashboard
<Trans i18nKey="datasources.edit-data-source-actions.build-a-dashboard">Build a dashboard</Trans>
</LinkButton>
</>
);

@ -3,6 +3,7 @@ import { Action } from 'redux';
import { DataSourcePluginMeta, PluginType } from '@grafana/data';
import { LinkButton, FilterInput } from '@grafana/ui';
import PageLoader from 'app/core/components/PageLoader/PageLoader';
import { t, Trans } from 'app/core/internationalization';
import { PluginsErrorsInfo } from 'app/features/plugins/components/PluginsErrorsInfo';
import { DataSourcePluginCategory, StoreState, useDispatch, useSelector } from 'app/types';
@ -64,10 +65,17 @@ export function NewDataSourceView({
<>
{/* Search */}
<div className="page-action-bar">
<FilterInput value={searchQuery} onChange={onSetSearchQuery} placeholder="Filter by name or type" />
<FilterInput
value={searchQuery}
onChange={onSetSearchQuery}
placeholder={t(
'datasources.new-data-source-view.placeholder-filter-by-name-or-type',
'Filter by name or type'
)}
/>
<div className="page-action-bar__spacer" />
<LinkButton href={ROUTES.DataSources} fill="outline" variant="secondary" icon="arrow-left">
Cancel
<Trans i18nKey="datasources.new-data-source-view.cancel">Cancel</Trans>
</LinkButton>
</div>

@ -14,7 +14,7 @@ import { reportInteraction } from '@grafana/runtime';
import { DataQuery, DataSourceRef } from '@grafana/schema';
import { Button, Icon, Input, ModalsController, Portal, ScrollContainer, useStyles2 } from '@grafana/ui';
import config from 'app/core/config';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { useKeyNavigationListener } from 'app/features/search/hooks/useSearchKeyboardSelection';
import { defaultFileUploadQuery, GrafanaQuery } from 'app/plugins/datasource/grafana/types';
@ -242,7 +242,7 @@ export function DataSourcePicker(props: DataSourcePickerProps) {
id={inputId || 'data-source-picker'}
className={inputHasFocus ? undefined : styles.input}
data-testid={selectors.components.DataSourcePicker.inputV2}
aria-label="Select a data source"
aria-label={t('datasources.data-source-picker.aria-label-select-a-data-source', 'Select a data source')}
autoComplete="off"
prefix={currentValue ? prefixIcon : undefined}
suffix={<Icon name={isOpen ? 'search' : 'angle-down'} />}
@ -463,7 +463,7 @@ function Footer({ onClose, onChange, onClickAddCSV, ...props }: FooterProps) {
</ModalsController>
{isUploadFileEnabled && (
<Button variant="secondary" size="sm" onClick={onClickAddCSV} onKeyDown={onKeyDownLastButton}>
Add csv or spreadsheet
<Trans i18nKey="datasources.footer.add-csv-or-spreadsheet">Add csv or spreadsheet</Trans>
</Button>
)}
</div>

@ -4,6 +4,7 @@ import { Dispatch, SetStateAction, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { FileDropzone, useStyles2, Button, DropzoneFile, Field } from '@grafana/ui';
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
import { Trans, t } from 'app/core/internationalization';
import { MediaType } from '../types';
@ -24,7 +25,7 @@ export function FileDropzoneCustomChildren({ secondaryText = 'Drag and drop here
<div className={styles.iconWrapper}>
<small className={styles.small}>{secondaryText}</small>
<Button type="button" icon="upload">
Upload
<Trans i18nKey="dimensions.file-dropzone-custom-children.upload">Upload</Trans>
</Button>
</div>
);
@ -35,7 +36,7 @@ export const FileUploader = ({ mediaType, setFormData, setUpload, error }: Props
const [file, setFile] = useState<string>('');
const Preview = () => (
<Field label="Preview">
<Field label={t('dimensions.file-uploader.preview.label-preview', 'Preview')}>
<div className={styles.iconPreview}>
{mediaType === MediaType.Icon && <SanitizedSVG src={file} className={styles.img} />}
{mediaType === MediaType.Image && <img src={file} alt="Preview of the uploaded file" className={styles.img} />}

@ -3,6 +3,7 @@ import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { Field, FilterInput, Select, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { FileElement, GrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
@ -106,7 +107,7 @@ export const FolderPickerTab = (props: Props) => {
<Field>
<FilterInput
value={searchQuery ?? ''}
placeholder="Search"
placeholder={t('dimensions.folder-picker-tab.placeholder-search', 'Search')}
onChange={(v) => {
onChangeSearch(v);
setSearchQuery(v);

@ -5,6 +5,7 @@ import { FieldNamePickerConfigSettings, StandardEditorProps, StandardEditorsRegi
import { ResourceDimensionConfig, ResourceDimensionMode } from '@grafana/schema';
import { InlineField, InlineFieldRow, RadioButtonGroup } from '@grafana/ui';
import { FieldNamePicker } from '@grafana/ui/internal';
import { t } from 'app/core/internationalization';
import { getPublicOrAbsoluteUrl, ResourceFolderName } from '..';
import { MediaType, ResourceDimensionOptions, ResourcePickerSize } from '../types';
@ -80,14 +81,22 @@ export const ResourceDimensionEditor = (
<>
{showSourceRadio && (
<InlineFieldRow>
<InlineField label="Source" labelWidth={labelWidth} grow={true}>
<InlineField
label={t('dimensions.resource-dimension-editor.label-source', 'Source')}
labelWidth={labelWidth}
grow={true}
>
<RadioButtonGroup value={mode} options={resourceOptions} onChange={onModeChange} fullWidth />
</InlineField>
</InlineFieldRow>
)}
{mode !== ResourceDimensionMode.Fixed && (
<InlineFieldRow>
<InlineField label="Field" labelWidth={labelWidth} grow={true}>
<InlineField
label={t('dimensions.resource-dimension-editor.label-field', 'Field')}
labelWidth={labelWidth}
grow={true}
>
<FieldNamePicker
context={context}
value={value.field ?? ''}

@ -16,6 +16,7 @@ import {
} from '@grafana/ui';
import { closePopover } from '@grafana/ui/internal';
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
import { Trans } from 'app/core/internationalization';
import { getPublicOrAbsoluteUrl } from '../resource';
import { MediaType, ResourceFolderName, ResourcePickerSize } from '../types';
@ -71,7 +72,7 @@ export const ResourcePicker = (props: Props) => {
} else {
return (
<LinkButton variant="primary" fill="text" size="sm">
Set icon
<Trans i18nKey="dimensions.resource-picker.render-small-resource-picker.set-icon">Set icon</Trans>
</LinkButton>
);
}

@ -8,6 +8,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { Button, useStyles2 } from '@grafana/ui';
import { config } from 'app/core/config';
import { Trans } from 'app/core/internationalization';
import { MediaType, PickerTabType, ResourceFolderName } from '../types';
@ -94,17 +95,17 @@ export const ResourcePickerPopover = (props: Props) => {
className={getTabClassName(PickerTabType.Folder)}
onClick={() => setActivePicker(PickerTabType.Folder)}
>
Folder
<Trans i18nKey="dimensions.resource-picker-popover.folder">Folder</Trans>
</button>
<button className={getTabClassName(PickerTabType.URL)} onClick={() => setActivePicker(PickerTabType.URL)}>
URL
<Trans i18nKey="dimensions.resource-picker-popover.url">URL</Trans>
</button>
</div>
<div className={styles.resourcePickerPopoverContent}>
{renderPicker()}
<div className={styles.buttonRow}>
<Button variant={'secondary'} onClick={() => onClose()} fill="outline">
Cancel
<Trans i18nKey="dimensions.resource-picker-popover.cancel">Cancel</Trans>
</Button>
<Button
variant={newValue && newValue !== value ? 'primary' : 'secondary'}
@ -136,7 +137,7 @@ export const ResourcePickerPopover = (props: Props) => {
}
}}
>
Select
<Trans i18nKey="dimensions.resource-picker-popover.select">Select</Trans>
</Button>
</div>
</div>

@ -6,6 +6,7 @@ import { ScalarDimensionMode, ScalarDimensionConfig } from '@grafana/schema';
import { InlineField, InlineFieldRow, RadioButtonGroup, Select, useStyles2 } from '@grafana/ui';
import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/internal';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { t } from 'app/core/internationalization';
import { ScalarDimensionOptions } from '../types';
@ -81,7 +82,7 @@ export const ScalarDimensionEditor = ({ value, context, onChange, item }: Props)
<>
<div>
<InlineFieldRow>
<InlineField label="Limit" labelWidth={8} grow={true}>
<InlineField label={t('dimensions.scalar-dimension-editor.label-limit', 'Limit')} labelWidth={8} grow={true}>
<RadioButtonGroup value={mode} options={scalarOptions} onChange={onModeChange} fullWidth />
</InlineField>
</InlineFieldRow>
@ -95,7 +96,11 @@ export const ScalarDimensionEditor = ({ value, context, onChange, item }: Props)
<div className={styles.range}>
{isFixed && (
<InlineFieldRow>
<InlineField label="Value" labelWidth={8} grow={true}>
<InlineField
label={t('dimensions.scalar-dimension-editor.label-value', 'Value')}
labelWidth={8}
grow={true}
>
<NumberInput
value={val?.fixed ?? DEFAULT_VALUE}
onChange={onValueChange}

@ -6,6 +6,7 @@ import { ScaleDimensionConfig } from '@grafana/schema';
import { InlineField, InlineFieldRow, Select, useStyles2 } from '@grafana/ui';
import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/internal';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { t } from 'app/core/internationalization';
import { validateScaleOptions, validateScaleConfig } from '../scale';
import { ScaleDimensionOptions } from '../types';
@ -106,7 +107,7 @@ export const ScaleDimensionEditor = (props: StandardEditorProps<ScaleDimensionCo
<div className={styles.range}>
{isFixed && (
<InlineFieldRow>
<InlineField label="Value" labelWidth={8} grow={true}>
<InlineField label={t('dimensions.scale-dimension-editor.label-value', 'Value')} labelWidth={8} grow={true}>
<NumberInput value={val.fixed} {...minMaxStep} onChange={onValueChange} />
</InlineField>
</InlineFieldRow>
@ -114,12 +115,12 @@ export const ScaleDimensionEditor = (props: StandardEditorProps<ScaleDimensionCo
{!isFixed && !minMaxStep.hideRange && (
<>
<InlineFieldRow>
<InlineField label="Min" labelWidth={8} grow={true}>
<InlineField label={t('dimensions.scale-dimension-editor.label-min', 'Min')} labelWidth={8} grow={true}>
<NumberInput value={val.min} {...minMaxStep} onChange={onMinChange} />
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<InlineField label="Max" labelWidth={8} grow={true}>
<InlineField label={t('dimensions.scale-dimension-editor.label-max', 'Max')} labelWidth={8} grow={true}>
<NumberInput value={val.max} {...minMaxStep} onChange={onMaxChange} />
</InlineField>
</InlineFieldRow>

@ -10,6 +10,7 @@ import { TextDimensionConfig, TextDimensionMode } from '@grafana/schema';
import { Button, InlineField, InlineFieldRow, RadioButtonGroup } from '@grafana/ui';
import { FieldNamePicker } from '@grafana/ui/internal';
import { StringValueEditor } from 'app/core/components/OptionsUI/string';
import { t } from 'app/core/internationalization';
import { TextDimensionOptions } from '../types';
@ -70,13 +71,21 @@ export const TextDimensionEditor = ({ value, context, onChange }: Props) => {
return (
<>
<InlineFieldRow>
<InlineField label="Source" labelWidth={labelWidth} grow={true}>
<InlineField
label={t('dimensions.text-dimension-editor.label-source', 'Source')}
labelWidth={labelWidth}
grow={true}
>
<RadioButtonGroup value={mode} options={textOptions} onChange={onModeChange} fullWidth />
</InlineField>
</InlineFieldRow>
{mode !== TextDimensionMode.Fixed && (
<InlineFieldRow>
<InlineField label="Field" labelWidth={labelWidth} grow={true}>
<InlineField
label={t('dimensions.text-dimension-editor.label-field', 'Field')}
labelWidth={labelWidth}
grow={true}
>
<FieldNamePicker
context={context}
value={value.field ?? ''}
@ -103,7 +112,11 @@ export const TextDimensionEditor = ({ value, context, onChange }: Props) => {
)}
{mode === TextDimensionMode.Template && (
<InlineFieldRow>
<InlineField label="Template" labelWidth={labelWidth} grow={true}>
<InlineField
label={t('dimensions.text-dimension-editor.label-template', 'Template')}
labelWidth={labelWidth}
grow={true}
>
<StringValueEditor // This could be a code editor
context={context}
value={value?.fixed}

@ -13,6 +13,7 @@ import {
ThemeContext,
} from '@grafana/data';
import { Button, ColorPicker, colors, IconButton, Input, Label, RadioButtonGroup, stylesFactory } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
const modes: Array<SelectableValue<ThresholdsMode>> = [
{ value: ThresholdsMode.Absolute, label: 'Absolute', description: 'Pick thresholds based on the absolute values' },
@ -219,7 +220,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
className={styles.addButton}
fullWidth
>
Add threshold
<Trans i18nKey="dimensions.thresholds-editor.add-threshold">Add threshold</Trans>
</Button>
<div className={styles.thresholds}>
{steps
@ -233,7 +234,14 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
</div>
<div>
<Label description="Percentage means thresholds relative to min & max">Thresholds mode</Label>
<Label
description={t(
'dimensions.thresholds-editor.description-percentage-means-thresholds-relative',
'Percentage means thresholds relative to min & max'
)}
>
<Trans i18nKey="dimensions.thresholds-editor.thresholds-mode">Thresholds mode</Trans>
</Label>
<RadioButtonGroup options={modes} onChange={this.onModeChanged} value={thresholds.mode} />
</div>
</div>

@ -4,6 +4,7 @@ import { Dispatch, SetStateAction } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Field, Input, Label, useStyles2 } from '@grafana/ui';
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
import { t } from 'app/core/internationalization';
import { getPublicOrAbsoluteUrl } from '../resource';
import { MediaType } from '../types';
@ -31,7 +32,7 @@ export const URLPickerTab = (props: Props) => {
<Input onChange={(e) => setNewValue(e.currentTarget.value)} value={newValue} />
</Field>
<div className={styles.iconContainer}>
<Field label="Preview">
<Field label={t('dimensions.urlpicker-tab.label-preview', 'Preview')}>
<div className={styles.iconPreview}>
{mediaType === MediaType.Icon && <SanitizedSVG src={imgSrc} className={styles.img} />}
{mediaType === MediaType.Image && newValue && (

@ -5,6 +5,7 @@ import * as React from 'react';
import { GrafanaTheme2, MappingType, SpecialValueMatch, SelectableValue, ValueMappingResult } from '@grafana/data';
import { useStyles2, Icon, Select, HorizontalGroup, ColorPicker, IconButton, Input, Button } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { ResourcePickerSize, ResourceFolderName, MediaType } from '../../types';
import { ResourcePicker } from '../ResourcePicker';
@ -144,20 +145,36 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
type="text"
value={key ?? ''}
onChange={onUpdateMatchValue}
placeholder="Exact value to match"
placeholder={t(
'dimensions.value-mapping-edit-row.placeholder-exact-value-to-match',
'Exact value to match'
)}
/>
)}
{mapping.type === MappingType.RangeToText && (
<div className={styles.rangeInputWrapper}>
<Input type="number" value={mapping.from ?? ''} placeholder="From" onChange={onChangeFrom} />
<Input type="number" value={mapping.to ?? ''} placeholder="To" onChange={onChangeTo} />
<Input
type="number"
value={mapping.from ?? ''}
placeholder={t('dimensions.value-mapping-edit-row.placeholder-from', 'From')}
onChange={onChangeFrom}
/>
<Input
type="number"
value={mapping.to ?? ''}
placeholder={t('dimensions.value-mapping-edit-row.placeholder-to', 'To')}
onChange={onChangeTo}
/>
</div>
)}
{mapping.type === MappingType.RegexToText && (
<Input
type="text"
value={mapping.pattern ?? ''}
placeholder="Regular expression"
placeholder={t(
'dimensions.value-mapping-edit-row.placeholder-regular-expression',
'Regular expression'
)}
onChange={onChangePattern}
/>
)}
@ -170,20 +187,33 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
)}
</td>
<td>
<Input type="text" value={result.text ?? ''} onChange={onChangeText} placeholder="Optional display text" />
<Input
type="text"
value={result.text ?? ''}
onChange={onChangeText}
placeholder={t(
'dimensions.value-mapping-edit-row.placeholder-optional-display-text',
'Optional display text'
)}
/>
</td>
<td className={styles.textAlignCenter}>
{result.color && (
<HorizontalGroup spacing="sm" justify="center">
<ColorPicker color={result.color} onChange={onChangeColor} enableNamedColors={true} />
<IconButton name="times" onClick={onClearColor} tooltip="Remove color" tooltipPlacement="top" />
<IconButton
name="times"
onClick={onClearColor}
tooltip={t('dimensions.value-mapping-edit-row.tooltip-remove-color', 'Remove color')}
tooltipPlacement="top"
/>
</HorizontalGroup>
)}
{!result.color && (
<ColorPicker color={'gray'} onChange={onChangeColor} enableNamedColors={true}>
{(props) => (
<Button variant="primary" fill="text" onClick={props.showColorPicker} ref={props.ref} size="sm">
Set color
<Trans i18nKey="dimensions.value-mapping-edit-row.set-color">Set color</Trans>
</Button>
)}
</ColorPicker>
@ -202,7 +232,12 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
color={result.color}
/>
{result.icon && (
<IconButton name="times" onClick={onClearIcon} tooltip="Remove icon" tooltipPlacement="top" />
<IconButton
name="times"
onClick={onClearIcon}
tooltip={t('dimensions.value-mapping-edit-row.tooltip-remove-icon', 'Remove icon')}
tooltipPlacement="top"
/>
)}
</HorizontalGroup>
</td>
@ -213,15 +248,21 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
name="copy"
onClick={() => onDuplicate(index)}
data-testid="duplicate-value-mapping"
aria-label="Duplicate value mapping"
tooltip="Duplicate"
aria-label={t(
'dimensions.value-mapping-edit-row.duplicate-value-mapping-aria-label-duplicate-value-mapping',
'Duplicate value mapping'
)}
tooltip={t('dimensions.value-mapping-edit-row.duplicate-value-mapping-tooltip-duplicate', 'Duplicate')}
/>
<IconButton
name="trash-alt"
onClick={() => onRemove(index)}
data-testid="remove-value-mapping"
aria-label="Delete value mapping"
tooltip="Delete"
aria-label={t(
'dimensions.value-mapping-edit-row.remove-value-mapping-aria-label-delete-value-mapping',
'Delete value mapping'
)}
tooltip={t('dimensions.value-mapping-edit-row.remove-value-mapping-tooltip-delete', 'Delete')}
/>
</HorizontalGroup>
</td>

@ -3,6 +3,7 @@ import { memo, useCallback, useMemo, useState } from 'react';
import { GrafanaTheme2, MappingType, StandardEditorProps, ValueMapping } from '@grafana/data';
import { useStyles2, VerticalGroup, Icon, ColorPicker, Button, Modal } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { MediaType, ResourceFolderName, ResourcePickerSize } from '../../types';
import { ResourcePicker } from '../ResourcePicker';
@ -88,12 +89,20 @@ export const ValueMappingsEditor = memo((props: Props) => {
</table>
<Button variant="secondary" size="sm" fullWidth onClick={() => setIsEditorOpen(true)}>
{rows.length > 0 && <span>Edit value mappings</span>}
{rows.length === 0 && <span>Add value mappings</span>}
{rows.length > 0 && (
<span>
<Trans i18nKey="dimensions.value-mappings-editor.edit-value-mappings">Edit value mappings</Trans>
</span>
)}
{rows.length === 0 && (
<span>
<Trans i18nKey="dimensions.value-mappings-editor.add-value-mappings">Add value mappings</Trans>
</span>
)}
</Button>
<Modal
isOpen={isEditorOpen}
title="Value mappings"
title={t('dimensions.value-mappings-editor.title-value-mappings', 'Value mappings')}
onDismiss={onCloseEditor}
className={styles.modal}
closeOnBackdropClick={false}

@ -5,6 +5,7 @@ import { useEffect, useState } from 'react';
import { GrafanaTheme2, MappingType, SelectableValue, SpecialValueMatch, ValueMapping } from '@grafana/data';
import { useStyles2, Modal, ValuePicker, Button } from '@grafana/ui';
import { Trans, t } from 'app/core/internationalization';
import { ValueMappingEditRow, ValueMappingEditRowModel } from './ValueMappingEditRow';
@ -91,11 +92,19 @@ export function ValueMappingsEditorModal({ value, onChange, onClose, showIconPic
<tr>
<th style={{ width: '1%' }}></th>
<th style={{ width: '40%', textAlign: 'left' }} colSpan={2}>
Condition
<Trans i18nKey="dimensions.value-mappings-editor-modal.condition">Condition</Trans>
</th>
<th style={{ textAlign: 'left' }}>Display text</th>
<th style={{ width: '10%' }}>Color</th>
{showIconPicker && <th style={{ width: '10%' }}>Icon</th>}
<th style={{ textAlign: 'left' }}>
<Trans i18nKey="dimensions.value-mappings-editor-modal.display-text">Display text</Trans>
</th>
<th style={{ width: '10%' }}>
<Trans i18nKey="dimensions.value-mappings-editor-modal.color">Color</Trans>
</th>
{showIconPicker && (
<th style={{ width: '10%' }}>
<Trans i18nKey="dimensions.value-mappings-editor-modal.icon">Icon</Trans>
</th>
)}
<th style={{ width: '1%' }}></th>
</tr>
</thead>
@ -125,7 +134,7 @@ export function ValueMappingsEditorModal({ value, onChange, onClose, showIconPic
<Modal.ButtonRow
leftItems={
<ValuePicker
label="Add a new mapping"
label={t('dimensions.value-mappings-editor-modal.label-add-a-new-mapping', 'Add a new mapping')}
variant="secondary"
size="md"
icon="plus"
@ -137,10 +146,10 @@ export function ValueMappingsEditorModal({ value, onChange, onClose, showIconPic
}
>
<Button variant="secondary" fill="outline" onClick={onClose}>
Cancel
<Trans i18nKey="dimensions.value-mappings-editor-modal.cancel">Cancel</Trans>
</Button>
<Button variant="primary" onClick={onUpdate}>
Update
<Trans i18nKey="dimensions.value-mappings-editor-modal.update">Update</Trans>
</Button>
</Modal.ButtonRow>
</>

@ -18,6 +18,7 @@ import { memo, Dispatch, SetStateAction, useMemo } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, Switch, useStyles2 } from '@grafana/ui';
import { getButtonStyles } from '@grafana/ui/internal';
import { Trans } from 'app/core/internationalization';
import { SearchProps } from '../../../useSearch';
import { Trace } from '../../types';
@ -83,7 +84,7 @@ export default memo(function TracePageSearchBar(props: TracePageSearchBarProps)
aria-label="Clear filters button"
onClick={clear}
>
Clear
<Trans i18nKey="explore.clear">Clear</Trans>
</Button>
<div className={styles.matchesOnly}>
<Switch
@ -99,7 +100,7 @@ export default memo(function TracePageSearchBar(props: TracePageSearchBarProps)
fill="text"
disabled={!spanFilterMatches?.size}
>
Show matches only
<Trans i18nKey="explore.show-matches-only">Show matches only</Trans>
</Button>
</div>
<div className={styles.matchesOnly}>
@ -114,7 +115,7 @@ export default memo(function TracePageSearchBar(props: TracePageSearchBarProps)
variant="secondary"
fill="text"
>
Show critical path only
<Trans i18nKey="explore.show-critical-path-only">Show critical path only</Trans>
</Button>
</div>
</div>

@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef } from 'react';
import { DataSourceApi, QueryEditorProps, SelectableValue } from '@grafana/data';
import { InlineField, Select } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { ClassicConditions } from './components/ClassicConditions';
import { Math } from './components/Math';
@ -103,7 +104,10 @@ export function ExpressionQueryEditor(props: Props) {
return (
<div>
<InlineField label="Operation" labelWidth={labelWidth}>
<InlineField
label={t('expressions.expression-query-editor.label-operation', 'Operation')}
labelWidth={labelWidth}
>
<Select options={expressionTypes} value={selected} onChange={onSelectExpressionType} width={25} />
</InlineField>
{renderExpressionType()}

@ -1,5 +1,6 @@
import { SelectableValue } from '@grafana/data';
import { Button, Icon, InlineField, InlineFieldRow } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { ClassicCondition, ExpressionQuery } from '../types';
import { defaultCondition } from '../utils/expressionTypes';
@ -60,7 +61,7 @@ export const ClassicConditions = ({ onChange, query, refIds }: Props) => {
return (
<div>
<InlineFieldRow>
<InlineField label="Conditions" labelWidth={14}>
<InlineField label={t('expressions.classic-conditions.label-conditions', 'Conditions')} labelWidth={14}>
<div>
{query.conditions?.map((condition, index) => {
if (!condition) {

@ -4,6 +4,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Icon, InlineField, InlineLabel, TextArea, Toggletip, useStyles2, Stack } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { ExpressionQuery } from '../types';
@ -46,7 +47,9 @@ export const Math = ({ labelWidth, onChange, query, onRunQuery }: Props) => {
<br />
Example: <code>$A + $B</code>
</div>
<header className={styles.documentationHeader}>Available Math functions</header>
<header className={styles.documentationHeader}>
<Trans i18nKey="expressions.math.available-math-functions">Available math functions</Trans>
</header>
<div className={styles.documentationFunctions}>
<DocumentedFunction
name="abs"

@ -67,7 +67,10 @@ export const Reduce = ({ labelWidth = 'auto', onChange, app, refIds, query }: Pr
return;
}
return (
<InlineField label="Replace With" labelWidth={labelWidth}>
<InlineField
label={t('expressions.reduce.replace-with-number.label-replace-with', 'Replace with')}
labelWidth={labelWidth}
>
<Input type="number" width={10} onChange={onReplaceWithChanged} value={query.settings?.replaceWithValue ?? 0} />
</InlineField>
);
@ -97,15 +100,15 @@ export const Reduce = ({ labelWidth = 'auto', onChange, app, refIds, query }: Pr
<>
{strictModeNotification()}
<InlineFieldRow>
<InlineField label="Input" labelWidth={labelWidth}>
<InlineField label={t('expressions.reduce.label-input', 'Input')} labelWidth={labelWidth}>
<Select onChange={onRefIdChange} options={refIds} value={query.expression} width={'auto'} />
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<InlineField label="Function" labelWidth={labelWidth}>
<InlineField label={t('expressions.reduce.label-function', 'Function')} labelWidth={labelWidth}>
<Select options={reducerTypes} value={reducer} onChange={onSelectReducer} width={20} />
</InlineField>
<InlineField label="Mode" labelWidth={labelWidth}>
<InlineField label={t('expressions.reduce.label-mode', 'Mode')} labelWidth={labelWidth}>
<Select onChange={onModeChanged} options={reducerModes} value={mode} width={25} />
</InlineField>
{replaceWithNumber()}

@ -2,6 +2,7 @@ import { ChangeEvent } from 'react';
import { SelectableValue } from '@grafana/data';
import { InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { downsamplingTypes, ExpressionQuery, upsamplingTypes } from '../types';
@ -35,18 +36,22 @@ export const Resample = ({ labelWidth = 'auto', onChange, refIds, query }: Props
return (
<>
<InlineFieldRow>
<InlineField label="Input" labelWidth={labelWidth}>
<InlineField label={t('expressions.resample.label-input', 'Input')} labelWidth={labelWidth}>
<Select onChange={onRefIdChange} options={refIds} value={query.expression} width={20} />
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<InlineField label="Resample to" labelWidth={labelWidth} tooltip="10s, 1m, 30m, 1h">
<InlineField
label={t('expressions.resample.label-resample-to', 'Resample to')}
labelWidth={labelWidth}
tooltip={t('expressions.resample.tooltip-s-m-h', '10s, 1m, 30m, 1h')}
>
<Input onChange={onWindowChange} value={query.window} width={15} />
</InlineField>
<InlineField label="Downsample">
<InlineField label={t('expressions.resample.label-downsample', 'Downsample')}>
<Select options={downsamplingTypes} value={downsampler} onChange={onSelectDownsampler} width={25} />
</InlineField>
<InlineField label="Upsample">
<InlineField label={t('expressions.resample.label-upsample', 'Upsample')}>
<Select options={upsamplingTypes} value={upsampler} onChange={onSelectUpsampler} width={25} />
</InlineField>
</InlineFieldRow>

@ -93,7 +93,7 @@ export const Threshold = ({ labelWidth, onChange, refIds, query, onError, useHys
return (
<>
<InlineFieldRow>
<InlineField label="Input" labelWidth={labelWidth} htmlFor={id}>
<InlineField label={t('expressions.threshold.label-input', 'Input')} labelWidth={labelWidth} htmlFor={id}>
<Select inputId={id} onChange={onRefIdChange} options={refIds} value={query.expression} width={20} />
</InlineField>
</InlineFieldRow>

@ -3,7 +3,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, Icon, LoadingPlaceholder, Stack, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { IrmCardConfiguration } from './ConfigureIRM';
import { ProgressBar, StepsStatus } from './ProgressBar';
@ -39,7 +39,13 @@ export function ConfigCard({ config, handleActionClick, isLoading = false }: Con
)}
</Stack>
<Stack direction={'column'}>
{!isLoading ? config.description : <LoadingPlaceholder text="Loading configuration...." />}
{!isLoading ? (
config.description
) : (
<LoadingPlaceholder
text={t('gops.config-card.text-loading-configuration', 'Loading configuration....')}
/>
)}
{/* Only show ProgressBar when not loading */}
{!isLoading && config.stepsDone && config.totalStepsToDo && (
<ProgressBar stepsDone={config.stepsDone} totalStepsToDo={config.totalStepsToDo} />

@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom-v5-compat';
import { GrafanaTheme2 } from '@grafana/data';
import { IconName, Text, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { useURLSearchParams } from 'app/features/alerting/unified/hooks/useURLSearchParams';
import { getFirstCompatibleDataSource } from 'app/features/alerting/unified/utils/datasource';
import { DATASOURCES_ROUTES } from 'app/features/datasources/constants';
@ -103,7 +104,7 @@ export function ConfigureIRM() {
return (
<>
<Text element="h4" variant="h4">
Configure
<Trans i18nKey="gops.configure-irm.configure">Configure</Trans>
</Text>
<section className={styles.container}>
{configuration.map((config) => (
@ -124,7 +125,7 @@ export function ConfigureIRM() {
)}
</section>
<Text element="h4" variant="h4">
IRM apps
<Trans i18nKey="gops.configure-irm.irm-apps">IRM apps</Trans>
</Text>
</>
);

@ -2,6 +2,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, Drawer, Dropdown, Icon, LinkButton, Menu, Stack, Text, Tooltip, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { RelativeUrl, createRelativeUrl } from 'app/features/alerting/unified/utils/url';
import { SectionDto, SectionDtoStep, SectionsDto, StepButtonDto } from '../irmHooks';
@ -17,7 +18,11 @@ export interface EssentialsProps {
export function Essentials({ onClose, essentialsConfig, stepsDone, totalStepsToDo }: EssentialsProps) {
return (
<Drawer title="Essentials" subtitle="Complete the following configuration tasks" onClose={onClose}>
<Drawer
title={t('gops.essentials.title-essentials', 'Essentials')}
subtitle="Complete the following configuration tasks"
onClose={onClose}
>
<EssentialContent essentialContent={essentialsConfig} stepsDone={stepsDone} totalStepsToDo={totalStepsToDo} />
</Drawer>
);

@ -258,7 +258,11 @@ export class InspectDataTab extends PureComponent<Props, State> {
const dataFrames = this.getProcessedData();
if (!dataFrames || !dataFrames.length) {
return <div>No Data</div>;
return (
<div>
<Trans i18nKey="inspector.inspect-data-tab.no-data">No data</Trans>
</div>
);
}
// let's make sure we don't try to render a frame that doesn't exists

@ -9,7 +9,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { locationService } from '@grafana/runtime';
import { Button, CodeEditor, Field, Select, useStyles2 } from '@grafana/ui';
import { appEvents } from 'app/core/core';
import { t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
@ -130,12 +130,12 @@ export function InspectJSONTab({ panel, dashboard, data, onClose }: Props) {
</Field>
{panel && isPanelJSON && canEdit && (
<Button className={styles.toolbarItem} onClick={onApplyPanelModel}>
Apply
<Trans i18nKey="inspector.inspect-jsontab.apply">Apply</Trans>
</Button>
)}
{show === ShowContent.DataFrames && dashboard !== undefined && (
<Button className={styles.toolbarItem} onClick={onShowHelpWizard}>
Support
<Trans i18nKey="inspector.inspect-jsontab.support">Support</Trans>
</Button>
)}
</div>

@ -6,7 +6,7 @@ import { LoadingState, PanelData } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config } from '@grafana/runtime';
import { Button, ClipboardButton, JSONFormatter, LoadingPlaceholder, Space, Stack } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { backendSrv } from 'app/core/services/backend_srv';
import { getPanelInspectorStyles2 } from './styles';
@ -228,7 +228,9 @@ export class QueryInspector extends PureComponent<Props, State> {
return (
<div className={styles.wrap}>
<div aria-label={selectors.components.PanelInspector.Query.content}>
<h3 className={styles.heading}>Query inspector</h3>
<h3 className={styles.heading}>
<Trans i18nKey="inspector.query-inspector.query-inspector">Query inspector</Trans>
</h3>
<p className="small muted">
<Trans i18nKey="inspector.query.description">
Query inspector allows you to view raw request and response. To collect this data Grafana needs to issue a
@ -265,7 +267,11 @@ export class QueryInspector extends PureComponent<Props, State> {
</Stack>
<Space v={2} />
<div className={styles.content}>
{isLoading && <LoadingPlaceholder text="Loading query inspector..." />}
{isLoading && (
<LoadingPlaceholder
text={t('inspector.query-inspector.text-loading-query-inspector', 'Loading query inspector...')}
/>
)}
{!isLoading && haveData && (
<JSONFormatter json={response} open={openNodes} onDidRender={this.setFormattedJson} />
)}

@ -2,6 +2,7 @@ import { PureComponent } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { Button, ClipboardButton } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { Invitee } from 'app/types';
import { revokeInvite } from './state/actions';
@ -37,7 +38,7 @@ class InviteeRow extends PureComponent<Props> {
size="sm"
icon="times"
onClick={() => revokeInvite(invitee.code)}
aria-label="Revoke Invite"
aria-label={t('invites.invitee-row.aria-label-revoke-invite', 'Revoke invite')}
/>
</td>
</tr>

@ -55,7 +55,7 @@ describe('InviteesTable', () => {
expect(rows.length).toEqual(6);
rows.forEach((row) => {
expect(within(row).getByRole('button', { name: 'Revoke Invite' })).toBeInTheDocument();
expect(within(row).getByRole('button', { name: 'Revoke invite' })).toBeInTheDocument();
});
});
});

@ -1,5 +1,6 @@
import { PureComponent } from 'react';
import { Trans } from 'app/core/internationalization';
import { Invitee } from 'app/types';
import InviteeRow from './InviteeRow';
@ -16,8 +17,12 @@ export default class InviteesTable extends PureComponent<Props> {
<table className="filter-table form-inline">
<thead>
<tr>
<th>Email</th>
<th>Name</th>
<th>
<Trans i18nKey="invites.invitees-table.email">Email</Trans>
</th>
<th>
<Trans i18nKey="invites.invitees-table.name">Name</Trans>
</th>
<th />
<th style={{ width: '34px' }} />
</tr>

@ -9,6 +9,7 @@ import { Button, Field, Input, useStyles2 } from '@grafana/ui';
import { Form } from 'app/core/components/Form/Form';
import { Page } from 'app/core/components/Page/Page';
import { getConfig } from 'app/core/config';
import { t, Trans } from 'app/core/internationalization';
import { w3cStandardEmailValidator } from '../admin/utils';
@ -76,8 +77,13 @@ export const SignupInvitedPage = () => {
<Form defaultValues={initFormModel} onSubmit={onSubmit}>
{({ register, errors }) => (
<>
<Field invalid={!!errors.email} error={errors.email && errors.email.message} label="Email">
<Field
invalid={!!errors.email}
error={errors.email && errors.email.message}
label={t('invites.signup-invited-page.label-email', 'Email')}
>
<Input
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="email@example.com"
{...register('email', {
required: 'Email is required',
@ -88,21 +94,41 @@ export const SignupInvitedPage = () => {
})}
/>
</Field>
<Field invalid={!!errors.name} error={errors.name && errors.name.message} label="Name">
<Input placeholder="Name (optional)" {...register('name')} />
<Field
invalid={!!errors.name}
error={errors.name && errors.name.message}
label={t('invites.signup-invited-page.label-name', 'Name')}
>
<Input
placeholder={t('invites.signup-invited-page.placeholder-name-optional', 'Name (optional)')}
{...register('name')}
/>
</Field>
<Field invalid={!!errors.username} error={errors.username && errors.username.message} label="Username">
<Input {...register('username', { required: 'Username is required' })} placeholder="Username" />
<Field
invalid={!!errors.username}
error={errors.username && errors.username.message}
label={t('invites.signup-invited-page.label-username', 'Username')}
>
<Input
{...register('username', { required: 'Username is required' })}
placeholder={t('invites.signup-invited-page.placeholder-username', 'Username')}
/>
</Field>
<Field invalid={!!errors.password} error={errors.password && errors.password.message} label="Password">
<Field
invalid={!!errors.password}
error={errors.password && errors.password.message}
label={t('invites.signup-invited-page.label-password', 'Password')}
>
<Input
{...register('password', { required: 'Password is required' })}
type="password"
placeholder="Password"
placeholder={t('invites.signup-invited-page.placeholder-password', 'Password')}
/>
</Field>
<Button type="submit">Sign up</Button>
<Button type="submit">
<Trans i18nKey="invites.signup-invited-page.sign-up">Sign up</Trans>
</Button>
</>
)}
</Form>

@ -5,6 +5,7 @@ import { Unsubscribable } from 'rxjs';
import { GrafanaTheme2, OrgRole } from '@grafana/data';
import { config, getGrafanaLiveSrv } from '@grafana/runtime';
import { Alert, stylesFactory } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { contextSrv } from 'app/core/services/context_srv';
export interface Props {}
@ -52,7 +53,14 @@ export class LiveConnectionWarning extends PureComponent<Props, State> {
return (
<div className={this.styles.foot}>
<Alert severity={'warning'} className={this.styles.warn} title="connection to server is lost..." />
<Alert
severity={'warning'}
className={this.styles.warn}
title={t(
'live.live-connection-warning.title-connection-to-server-is-lost',
'Connection to server is lost...'
)}
/>
</div>
);
}

@ -3,6 +3,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { Button, Modal, useStyles2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { dashboardWatcher } from './dashboardWatcher';
import { DashboardEvent, DashboardEventAction } from './types';
@ -28,7 +29,7 @@ export function DashboardChangedModal({ onDismiss, event }: Props) {
return (
<Modal
isOpen={true}
title="Dashboard changed"
title={t('live.dashboard-changed-modal.title-dashboard-changed', 'Dashboard changed')}
icon="copy"
onDismiss={onDismiss}
onClickBackdrop={() => {}}
@ -40,10 +41,10 @@ export function DashboardChangedModal({ onDismiss, event }: Props) {
</div>
<Modal.ButtonRow>
<Button onClick={onDismiss} variant="secondary" fill="outline">
Continue editing
<Trans i18nKey="live.dashboard-changed-modal.continue-editing">Continue editing</Trans>
</Button>
<Button onClick={onDiscardChanges} variant="destructive">
Discard local changes
<Trans i18nKey="live.dashboard-changed-modal.discard-local-changes">Discard local changes</Trans>
</Button>
</Modal.ButtonRow>
</Modal>

@ -211,7 +211,7 @@ const styles = {
const outOfRangeMessage = (
<div className={styles.messageContainer} data-testid="end-of-range">
End of the selected time range.
<Trans i18nKey="logs.out-of-range-message.end-of-the-selected-time-range">End of the selected time range.</Trans>
</div>
);

@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { CoreApp, DataFrame, DataFrameType, Field, LinkModel, LogRowModel } from '@grafana/data';
import { PopoverContent, Themeable2, withTheme2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { calculateLogsLabelStats, calculateStats } from '../utils';
@ -83,7 +83,7 @@ class UnThemedLogDetails extends PureComponent<Props> {
return (
<tr className={cx(className, styles.logDetails)}>
{showDuplicates && <td />}
<td className={levelClassName} aria-label="Log level" />
<td className={levelClassName} aria-label={t('logs.un-themed-log-details.aria-label-log-level', 'Log level')} />
<td colSpan={4}>
<div className={styles.logDetailsContainer}>
<table className={styles.logDetailsTable}>
@ -91,7 +91,11 @@ class UnThemedLogDetails extends PureComponent<Props> {
{displayedFields && displayedFields.length > 0 && (
<>
<tr>
<td colSpan={100} className={styles.logDetailsHeading} aria-label="Fields">
<td
colSpan={100}
className={styles.logDetailsHeading}
aria-label={t('logs.un-themed-log-details.aria-label-fields', 'Fields')}
>
<Trans i18nKey="logs.log-details.log-line">Log line</Trans>
</td>
</tr>
@ -108,7 +112,11 @@ class UnThemedLogDetails extends PureComponent<Props> {
)}
{(labelsAvailable || fieldsAvailable) && (
<tr>
<td colSpan={100} className={styles.logDetailsHeading} aria-label="Fields">
<td
colSpan={100}
className={styles.logDetailsHeading}
aria-label={t('logs.un-themed-log-details.aria-label-fields', 'Fields')}
>
<Trans i18nKey="logs.log-details.fields">Fields</Trans>
</td>
</tr>
@ -161,7 +169,11 @@ class UnThemedLogDetails extends PureComponent<Props> {
{fieldsWithLinksAvailable && (
<tr>
<td colSpan={100} className={styles.logDetailsHeading} aria-label="Data Links">
<td
colSpan={100}
className={styles.logDetailsHeading}
aria-label={t('logs.un-themed-log-details.aria-label-data-links', 'Data links')}
>
<Trans i18nKey="logs.log-details.links">Links</Trans>
</td>
</tr>
@ -211,7 +223,7 @@ class UnThemedLogDetails extends PureComponent<Props> {
{!fieldsAvailable && !labelsAvailable && !fieldsWithLinksAvailable && (
<tr>
<td colSpan={100} aria-label="No details">
<td colSpan={100} aria-label={t('logs.un-themed-log-details.aria-label-no-details', 'No details')}>
<Trans i18nKey="logs.log-details.no-details">No details available</Trans>
</td>
</tr>

@ -4,6 +4,7 @@ import memoizeOne from 'memoize-one';
import { CoreApp, GrafanaTheme2, LogRowModel } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { IconButton, Themeable2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getLogRowStyles } from './getLogRowStyles';
@ -65,9 +66,18 @@ export const LogDetailsBody = (props: Props) => {
const toggleFieldButton =
displayedFields != null && displayedFields.includes(LOG_LINE_BODY_FIELD_NAME) ? (
<IconButton variant="primary" tooltip="Hide log line" name="eye" onClick={hideField} />
<IconButton
variant="primary"
tooltip={t('logs.log-details-body.toggle-field-button.tooltip-hide-log-line', 'Hide log line')}
name="eye"
onClick={hideField}
/>
) : (
<IconButton tooltip="Show log line" name="eye" onClick={showField} />
<IconButton
tooltip={t('logs.log-details-body.toggle-field-button.tooltip-show-log-line', 'Show log line')}
name="eye"
onClick={showField}
/>
);
return (

@ -24,6 +24,7 @@ import {
Tooltip,
withTheme2,
} from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { logRowToSingleRowDataFrame } from '../logsModel';
import { getLabelTypeFromRow } from '../utils';
@ -244,7 +245,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
<div className={`log-details-value-copy ${styles.copyButton}`}>
<ClipboardButton
getText={() => val}
title="Copy value to clipboard"
title={t('logs.un-themed-log-details-row.title-copy-value-to-clipboard', 'Copy value to clipboard')}
fill="text"
variant="secondary"
icon="copy"
@ -304,9 +305,21 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
const toggleFieldButton =
displayedFields && parsedKeys != null && displayedFields.includes(parsedKeys[0]) ? (
<IconButton variant="primary" tooltip="Hide this field" name="eye" onClick={this.hideField} />
<IconButton
variant="primary"
tooltip={t('logs.un-themed-log-details-row.toggle-field-button.tooltip-hide-this-field', 'Hide this field')}
name="eye"
onClick={this.hideField}
/>
) : (
<IconButton tooltip="Show this field instead of the message" name="eye" onClick={this.showField} />
<IconButton
tooltip={t(
'logs.un-themed-log-details-row.toggle-field-button.tooltip-field-instead-message',
'Show this field instead of the message'
)}
name="eye"
onClick={this.showField}
/>
);
return (
@ -335,7 +348,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
<IconButton
variant={showFieldsStats ? 'primary' : 'secondary'}
name="signal"
tooltip="Ad-hoc statistics"
tooltip={t('logs.un-themed-log-details-row.tooltip-adhoc-statistics', 'Ad-hoc statistics')}
className="stats-button"
disabled={!singleKey}
onClick={this.showStats}
@ -388,7 +401,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
<IconButton
variant={showFieldsStats ? 'primary' : 'secondary'}
name="signal"
tooltip="Hide ad-hoc statistics"
tooltip={t('logs.un-themed-log-details-row.tooltip-hide-adhoc-statistics', 'Hide ad-hoc statistics')}
onClick={this.showStats}
/>
</td>

@ -13,6 +13,7 @@ import {
import { LogRowContextOptions, LogRowModel } from '@grafana/data';
import { DataQuery } from '@grafana/schema';
import { ClipboardButton, IconButton, PopoverContent } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { handleOpenLogsContextClick } from '../utils';
@ -110,9 +111,9 @@ export const LogRowMenuCell = memo(
size="md"
name="gf-pin"
onClick={() => onUnpinLine && onUnpinLine(row)}
tooltip="Unpin line"
tooltip={t('logs.log-row-menu-cell.tooltip-unpin-line', 'Unpin line')}
tooltipPlacement="top"
aria-label="Unpin line"
aria-label={t('logs.log-row-menu-cell.aria-label-unpin-line', 'Unpin line')}
tabIndex={0}
/>
)}
@ -124,9 +125,9 @@ export const LogRowMenuCell = memo(
size="md"
name="gf-show-context"
onClick={onShowContextClick}
tooltip="Show context"
tooltip={t('logs.log-row-menu-cell.tooltip-show-context', 'Show context')}
tooltipPlacement="top"
aria-label="Show context"
aria-label={t('logs.log-row-menu-cell.aria-label-show-context', 'Show context')}
tabIndex={0}
/>
)}
@ -137,7 +138,7 @@ export const LogRowMenuCell = memo(
fill="text"
size="md"
getText={getLogText}
tooltip="Copy to clipboard"
tooltip={t('logs.log-row-menu-cell.tooltip-copy-to-clipboard', 'Copy to clipboard')}
tooltipPlacement="top"
tabIndex={0}
/>
@ -147,9 +148,9 @@ export const LogRowMenuCell = memo(
size="md"
name="gf-pin"
onClick={() => onUnpinLine && onUnpinLine(row)}
tooltip="Unpin line"
tooltip={t('logs.log-row-menu-cell.tooltip-unpin-line', 'Unpin line')}
tooltipPlacement="top"
aria-label="Unpin line"
aria-label={t('logs.log-row-menu-cell.aria-label-unpin-line', 'Unpin line')}
tabIndex={0}
/>
)}
@ -161,14 +162,14 @@ export const LogRowMenuCell = memo(
onClick={() => onPinLine && onPinLine(row)}
tooltip={pinLineButtonTooltipTitle ?? 'Pin line'}
tooltipPlacement="top"
aria-label="Pin line"
aria-label={t('logs.log-row-menu-cell.aria-label-pin-line', 'Pin line')}
tabIndex={0}
/>
)}
{onPermalinkClick && row.rowId !== undefined && row.uid && (
<IconButton
tooltip="Copy shortlink"
aria-label="Copy shortlink"
tooltip={t('logs.log-row-menu-cell.tooltip-copy-shortlink', 'Copy shortlink')}
aria-label={t('logs.log-row-menu-cell.aria-label-copy-shortlink', 'Copy shortlink')}
tooltipPlacement="top"
size="md"
name="share-alt"

@ -5,6 +5,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { Button, InlineSwitch, useStyles2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
export type Props = {
wrapLines?: boolean;
@ -37,9 +38,14 @@ export const LogContextButtons = (props: Props) => {
return (
<div className={styles.buttons}>
<InlineSwitch showLabel value={wrapLines} onChange={internalOnChangeWrapLines} label="Wrap lines" />
<InlineSwitch
showLabel
value={wrapLines}
onChange={internalOnChangeWrapLines}
label={t('logs.log-context-buttons.label-wrap-lines', 'Wrap lines')}
/>
<Button variant="secondary" onClick={onScrollCenterClick}>
Center matched line
<Trans i18nKey="logs.log-context-buttons.center-matched-line">Center matched line</Trans>
</Button>
</div>
);

@ -20,6 +20,7 @@ import {
import { config, reportInteraction } from '@grafana/runtime';
import { DataQuery, TimeZone } from '@grafana/schema';
import { Button, Modal, useTheme2 } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import store from 'app/core/store';
import { SETTINGS_KEYS } from 'app/features/explore/Logs/utils/logs';
import { splitOpen } from 'app/features/explore/state/main';
@ -495,7 +496,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
return (
<Modal
isOpen={open}
title="Log context"
title={t('logs.log-row-context-modal.title-log-context', 'Log context')}
contentClassName={styles.flexColumn}
className={styles.modal}
onDismiss={onClose}
@ -522,8 +523,18 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
<LoadingIndicator adjective="newer" />
</div>
)}
{loadingStateAbove === LoadingState.Error && <div>Error loading log more logs.</div>}
{loadingStateAbove === LoadingState.Done && <div>No more logs available.</div>}
{loadingStateAbove === LoadingState.Error && (
<div>
<Trans i18nKey="logs.log-row-context-modal.error-loading-log-more-logs">
Error loading more logs.
</Trans>
</div>
)}
{loadingStateAbove === LoadingState.Done && (
<div>
<Trans i18nKey="logs.log-row-context-modal.no-more-logs-available">No more logs available.</Trans>
</div>
)}
</td>
</tr>
<tr>
@ -594,8 +605,18 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
<LoadingIndicator adjective="older" />
</div>
)}
{loadingStateBelow === LoadingState.Error && <div>Error loading log more logs.</div>}
{loadingStateBelow === LoadingState.Done && <div>No more logs available.</div>}
{loadingStateBelow === LoadingState.Error && (
<div>
<Trans i18nKey="logs.log-row-context-modal.error-loading-log-more-logs">
Error loading more logs.
</Trans>
</div>
)}
{loadingStateBelow === LoadingState.Done && (
<div>
<Trans i18nKey="logs.log-row-context-modal.no-more-logs-available">No more logs available.</Trans>
</div>
)}
</td>
</tr>
</tbody>
@ -632,7 +653,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
});
}}
>
Open in split view
<Trans i18nKey="logs.log-row-context-modal.open-in-split-view">Open in split view</Trans>
</Button>
)}
</Modal.ButtonRow>

@ -127,6 +127,7 @@ class UnthemedDashboardImport extends PureComponent<Props> {
const styles = importStyles(this.props.theme);
const GcomDashboardsLink = () => (
// eslint-disable-next-line @grafana/no-untranslated-strings
<TextLink variant="bodySmall" href="https://grafana.com/grafana/dashboards/" external>
grafana.com/dashboards
</TextLink>

@ -5,6 +5,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { ExpressionDatasourceRef } from '@grafana/runtime/internal';
import { Button, Field, FormFieldErrors, FormsOnSubmit, Stack, Input, Legend } from '@grafana/ui';
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { Trans, t } from 'app/core/internationalization';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import {
@ -57,8 +58,14 @@ export const ImportDashboardForm = ({
return (
<>
<Legend>Options</Legend>
<Field label="Name" invalid={!!errors.title} error={errors.title && errors.title.message}>
<Legend>
<Trans i18nKey="manage-dashboards.import-dashboard-form.options">Options</Trans>
</Legend>
<Field
label={t('manage-dashboards.import-dashboard-form.label-name', 'Name')}
invalid={!!errors.title}
error={errors.title && errors.title.message}
>
<Input
{...register('title', {
required: 'Name is required',
@ -68,7 +75,7 @@ export const ImportDashboardForm = ({
data-testid={selectors.components.ImportDashboardForm.name}
/>
</Field>
<Field label="Folder">
<Field label={t('manage-dashboards.import-dashboard-form.label-folder', 'Folder')}>
<Controller
render={({ field: { ref, value, onChange, ...field } }) => (
<FolderPicker {...field} onChange={(uid, title) => onChange({ uid, title })} value={value.uid} />
@ -78,7 +85,7 @@ export const ImportDashboardForm = ({
/>
</Field>
<Field
label="Unique identifier (UID)"
label={t('manage-dashboards.import-dashboard-form.label-unique-identifier-uid', 'Unique identifier (UID)')}
description="The unique identifier (UID) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
The UID allows having consistent URLs for accessing dashboards so changing the title of a dashboard will not break any
bookmarked links to that dashboard."
@ -90,7 +97,13 @@ export const ImportDashboardForm = ({
<Input
disabled
{...register('uid', { validate: async (v: string) => await validateUid(v) })}
addonAfter={!uidReset && <Button onClick={onUidReset}>Change uid</Button>}
addonAfter={
!uidReset && (
<Button onClick={onUidReset}>
<Trans i18nKey="manage-dashboards.import-dashboard-form.change-uid">Change uid</Trans>
</Button>
)
}
/>
) : (
<Input {...register('uid', { required: true, validate: async (v: string) => await validateUid(v) })} />
@ -145,13 +158,16 @@ export const ImportDashboardForm = ({
})}
<ImportDashboardLibraryPanelsList
inputs={newLibraryPanels}
label="New library panels"
description="List of new library panels that will get imported."
label={t('manage-dashboards.import-dashboard-form.label-new-library-panels', 'New library panels')}
description={t(
'manage-dashboards.import-dashboard-form.description-library-panels-imported',
'List of new library panels that will get imported.'
)}
folderName={watchFolder.title}
/>
<ImportDashboardLibraryPanelsList
inputs={existingLibraryPanels}
label="Existing library panels"
label={t('manage-dashboards.import-dashboard-form.label-existing-library-panels', 'Existing library panels')}
description="List of existing library panels. These panels are not affected by the import."
folderName={watchFolder.title}
/>
@ -167,7 +183,7 @@ export const ImportDashboardForm = ({
{getButtonText(errors)}
</Button>
<Button type="reset" variant="secondary" onClick={onCancel}>
Cancel
<Trans i18nKey="manage-dashboards.import-dashboard-form.cancel">Cancel</Trans>
</Button>
</Stack>
</>

@ -5,6 +5,7 @@ import { dateTimeFormat } from '@grafana/data';
import { locationService, reportInteraction } from '@grafana/runtime';
import { Box, Legend } from '@grafana/ui';
import { Form } from 'app/core/components/Form/Form';
import { Trans } from 'app/core/internationalization';
import { StoreState } from 'app/types';
import { clearLoadedDashboard, importDashboard } from '../state/actions';
@ -82,11 +83,19 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
<table className="filter-table form-inline">
<tbody>
<tr>
<td>Published by</td>
<td>
<Trans i18nKey="manage-dashboards.import-dashboard-overview-un-connected.published-by">
Published by
</Trans>
</td>
<td>{meta.orgName}</td>
</tr>
<tr>
<td>Updated on</td>
<td>
<Trans i18nKey="manage-dashboards.import-dashboard-overview-un-connected.updated-on">
Updated on
</Trans>
</td>
<td>{dateTimeFormat(meta.updatedAt)}</td>
</tr>
</tbody>

@ -103,7 +103,7 @@ export const SnapshotListTable = () => {
<ConfirmModal
isOpen={!!removeSnapshot}
icon="trash-alt"
title="Delete"
title={t('manage-dashboards.snapshot-list-table.title-delete', 'Delete')}
body={`Are you sure you want to delete '${removeSnapshot?.name}'?`}
confirmText="Delete"
onDismiss={() => setRemoveSnapshot(undefined)}

@ -126,7 +126,9 @@ function FolderInfo({ data }: { data: ResourceTableItem }) {
if (isError) {
return (
<>
<Text italic>Unable to load folder</Text>
<Text italic>
<Trans i18nKey="migrate-to-cloud.folder-info.unable-to-load-folder">Unable to load folder</Trans>
</Text>
<Text color="secondary">Folder {data.refId}</Text>
</>
);

@ -75,7 +75,7 @@ export function StoredNotifications() {
onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleAllCheckboxToggle(event.target.checked)}
/>
<Button disabled={selectedNotificationIds.length === 0} onClick={clearSelectedNotifications}>
Dismiss notifications
<Trans i18nKey="notifications.stored-notifications.dismiss-notifications">Dismiss notifications</Trans>
</Button>
</div>
<ul className={styles.list}>

@ -12,6 +12,7 @@ import { PanelDataErrorViewProps, locationService } from '@grafana/runtime';
import { usePanelContext, useStyles2 } from '@grafana/ui';
import { CardButton } from 'app/core/components/CardButton';
import { LS_VISUALIZATION_SELECT_TAB_KEY } from 'app/core/constants';
import { Trans } from 'app/core/internationalization';
import store from 'app/core/store';
import { toggleVizPicker } from 'app/features/dashboard/components/PanelEditor/state/reducers';
import { VisualizationSelectPaneTab } from 'app/features/dashboard/components/PanelEditor/types';
@ -81,10 +82,12 @@ export function PanelDataErrorView(props: PanelDataErrorViewProps) {
</>
)}
<CardButton icon="table" onClick={switchToTable}>
Switch to table
<Trans i18nKey="panel.panel-data-error-view.switch-to-table">Switch to table</Trans>
</CardButton>
<CardButton icon="chart-line" onClick={openVizPicker}>
Open visualization suggestions
<Trans i18nKey="panel.panel-data-error-view.open-visualization-suggestions">
Open visualization suggestions
</Trans>
</CardButton>
</div>
)}

@ -12,6 +12,7 @@ import {
import { getTemplateSrv, PanelRendererProps } from '@grafana/runtime';
import { ErrorBoundaryAlert, usePanelContext, useTheme2 } from '@grafana/ui';
import { appEvents } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import { importPanelPlugin, syncGetPanelPlugin } from '../../plugins/importPanelPlugin';
@ -68,7 +69,11 @@ export function PanelRenderer<P extends object = {}, F extends object = {}>(prop
}
if (!plugin || !plugin.hasPluginId(pluginId)) {
return <div>Loading plugin panel...</div>;
return (
<div>
<Trans i18nKey="panel.panel-renderer.loading-plugin-panel">Loading plugin panel...</Trans>
</div>
);
}
if (!plugin.panel) {
@ -76,7 +81,11 @@ export function PanelRenderer<P extends object = {}, F extends object = {}>(prop
}
if (!dataWithOverrides) {
return <div>No panel data</div>;
return (
<div>
<Trans i18nKey="panel.panel-renderer.no-panel-data">No panel data</Trans>
</div>
);
}
const PanelComponent = plugin.panel;

@ -7,6 +7,7 @@ import { GrafanaTheme2, isUnsignedPluginSignature, PanelPluginMeta, PluginState
import { selectors } from '@grafana/e2e-selectors';
import { IconButton, PluginSignatureBadge, useStyles2 } from '@grafana/ui';
import { SkeletonComponent, attachSkeleton } from '@grafana/ui/unstable';
import { t } from 'app/core/internationalization';
import { PluginStateInfo } from 'app/features/plugins/components/PluginStateInfo';
interface Props {
@ -71,8 +72,11 @@ const PanelTypeCardComponent = ({
onDelete();
}}
className={styles.deleteButton}
aria-label="Delete button on panel type card"
tooltip="Delete"
aria-label={t(
'panel.panel-type-card.aria-label-delete-button-on-panel-type-card',
'Delete button on panel type card'
)}
tooltip={t('panel.panel-type-card.tooltip-delete', 'Delete')}
/>
)}
</div>

@ -5,6 +5,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
import { GrafanaTheme2, PanelData, PanelModel, VisualizationSuggestion } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { getAllSuggestions } from '../../state/getAllSuggestions';
@ -47,7 +48,9 @@ export function VisualizationSuggestions({ searchQuery, onChange, data, panel, t
return (
<div>
<div className={styles.filterRow}>
<div className={styles.infoText}>Based on current data</div>
<div className={styles.infoText}>
<Trans i18nKey="panel.visualization-suggestions.based-on-current-data">Based on current data</Trans>
</div>
</div>
<div className={styles.grid} style={{ gridTemplateColumns: `repeat(auto-fill, ${previewWidth}px)` }}>
{filteredSuggestions.map((suggestion, index) => (
@ -60,7 +63,11 @@ export function VisualizationSuggestions({ searchQuery, onChange, data, panel, t
/>
))}
{searchQuery && filteredSuggestions.length === 0 && (
<div className={styles.infoText}>No results matched your query</div>
<div className={styles.infoText}>
<Trans i18nKey="panel.visualization-suggestions.no-results-matched-your-query">
No results matched your query
</Trans>
</div>
)}
</div>
</div>

@ -3,6 +3,7 @@ import { useMemo } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { EmptySearchResult, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { filterPluginList, getAllPanelPluginMeta } from '../../state/util';
@ -29,7 +30,13 @@ export function VizTypePicker({ pluginId, searchQuery, onChange, trackSearch }:
}, [pluginsList, searchQuery, pluginId, trackSearch]);
if (filteredPluginTypes.length === 0) {
return <EmptySearchResult>Could not find anything matching your query</EmptySearchResult>;
return (
<EmptySearchResult>
<Trans i18nKey="panel.viz-type-picker.could-anything-matching-query">
Could not find anything matching your query
</Trans>
</EmptySearchResult>
);
}
return (

@ -6,6 +6,7 @@ import { PureComponent } from 'react';
import { PluginMeta, AppPlugin, deprecationWarning } from '@grafana/data';
import { AngularComponent, getAngularLoader, getBackendSrv } from '@grafana/runtime';
import { Button } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
interface Props {
app: AppPlugin;
@ -74,17 +75,17 @@ export class AppConfigCtrlWrapper extends PureComponent<Props, State> {
<div className="gf-form">
{!model.enabled && (
<Button variant="primary" onClick={this.enable} className={withRightMargin}>
Enable
<Trans i18nKey="plugins.app-config-ctrl-wrapper.enable">Enable</Trans>
</Button>
)}
{model.enabled && (
<Button variant="primary" onClick={this.update} className={withRightMargin}>
Update
<Trans i18nKey="plugins.app-config-ctrl-wrapper.update">Update</Trans>
</Button>
)}
{model.enabled && (
<Button variant="destructive" onClick={this.disable} className={withRightMargin}>
Disable
<Trans i18nKey="plugins.app-config-ctrl-wrapper.disable">Disable</Trans>
</Button>
)}
</div>

@ -6,6 +6,7 @@ export function PluginAngularBadge(): React.ReactElement {
return (
<Badge
icon="exclamation-triangle"
// eslint-disable-next-line @grafana/no-untranslated-strings
text="Angular"
color="orange"
tooltip="This plugin uses deprecated functionality, support for which is being removed."

@ -1,14 +1,18 @@
import * as React from 'react';
import { Badge } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export function PluginDeprecatedBadge(): React.ReactElement {
return (
<Badge
icon="exclamation-triangle"
text="Deprecated"
text={t('plugins.plugin-deprecated-badge.text-deprecated', 'Deprecated')}
color="orange"
tooltip="This plugin is deprecated and no longer receives updates."
tooltip={t(
'plugins.plugin-deprecated-badge.tooltip-plugin-deprecated-longer-receives-updates',
'This plugin is deprecated and no longer receives updates.'
)}
/>
);
}

@ -2,12 +2,20 @@ import * as React from 'react';
import { PluginErrorCode } from '@grafana/data';
import { Badge } from '@grafana/ui';
import { t } from 'app/core/internationalization';
type Props = { error?: PluginErrorCode };
export function PluginDisabledBadge({ error }: Props): React.ReactElement {
const tooltip = errorCodeToTooltip(error);
return <Badge icon="exclamation-triangle" text="Disabled" color="red" tooltip={tooltip} />;
return (
<Badge
icon="exclamation-triangle"
text={t('plugins.plugin-disabled-badge.text-disabled', 'Disabled')}
color="red"
tooltip={tooltip}
/>
);
}
function errorCodeToTooltip(error?: PluginErrorCode): string | undefined {

@ -2,6 +2,7 @@ import * as React from 'react';
import { featureEnabled } from '@grafana/runtime';
import { Badge, PluginSignatureBadge, Stack, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { CatalogPlugin } from '../../types';
@ -13,7 +14,7 @@ export function PluginEnterpriseBadge({ plugin }: Props): React.ReactElement {
const customBadgeStyles = useStyles2(getBadgeColor);
if (featureEnabled('enterprise.plugins')) {
return <Badge text="Enterprise" color="blue" />;
return <Badge text={t('plugins.plugin-enterprise-badge.text-enterprise', 'Enterprise')} color="blue" />;
}
return (
@ -22,11 +23,14 @@ export function PluginEnterpriseBadge({ plugin }: Props): React.ReactElement {
<Badge
icon="lock"
role="img"
aria-label="lock icon"
text="Enterprise"
aria-label={t('plugins.plugin-enterprise-badge.aria-label-enterprise', 'Enterprise')}
text={t('plugins.plugin-enterprise-badge.text-enterprise', 'Enterprise')}
color="blue"
className={customBadgeStyles}
title="Requires a Grafana Enterprise license"
title={t(
'plugins.plugin-enterprise-badge.title-requires-a-grafana-enterprise-license',
'Requires a Grafana Enterprise license'
)}
/>
</Stack>
);

@ -1,10 +1,17 @@
import * as React from 'react';
import { Badge, useStyles2 } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { getBadgeColor } from './sharedStyles';
export function PluginInstalledBadge(): React.ReactElement {
const customBadgeStyles = useStyles2(getBadgeColor);
return <Badge text="Installed" color="orange" className={customBadgeStyles} />;
return (
<Badge
text={t('plugins.plugin-installed-badge.text-installed', 'Installed')}
color="orange"
className={customBadgeStyles}
/>
);
}

@ -3,6 +3,7 @@ import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { CatalogPlugin } from '../../types';
@ -12,7 +13,11 @@ type Props = {
export function PluginUpdateAvailableBadge({ plugin }: Props): React.ReactElement | null {
const styles = useStyles2(getStyles);
return <p className={styles.hasUpdate}>Update available!</p>;
return (
<p className={styles.hasUpdate}>
<Trans i18nKey="plugins.plugin-update-available-badge.update-available">Update available!</Trans>
</p>
);
}
export const getStyles = (theme: GrafanaTheme2) => {

@ -4,6 +4,7 @@ import { PluginMeta } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { Button } from '@grafana/ui';
import { contextSrv } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import { AccessControlAction } from 'app/types';
import { updatePluginSettings } from '../../api';
@ -59,13 +60,13 @@ export function GetStartedWithApp({ plugin }: Props): React.ReactElement | null
<>
{!enabled && (
<Button variant="primary" onClick={enable}>
Enable
<Trans i18nKey="plugins.get-started-with-app.enable">Enable</Trans>
</Button>
)}
{enabled && !autoEnabled && (
<Button variant="destructive" onClick={disable}>
Disable
<Trans i18nKey="plugins.get-started-with-app.disable">Disable</Trans>
</Button>
)}
</>

@ -4,6 +4,7 @@ import * as React from 'react';
import { DataSourcePluginMeta } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Button } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { ROUTES } from 'app/features/connections/constants';
import { addDataSource } from 'app/features/datasources/state';
import { useDispatch } from 'app/types';
@ -41,7 +42,7 @@ export function GetStartedWithDataSource({ plugin }: Props): React.ReactElement
disabledButton ? "The plugin isn't usable yet, it may take some time to complete the installation." : undefined
}
>
Add new data source
<Trans i18nKey="plugins.get-started-with-data-source.add-new-data-source">Add new data source</Trans>
</Button>
);
}

@ -4,6 +4,7 @@ import { GrafanaTheme2, PluginType } from '@grafana/data';
import { config, featureEnabled } from '@grafana/runtime';
import { HorizontalGroup, LinkButton, useStyles2, Alert } from '@grafana/ui';
import { contextSrv } from 'app/core/core';
import { t, Trans } from 'app/core/internationalization';
import { AccessControlAction } from 'app/types';
import { getExternalManageLink } from '../../helpers';
@ -27,7 +28,10 @@ export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleV
return (
<Alert
severity="warning"
title="Renderer plugins cannot be managed by the Plugin Catalog."
title={t(
'plugins.install-controls-warning.title-renderer-plugins-cannot-managed-plugin-catalog',
'Renderer plugins cannot be managed by the Plugin Catalog.'
)}
className={styles.alert}
/>
);
@ -37,7 +41,11 @@ export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleV
return (
<Alert severity="warning" title="" className={styles.alert}>
<HorizontalGroup height="auto" align="center">
<span>No valid Grafana Enterprise license detected.</span>
<span>
<Trans i18nKey="plugins.install-controls-warning.no-valid-grafana-enterprise-license-detected">
No valid Grafana Enterprise license detected.
</Trans>
</span>
<LinkButton
href={`${getExternalManageLink(plugin.id)}?utm_source=grafana_catalog_learn_more`}
target="_blank"
@ -46,7 +54,7 @@ export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleV
fill="text"
icon="external-link-alt"
>
Learn more
<Trans i18nKey="plugins.install-controls-warning.learn-more">Learn more</Trans>
</LinkButton>
</HorizontalGroup>
</Alert>
@ -85,7 +93,10 @@ export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleV
return (
<Alert
severity="warning"
title="This plugin doesn&#39;t support your version of Grafana."
title={t(
'plugins.install-controls-warning.title-plugin-doesnt-support-version-grafana',
"This plugin doesn't support your version of Grafana."
)}
className={styles.alert}
/>
);

@ -3,6 +3,7 @@ import { useState } from 'react';
import { GrafanaTheme2, PluginErrorCode } from '@grafana/data';
import { Icon, Stack, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { GetStartedWithPlugin } from '../components/GetStartedWithPlugin';
import { InstallControlsButton } from '../components/InstallControls';
@ -51,7 +52,9 @@ export const PluginActions = ({ plugin }: Props) => {
{needReload && (
<Stack alignItems="center">
<Icon name="exclamation-triangle" />
<span className={styles.message}>Refresh the page to see the changes</span>
<span className={styles.message}>
<Trans i18nKey="plugins.plugin-actions.refresh-changes">Refresh the page to see the changes</Trans>
</span>
</Stack>
)}
</Stack>

@ -4,6 +4,7 @@ import { PureComponent } from 'react';
import { AppEvents, PluginMeta, DataSourceApi } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { appEvents } from 'app/core/core';
import { Trans } from 'app/core/internationalization';
import DashboardsTable from 'app/features/datasources/components/DashboardsTable';
import { PluginDashboard } from 'app/types';
@ -96,10 +97,20 @@ export class PluginDashboards extends PureComponent<Props, State> {
render() {
const { loading, dashboards } = this.state;
if (loading) {
return <div>loading...</div>;
return (
<div>
<Trans i18nKey="plugins.plugin-dashboards.loading">Loading...</Trans>
</div>
);
}
if (!dashboards || !dashboards.length) {
return <div>No dashboards are included with this plugin</div>;
return (
<div>
<Trans i18nKey="plugins.plugin-dashboards.dashboards-included-plugin">
No dashboards are included with this plugin
</Trans>
</div>
);
}
return <DashboardsTable dashboards={dashboards} onImport={this.import} onRemove={this.remove} />;

@ -5,6 +5,7 @@ import { AppPlugin, GrafanaTheme2, PluginContextProvider, UrlQueryMap, PluginTyp
import { config } from '@grafana/runtime';
import { PageInfoItem } from '@grafana/runtime/internal';
import { CellProps, Column, InteractiveTable, Stack, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Changelog } from '../components/Changelog';
import { PluginDetailsPanel } from '../components/PluginDetailsPanel';
@ -160,7 +161,9 @@ export function PluginDetailsBody({ plugin, queryParams, pageId, info, showDetai
return (
<div>
<p>Page not found.</p>
<p>
<Trans i18nKey="plugins.plugin-details-body.page-not-found">Page not found.</Trans>
</p>
</div>
);
}

@ -3,6 +3,7 @@ import * as React from 'react';
import { renderMarkdown } from '@grafana/data';
import { Alert } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { CatalogPlugin } from '../types';
@ -17,7 +18,12 @@ export function PluginDetailsDeprecatedWarning(props: Props): React.ReactElement
const isWarningVisible = plugin.isDeprecated && !dismissed;
return isWarningVisible ? (
<Alert severity="warning" title="Deprecated" className={className} onRemove={() => setDismissed(true)}>
<Alert
severity="warning"
title={t('plugins.plugin-details-deprecated-warning.title-deprecated', 'Deprecated')}
className={className}
onRemove={() => setDismissed(true)}
>
<p>
This {plugin.type} plugin is{' '}
<a

@ -7,6 +7,7 @@ import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Alert, Box, Stack, TabContent, useStyles2 } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { t } from 'app/core/internationalization';
import { AppNotificationSeverity } from 'app/types';
import { AngularDeprecationPluginNotice } from '../../angularDeprecation/AngularDeprecationPluginNotice';
@ -138,7 +139,10 @@ function NotFoundPlugin() {
return (
<Stack justifyContent="center" alignItems="center" height="100%">
<Box>
<Alert severity={AppNotificationSeverity.Warning} title="Plugin not found">
<Alert
severity={AppNotificationSeverity.Warning}
title={t('plugins.not-found-plugin.title-plugin-not-found', 'Plugin not found')}
>
That plugin cannot be found. Please check the url is correct or <br />
go to the <a href="/plugins">plugin catalog</a>.
</Alert>

@ -229,6 +229,7 @@ export function PluginDetailsPanel(props: Props): React.ReactElement | null {
This feature is for reporting malicious or harmful behaviour within plugins. For plugin concerns, email
us at:{' '}
</Trans>
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
<TextLink href="mailto:integrations+report-plugin@grafana.com">integrations@grafana.com</TextLink>
</Text>
<Text>

@ -3,6 +3,7 @@ import * as React from 'react';
import { PluginErrorCode, PluginSignatureStatus } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Alert } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { CatalogPlugin } from '../types';
@ -25,7 +26,7 @@ export function PluginDetailsSignature({ className, plugin }: Props): React.Reac
return (
<Alert
severity="warning"
title="Invalid plugin signature"
title={t('plugins.plugin-details-signature.title-invalid-plugin-signature', 'Invalid plugin signature')}
data-testid={selectors.pages.PluginPage.signatureInfo}
className={className}
>
@ -41,7 +42,9 @@ export function PluginDetailsSignature({ className, plugin }: Props): React.Reac
target="_blank"
rel="noreferrer"
>
Read more about plugins signing.
<Trans i18nKey="plugins.plugin-details-signature.read-more-about-plugins-signing">
Read more about plugins signing.
</Trans>
</a>
</Alert>
);

@ -65,7 +65,7 @@ describe('PluginListItemBadges', () => {
config.licenseInfo.enabledFeatures = {};
render(<PluginListItemBadges plugin={{ ...plugin, isEnterprise: true }} />);
expect(screen.getByText(/enterprise/i)).toBeVisible();
expect(screen.getByLabelText(/lock icon/i)).toBeInTheDocument();
expect(screen.getByLabelText(/enterprise/i)).toBeInTheDocument();
});
it('renders a error badge (when plugin has an error)', () => {

@ -4,6 +4,7 @@ import * as React from 'react';
import { GrafanaTheme2, PluginSignatureType } from '@grafana/data';
import { useStyles2, Icon, Badge, IconName } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
const SIGNATURE_ICONS: Record<string, IconName> = {
[PluginSignatureType.grafana]: 'grafana',
@ -40,7 +41,11 @@ export function PluginSignatureDetailsBadge({ signatureType, signatureOrg = '' }
</DetailsBadge>
<DetailsBadge>
<strong className={styles.strong}>Signed by:</strong> {signatureOrg}
<strong className={styles.strong}>
<Trans i18nKey="plugins.plugin-signature-details-badge.signed-by" values={{ signatureOrg }}>
Signed by: {{ signatureOrg }}
</Trans>
</strong>
</DetailsBadge>
</>
);

@ -8,6 +8,7 @@ import { GrafanaTheme2, PluginMeta, PluginType } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Alert, Spinner, useStyles2 } from '@grafana/ui';
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
import { t } from 'app/core/internationalization';
import { SearchResultsTable } from 'app/features/search/page/components/SearchResultsTable';
import { getGrafanaSearcher } from 'app/features/search/service/searcher';
import { SearchQuery } from 'app/features/search/service/types';
@ -69,7 +70,14 @@ export function PluginUsage({ plugin }: Props) {
if (!config.featureToggles.panelTitleSearch) {
return (
<Alert title="Missing feature toggle: panelTitleSearch">
<Alert
title={t(
'plugins.plugin-usage.title-missing-feature-toggle-panel-title-search',
'Missing feature toggle: {{toggle}}',
{ toggle: 'panelTitleSearch' }
)}
severity="warning"
>
Plugin usage requires the new search index to find usage across dashboards
</Alert>
);

@ -3,6 +3,7 @@ import * as React from 'react';
import { useDebounce } from 'react-use';
import { FilterInput } from '@grafana/ui';
import { t } from 'app/core/internationalization';
interface Props {
value?: string;
@ -41,7 +42,7 @@ export const SearchField = ({ value, onSearch }: Props) => {
onSearch(e.currentTarget.value);
}
}}
placeholder="Search Grafana plugins"
placeholder={t('plugins.search-field.placeholder-search-grafana-plugins', 'Search Grafana plugins')}
onChange={(value) => {
setQuery(value);
}}

@ -47,7 +47,14 @@ export const VersionInstallButton = ({
}, [installedVersion, version.version]);
if (version.version === installedVersion) {
return <Badge className={styles.badge} text="Installed" icon="check" color="green" />;
return (
<Badge
className={styles.badge}
text={t('plugins.version-install-button.text-installed', 'Installed')}
icon="check"
color="green"
/>
);
}
const performInstallation = () => {

@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
import { dateTimeFormatTimeAgo, GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { getLatestCompatibleVersion } from '../helpers';
import { Version } from '../types';
@ -28,7 +29,11 @@ export const VersionList = ({ pluginId, versions = [], installedVersion, disable
}, [installedVersion]);
if (versions.length === 0) {
return <p>No version history was found.</p>;
return (
<p>
<Trans i18nKey="plugins.version-list.no-version-history-was-found">No version history was found.</Trans>
</p>
);
}
const onInstallClick = () => {
@ -39,10 +44,16 @@ export const VersionList = ({ pluginId, versions = [], installedVersion, disable
<table className={styles.table}>
<thead>
<tr>
<th>Version</th>
<th>
<Trans i18nKey="plugins.version-list.version">Version</Trans>
</th>
<th></th>
<th>Last updated</th>
<th>Grafana Dependency</th>
<th>
<Trans i18nKey="plugins.version-list.last-updated">Last updated</Trans>
</th>
<th>
<Trans i18nKey="plugins.version-list.grafana-dependency">Grafana dependency</Trans>
</th>
</tr>
</thead>
<tbody>

@ -6,6 +6,7 @@ import { SelectableValue, GrafanaTheme2, PluginType } from '@grafana/data';
import { locationSearchToObject } from '@grafana/runtime';
import { Select, RadioButtonGroup, useStyles2, Tooltip, Field } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { t } from 'app/core/internationalization';
import { getNavModel } from 'app/core/selectors/navModel';
import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants';
import { useSelector } from 'app/types';
@ -95,14 +96,14 @@ export default function Browse() {
<Page navModel={navModel} actions={updateAllButton} subTitle={subTitle}>
<Page.Contents>
<HorizontalGroup wrap>
<Field label="Search">
<Field label={t('plugins.browse.label-search', 'Search')}>
<SearchField value={keyword} onSearch={onSearch} />
</Field>
<HorizontalGroup wrap className={styles.actionBar}>
{/* Filter by type */}
<Field label="Type">
<Field label={t('plugins.browse.label-type', 'Type')}>
<Select
aria-label="Plugin type filter"
aria-label={t('plugins.browse.aria-label-plugin-type-filter', 'Plugin type filter')}
value={filterByType}
onChange={onFilterByTypeChange}
width={18}
@ -117,7 +118,7 @@ export default function Browse() {
{/* Filter by installed / all */}
{remotePluginsAvailable ? (
<Field label="State">
<Field label={t('plugins.browse.label-state', 'State')}>
<RadioButtonGroup value={filterBy} onChange={onFilterByChange} options={filterByOptions} />
</Field>
) : (
@ -126,7 +127,7 @@ export default function Browse() {
placement="top"
>
<div>
<Field label="State">
<Field label={t('plugins.browse.label-state', 'State')}>
<RadioButtonGroup
disabled={true}
value={filterBy}

@ -1,6 +1,7 @@
import { reportInteraction } from '@grafana/runtime';
import { Alert, Button } from '@grafana/ui';
import { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';
import { Trans } from 'app/core/internationalization';
const LOCAL_STORAGE_KEY_PREFIX = 'grafana.angularDeprecation.dashboardNoticeAndMigration.isDismissed';
@ -46,13 +47,15 @@ export function AngularDeprecationNotice({ dashboardUid, showAutoMigrateLink }:
target="_blank"
rel="noreferrer"
>
Read our deprecation notice and migration advice.
<Trans i18nKey="plugins.angular-deprecation-notice.deprecation-notice-migration-advice">
Read our deprecation notice and migration advice.
</Trans>
</a>
<br />
{showAutoMigrateLink && (
<Button fill="outline" size="sm" onClick={tryMigration} style={{ marginTop: 10 }}>
Try migration
<Trans i18nKey="plugins.angular-deprecation-notice.try-migration">Try migration</Trans>
</Button>
)}
</div>

@ -4,6 +4,7 @@ import * as React from 'react';
import { PluginType } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { Alert } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
type Props = {
className?: string;
@ -63,7 +64,12 @@ export function AngularDeprecationPluginNotice(props: Props): React.ReactElement
}
return dismissed ? null : (
<Alert severity="warning" title="Angular plugin" className={className} onRemove={() => setDismissed(true)}>
<Alert
severity="warning"
title={t('plugins.angular-deprecation-plugin-notice.title-angular-plugin', 'Angular plugin')}
className={className}
onRemove={() => setDismissed(true)}
>
<p>{deprecationMessage(pluginType, angularSupportEnabled)}</p>
<div className="markdown-html">
<ul>
@ -77,7 +83,9 @@ export function AngularDeprecationPluginNotice(props: Props): React.ReactElement
reportInteraction('angular_deprecation_docs_clicked', interactionAttributes);
}}
>
Read our deprecation notice and migration advice.
<Trans i18nKey="plugins.angular-deprecation-plugin-notice.deprecation-notice-migration-advice">
Read our deprecation notice and migration advice.
</Trans>
</a>
</li>
{showPluginDetailsLink && pluginId ? (
@ -88,7 +96,9 @@ export function AngularDeprecationPluginNotice(props: Props): React.ReactElement
target="_blank"
rel="noreferrer"
>
View plugin details
<Trans i18nKey="plugins.angular-deprecation-plugin-notice.view-plugin-details">
View plugin details
</Trans>
</a>
</li>
) : null}

@ -3,6 +3,7 @@ import { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, Button, useStyles2 } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { migrationFeatureFlags } from './utils';
@ -46,10 +47,10 @@ export function AngularMigrationNotice({ dashboardUid }: Props) {
>
<div className="markdown-html">
<Button fill="outline" size="sm" className={styles.linkButton} onClick={reportIssue}>
Report issue
<Trans i18nKey="plugins.angular-migration-notice.report-issue">Report issue</Trans>
</Button>
<Button fill="outline" size="sm" className={styles.linkButton} onClick={revertAutoMigrateUrlFlag}>
Revert migration
<Trans i18nKey="plugins.angular-migration-notice.revert-migration">Revert migration</Trans>
</Button>
</div>
</Alert>

@ -21,6 +21,7 @@ import PageLoader from 'app/core/components/PageLoader/PageLoader';
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
import { useGrafana } from 'app/core/context/GrafanaContext';
import { appEvents, contextSrv } from 'app/core/core';
import { Trans, t } from 'app/core/internationalization';
import { getNotFoundNav, getWarningNav, getExceptionNav } from 'app/core/navigation/errorModels';
import { getMessageFromError } from 'app/core/utils/errors';
@ -94,7 +95,11 @@ export function AppRootPage({ pluginId, pluginNavSection }: Props) {
if (!plugin.root) {
return (
<Page navModel={navModel ?? getWarningNav('Plugin load error')}>
<div>No root app page component found</div>
<div>
<Trans i18nKey="plugins.app-root-page.no-root-app-page-component-found">
No root app page component found
</Trans>
</div>
</Page>
);
}
@ -153,8 +158,10 @@ export function AppRootPage({ pluginId, pluginNavSection }: Props) {
const AccessDenied = () => {
return (
<Alert severity="warning" title="Access denied">
You do not have permission to see this page.
<Alert severity="warning" title={t('plugins.app-root-page.access-denied.title-access-denied', 'Access denied')}>
<Trans i18nKey="plugins.app-root-page.access-denied.permission">
You do not have permission to see this page.
</Trans>
</Alert>
);
};

@ -4,6 +4,7 @@ import { ReactElement, useMemo } from 'react';
import { DataFrame, MatcherConfig, SelectableValue } from '@grafana/data';
import { SceneDataProvider } from '@grafana/scenes';
import { InlineField, InlineFieldRow, MultiSelect } from '@grafana/ui';
import { t } from 'app/core/internationalization';
export type LogFilter = {
pluginIds?: Set<string>;
@ -63,13 +64,13 @@ export function LogViewFilters({ provider, filteredProvider, filter, onChange }:
return (
<InlineFieldRow>
<InlineField label="Plugin Id">
<InlineField label={t('plugins.log-view-filters.label-plugin-id', 'Plugin Id')}>
<MultiSelect options={pluginIds} onChange={onChangePluginIds} />
</InlineField>
<InlineField label="Extension">
<InlineField label={t('plugins.log-view-filters.label-extension', 'Extension')}>
<MultiSelect options={extensionPointIds} onChange={onChangeExtensionPointIds} />
</InlineField>
<InlineField label="Severity">
<InlineField label={t('plugins.log-view-filters.label-severity', 'Severity')}>
<MultiSelect options={severity} onChange={onChangeSeverity} />
</InlineField>
</InlineFieldRow>

@ -2,7 +2,7 @@ import { PureComponent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Button, LoadingPlaceholder, ScrollContainer } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { Trans, t } from 'app/core/internationalization';
import { UserDTO, UserOrg } from 'app/types';
export interface Props {
@ -17,7 +17,11 @@ export class UserOrganizations extends PureComponent<Props> {
const { isLoading, orgs, user } = this.props;
if (isLoading) {
return <LoadingPlaceholder text="Loading organizations..." />;
return (
<LoadingPlaceholder
text={t('profile.user-organizations.text-loading-organizations', 'Loading organizations...')}
/>
);
}
if (orgs.length === 0) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save