diff --git a/core/lib/Drupal/Core/ImageToolkit/Attribute/ImageToolkitOperation.php b/core/lib/Drupal/Core/ImageToolkit/Attribute/ImageToolkitOperation.php
new file mode 100644
index 0000000000000000000000000000000000000000..705a64ca0e1630d8dbb35e15aa0917ece3ce1eed
--- /dev/null
+++ b/core/lib/Drupal/Core/ImageToolkit/Attribute/ImageToolkitOperation.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\ImageToolkit\Attribute;
+
+use Drupal\Component\Plugin\Attribute\Plugin;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines a Plugin attribute for the image toolkit plugin.
+ *
+ * An image toolkit operation plugin provides a self-contained image
+ * manipulation routine, for a specific image toolkit. Examples of image
+ * toolkit operations are scaling, cropping, rotating, etc.
+ *
+ * Plugin namespace: Plugin\ImageToolkit\Operation
+ *
+ * For a working example, see
+ * \Drupal\system\Plugin\ImageToolkit\Operation\gd\Crop
+ *
+ * @see \Drupal\Core\ImageToolkit\Annotation\ImageToolkit
+ * @see \Drupal\image\Annotation\ImageEffect
+ * @see \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface
+ * @see \Drupal\Core\ImageToolkit\ImageToolkitOperationBase
+ * @see \Drupal\Core\ImageToolkit\ImageToolkitOperationManager
+ * @see plugin_api
+ *
+ * @Annotation
+ */
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class ImageToolkitOperation extends Plugin {
+
+  /**
+   * Constructs a new ImageToolkitOperation instance.
+   *
+   * @param string $id
+   *   The plugin ID.
+   *   There are no strict requirements as to the string to be used to identify
+   *   the plugin, since discovery of the appropriate operation plugin to be
+   *   used to apply an operation is based on the values of the 'toolkit' and
+   *   the 'operation' annotation values.
+   *   However, it is recommended that the following patterns be used:
+   *    - '{toolkit}_{operation}' for the first implementation of an operation
+   *      by a toolkit.
+   *    - '{module}_{toolkit}_{operation}' for overrides of existing
+   *      implementations supplied by an alternative module, and for new
+   *      module-supplied operations.
+   * @param string $toolkit
+   *   The id of the image toolkit plugin for which the operation is
+   *   implemented.
+   * @param string $operation
+   *   The machine name of the image toolkit operation implemented
+   *   (e.g. "crop").
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $label
+   *   The human-readable name of the image toolkit operation.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description
+   *   (optional) The description of the image toolkit operation.
+   * @param string|null $deriver
+   *   (optional) The deriver class for the image toolkit operation.
+   */
+  public function __construct(
+    public readonly string $id,
+    public readonly string $toolkit,
+    public readonly string $operation,
+    public readonly TranslatableMarkup $label,
+    public readonly ?TranslatableMarkup $description = NULL,
+    public readonly ?string $deriver = NULL,
+  ) {}
+
+}
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
index 3eeb7867e4ceaee3cca39a895bc20f2010fcc1e2..4c1536eac7fff6ca92e563690e204b40dbf84c49 100644
--- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManager.php
@@ -2,12 +2,13 @@
 
 namespace Drupal\Core\ImageToolkit;
 
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\Plugin\DefaultPluginManager;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -50,7 +51,14 @@ class ImageToolkitOperationManager extends DefaultPluginManager implements Image
    *   The image toolkit manager.
    */
   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger, ImageToolkitManager $toolkit_manager) {
-    parent::__construct('Plugin/ImageToolkit/Operation', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\ImageToolkitOperationInterface', 'Drupal\Core\ImageToolkit\Annotation\ImageToolkitOperation');
+    parent::__construct(
+      'Plugin/ImageToolkit/Operation',
+      $namespaces,
+      $module_handler,
+      ImageToolkitOperationInterface::class,
+      ImageToolkitOperation::class,
+      'Drupal\Core\ImageToolkit\Annotation\ImageToolkitOperation',
+    );
 
     $this->alterInfo('image_toolkit_operation');
     $this->setCacheBackend($cache_backend, 'image_toolkit_operation_plugins');
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Convert.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Convert.php
index a7d00573927ca36795fab3c1b4853936d75048cb..81648a4cdc3189c2fd1cd56c8637eefd26307e81 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Convert.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Convert.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 convert operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_convert",
- *   toolkit = "gd",
- *   operation = "convert",
- *   label = @Translation("Convert"),
- *   description = @Translation("Instructs the toolkit to save the image with a specified extension.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_convert",
+  toolkit: "gd",
+  operation: "convert",
+  label: new TranslatableMarkup("Convert"),
+  description: new TranslatableMarkup("Instructs the toolkit to save the image with a specified extension.")
+)]
 class Convert extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
index 282380ffb1ce05463d4b768b90ee4113311f5bba..7b15796dbce4ba403676ea0d81d02669659556c0 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/CreateNew.php
@@ -3,18 +3,19 @@
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
 use Drupal\Component\Utility\Color;
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 /**
  * Defines GD2 create_new image operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_create_new",
- *   toolkit = "gd",
- *   operation = "create_new",
- *   label = @Translation("Set a new image"),
- *   description = @Translation("Creates a new transparent object and sets it for the image.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_create_new",
+  toolkit: "gd",
+  operation: "create_new",
+  label: new TranslatableMarkup("Set a new image"),
+  description: new TranslatableMarkup("Creates a new transparent object and sets it for the image.")
+)]
 class CreateNew extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Crop.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Crop.php
index 315cda2e2bca67341e210cbd5cfe774b51ab9fa6..e1105e9e31e8f829fd58e4f0de16b9bde71cffeb 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Crop.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Crop.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 Crop operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_crop",
- *   toolkit = "gd",
- *   operation = "crop",
- *   label = @Translation("Crop"),
- *   description = @Translation("Crops an image to a rectangle specified by the given dimensions.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_crop",
+  toolkit: "gd",
+  operation: "crop",
+  label: new TranslatableMarkup("Crop"),
+  description: new TranslatableMarkup("Crops an image to a rectangle specified by the given dimensions.")
+)]
 class Crop extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Desaturate.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Desaturate.php
index 076f21a6f2fac71d25340fe359e46942383a2992..466864aa873207ef23a83a68d472679987a1f2ad 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Desaturate.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Desaturate.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 Desaturate operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_desaturate",
- *   toolkit = "gd",
- *   operation = "desaturate",
- *   label = @Translation("Desaturate"),
- *   description = @Translation("Converts an image to grayscale.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_desaturate",
+  toolkit: "gd",
+  operation: "desaturate",
+  label: new TranslatableMarkup("Desaturate"),
+  description: new TranslatableMarkup("Converts an image to grayscale.")
+)]
 class Desaturate extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Resize.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Resize.php
index 317bc14bda26d5e9a36ea019881a3b265964a144..e76104ffa3515a7e835833036cb4fc3177b865cc 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Resize.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Resize.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 resize operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_resize",
- *   toolkit = "gd",
- *   operation = "resize",
- *   label = @Translation("Resize"),
- *   description = @Translation("Resizes an image to the given dimensions (ignoring aspect ratio).")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_resize",
+  toolkit: "gd",
+  operation: "resize",
+  label: new TranslatableMarkup("Resize"),
+  description: new TranslatableMarkup("Resizes an image to the given dimensions (ignoring aspect ratio).")
+)]
 class Resize extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
index db20c726cf790ae411a9297794fb76f3e565d25c..19f393ce4ae2348a2e7b7cea45864e3a3627ee48 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Rotate.php
@@ -3,18 +3,19 @@
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
 use Drupal\Component\Utility\Color;
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 /**
  * Defines GD2 rotate operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_rotate",
- *   toolkit = "gd",
- *   operation = "rotate",
- *   label = @Translation("Rotate"),
- *   description = @Translation("Rotates an image by the given number of degrees.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_rotate",
+  toolkit: "gd",
+  operation: "rotate",
+  label: new TranslatableMarkup("Rotate"),
+  description: new TranslatableMarkup("Rotates an image by the given number of degrees.")
+)]
 class Rotate extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Scale.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Scale.php
index 37097d864ee93fe2f7acd6e33de5379436fd601b..85cc7442b0270043bd4f850a67d8ca4903881c22 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Scale.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/Scale.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 Scale operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_scale",
- *   toolkit = "gd",
- *   operation = "scale",
- *   label = @Translation("Scale"),
- *   description = @Translation("Scales an image while maintaining aspect ratio. The resulting image can be smaller for one or both target dimensions.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_scale",
+  toolkit: "gd",
+  operation: "scale",
+  label: new TranslatableMarkup("Scale"),
+  description: new TranslatableMarkup("Scales an image while maintaining aspect ratio. The resulting image can be smaller for one or both target dimensions.")
+)]
 class Scale extends Resize {
 
   /**
diff --git a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php
index ad53ec3fa156ce3944cd0032c886f706e8a4ad11..d502b213673126f1680ff4061e0b400c7ec7165c 100644
--- a/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php
+++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\system\Plugin\ImageToolkit\Operation\gd;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Defines GD2 Scale and crop operation.
- *
- * @ImageToolkitOperation(
- *   id = "gd_scale_and_crop",
- *   toolkit = "gd",
- *   operation = "scale_and_crop",
- *   label = @Translation("Scale and crop"),
- *   description = @Translation("Scales an image to the exact width and height given. This plugin achieves the target aspect ratio by cropping the original image equally on both sides, or equally on the top and bottom. This function is useful to create uniform sized avatars from larger images.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "gd_scale_and_crop",
+  toolkit: "gd",
+  operation: "scale_and_crop",
+  label: new TranslatableMarkup("Scale and crop"),
+  description: new TranslatableMarkup("Scales an image to the exact width and height given. This plugin achieves the target aspect ratio by cropping the original image equally on both sides, or equally on the top and bottom. This function is useful to create uniform sized avatars from larger images.")
+)]
 class ScaleAndCrop extends GDImageToolkitOperationBase {
 
   /**
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Bar.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Bar.php
index ecd4aaafdefc18d7f46266ba57fd8cd424894aea..960c8886208453b77e2ece2b2432d4641188d62b 100644
--- a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Bar.php
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Bar.php
@@ -2,15 +2,17 @@
 
 namespace Drupal\image_test\Plugin\ImageToolkit\Operation\test;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Builds an image toolkit operation.
- *
- * @ImageToolkitOperation(
- *   id = "bar",
- *   toolkit = "test",
- *   operation = "invert",
- *   label = @Translation("Invert"),
- *   description = @Translation("Bar.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "bar",
+  toolkit: "test",
+  operation: "invert",
+  label: new TranslatableMarkup("Invert"),
+  description: new TranslatableMarkup("Bar.")
+)]
 class Bar extends OperationBase {}
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Failing.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Failing.php
index eb37d9f07d48ee4eb1762b8964f6c372ced04cc9..03b492f6140f4dde805f0a724297214baa163594 100644
--- a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Failing.php
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Failing.php
@@ -2,17 +2,19 @@
 
 namespace Drupal\image_test\Plugin\ImageToolkit\Operation\test;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * An image toolkit operation that throws a \RuntimeException.
- *
- * @ImageToolkitOperation(
- *   id = "failing",
- *   toolkit = "test",
- *   operation = "failing",
- *   label = @Translation("An image toolkit operation that throws a \\RuntimeException"),
- *   description = @Translation("An image toolkit operation that throws a \\RuntimeException.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "failing",
+  toolkit: "test",
+  operation: "failing",
+  label: new TranslatableMarkup("An image toolkit operation that throws a \\RuntimeException"),
+  description: new TranslatableMarkup("An image toolkit operation that throws a \\RuntimeException.")
+)]
 class Failing extends OperationBase {
 
   /**
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Foo.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Foo.php
index 3b067d5919c3469ed2b46670a1d3bc9a38c2b9cc..35671d03c95871a995b068f148e322ca3a1448b8 100644
--- a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Foo.php
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/Foo.php
@@ -2,15 +2,17 @@
 
 namespace Drupal\image_test\Plugin\ImageToolkit\Operation\test;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Builds an image toolkit operation.
- *
- * @ImageToolkitOperation(
- *   id = "foo",
- *   toolkit = "test",
- *   operation = "blur",
- *   label = @Translation("Blur"),
- *   description = @Translation("Foo.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "foo",
+  toolkit: "test",
+  operation: "blur",
+  label: new TranslatableMarkup("Blur"),
+  description: new TranslatableMarkup("Foo."),
+)]
 class Foo extends OperationBase {}
diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/FooDerived.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/FooDerived.php
index bf38dfddf54e57da5e2c6716736ef3095656d870..058c25b5de2dd152870151f3af0d0e817f51c6ce 100644
--- a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/FooDerived.php
+++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/Operation/test/FooDerived.php
@@ -2,15 +2,17 @@
 
 namespace Drupal\image_test\Plugin\ImageToolkit\Operation\test;
 
+use Drupal\Core\ImageToolkit\Attribute\ImageToolkitOperation;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
 /**
  * Builds an image toolkit operation.
- *
- * @ImageToolkitOperation(
- *   id = "foo_derived",
- *   toolkit = "test:derived_toolkit",
- *   operation = "blur",
- *   label = @Translation("Blur Derived"),
- *   description = @Translation("Foo derived.")
- * )
  */
+#[ImageToolkitOperation(
+  id: "foo_derived",
+  toolkit: "test:derived_toolkit",
+  operation: "blur",
+  label: new TranslatableMarkup("Blur Derived"),
+  description: new TranslatableMarkup("Foo derived.")
+)]
 class FooDerived extends OperationBase {}