diff --git a/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php b/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php
index 23920dba0629d77dd09eb2f3b09f1a81976d876d..9ed0a1bb51a772897f0d04fcbf7be9c3d7fd6466 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument_validator/TermName.php
@@ -5,17 +5,18 @@
 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\views\Attribute\ViewsArgumentValidator;
 use Drupal\views\Plugin\views\argument_validator\Entity;
 
 /**
  * Validates whether a term name is a valid term argument.
- *
- * @ViewsArgumentValidator(
- *   id = "taxonomy_term_name",
- *   title = @Translation("Taxonomy term name"),
- *   entity_type = "taxonomy_term"
- * )
  */
+#[ViewsArgumentValidator(
+  id: 'taxonomy_term_name',
+  title: new TranslatableMarkup('Taxonomy term name'),
+  entity_type: 'taxonomy_term'
+)]
 class TermName extends Entity {
 
   /**
diff --git a/core/modules/user/src/Plugin/views/argument_validator/UserName.php b/core/modules/user/src/Plugin/views/argument_validator/UserName.php
index 8b047fc035e272e5671f50d190b0bc8fd8764cda..0ab8dce2162c7b5c18595bac60d808359f7db8df 100644
--- a/core/modules/user/src/Plugin/views/argument_validator/UserName.php
+++ b/core/modules/user/src/Plugin/views/argument_validator/UserName.php
@@ -3,16 +3,17 @@
 namespace Drupal\user\Plugin\views\argument_validator;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\views\Attribute\ViewsArgumentValidator;
 
 /**
  * Validates whether a user name is valid.
- *
- * @ViewsArgumentValidator(
- *   id = "user_name",
- *   title = @Translation("User name"),
- *   entity_type = "user"
- * )
  */
+#[ViewsArgumentValidator(
+  id: 'user_name',
+  title: new TranslatableMarkup('User name'),
+  entity_type: 'user'
+)]
 class UserName extends User {
 
   /**
diff --git a/core/modules/views/src/Attribute/ViewsArgumentValidator.php b/core/modules/views/src/Attribute/ViewsArgumentValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c51983e9d331a444bbda2fcc9e816cb6a8ca840
--- /dev/null
+++ b/core/modules/views/src/Attribute/ViewsArgumentValidator.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\views\Attribute;
+
+use Drupal\Component\Plugin\Attribute\Plugin;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines a ViewsArgumentValidator attribute object for plugin discovery.
+ *
+ * Plugin Namespace: Plugin\ViewsArgumentValidator
+ *
+ * @see \Drupal\views\Plugin\views\argument_validator\ArgumentValidatorPluginBase
+ *
+ * @ingroup views_argument_validate_plugins
+ */
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class ViewsArgumentValidator extends Plugin {
+
+  /**
+   * Constructs a ViewsArgumentValidator attribute.
+   *
+   * @param string $id
+   *   The plugin ID.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $title
+   *   The plugin title used in the views UI.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $short_title
+   *   (optional) The short title used in the views UI.
+   * @param string $entity_type
+   *   (optional) Entity type.
+   * @param bool $no_ui
+   *   Whether the plugin is selectable in the UI.
+   * @param class-string|null $deriver
+   *   (optional) The deriver class.
+   */
+  public function __construct(
+    public readonly string $id,
+    public readonly ?TranslatableMarkup $title = NULL,
+    public readonly ?TranslatableMarkup $short_title = NULL,
+    public readonly ?string $entity_type = NULL,
+    public readonly bool $no_ui = FALSE,
+    public readonly ?string $deriver = NULL
+  ) {}
+
+}
diff --git a/core/modules/views/src/Plugin/views/argument_validator/Entity.php b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
index 1954a10c56c08848b4ea37ce6932f7ce102bc888..caea24cf510f567d202fc479a6098236fea5f17a 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/Entity.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
@@ -7,19 +7,18 @@
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\Context\EntityContextDefinition;
+use Drupal\views\Attribute\ViewsArgumentValidator;
+use Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator;
 use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines an argument validator plugin for each entity type.
- *
- * @ViewsArgumentValidator(
- *   id = "entity",
- *   deriver = "Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator"
- * )
- *
- * @see \Drupal\views\Plugin\Derivative\ViewsEntityArgumentValidator
  */
+#[ViewsArgumentValidator(
+  id: 'entity',
+  deriver: ViewsEntityArgumentValidator::class
+)]
 class Entity extends ArgumentValidatorPluginBase {
 
   /**
diff --git a/core/modules/views/src/Plugin/views/argument_validator/None.php b/core/modules/views/src/Plugin/views/argument_validator/None.php
index c74f5290d121e9816b6b276f2ff073f8684353d0..c22a8fd307ec588c35f6b471ee7f8111d015c3b1 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/None.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/None.php
@@ -2,16 +2,18 @@
 
 namespace Drupal\views\Plugin\views\argument_validator;
 
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\views\Attribute\ViewsArgumentValidator;
+
 /**
  * Do not validate the argument.
  *
  * @ingroup views_argument_validate_plugins
- *
- * @ViewsArgumentValidator(
- *   id = "none",
- *   title = @Translation(" - Basic validation - ")
- * )
  */
+#[ViewsArgumentValidator(
+  id: 'none',
+  title: new TranslatableMarkup('- Basic validation -')
+)]
 class None extends ArgumentValidatorPluginBase {
 
   public function validateArgument($argument) {
diff --git a/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php b/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php
index 7368e06286dd3ede0cb65022ebbe3c636e7d2e96..e973762ac6aa3b09d50785f790a8a0f0ef58e7c6 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/NumericArgumentValidator.php
@@ -3,17 +3,18 @@
 namespace Drupal\views\Plugin\views\argument_validator;
 
 use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\views\Attribute\ViewsArgumentValidator;
 
 /**
  * Validate whether an argument is numeric or not.
  *
  * @ingroup views_argument_validate_plugins
- *
- * @ViewsArgumentValidator(
- *   id = "numeric",
- *   title = @Translation("Numeric")
- * )
  */
+#[ViewsArgumentValidator(
+  id: 'numeric',
+  title: new TranslatableMarkup('Numeric')
+)]
 class NumericArgumentValidator extends ArgumentValidatorPluginBase {
 
   public function validateArgument($argument) {
diff --git a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php
index ebffc7af7dcacc58db99dc627da48f3ee5915406..3bded483cd5af2481c709fe59b397c9d0fd977cd 100644
--- a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php
+++ b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php
@@ -2,16 +2,17 @@
 
 namespace Drupal\views_test_data\Plugin\views\argument_validator;
 
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\views\Plugin\views\argument_validator\ArgumentValidatorPluginBase;
+use Drupal\views\Attribute\ViewsArgumentValidator;
 
 /**
  * Defines an argument validator test plugin.
- *
- * @ViewsArgumentValidator(
- *   id = "argument_validator_test",
- *   title = @Translation("Argument validator test")
- * )
  */
+#[ViewsArgumentValidator(
+  id: 'argument_validator_test',
+  title: new TranslatableMarkup('Argument validator test')
+)]
 class ArgumentValidatorTest extends ArgumentValidatorPluginBase {
 
   /**