diff --git a/core/lib/Drupal/Core/Config/Action/Attribute/ActionMethod.php b/core/lib/Drupal/Core/Config/Action/Attribute/ActionMethod.php
index f5f9b0de5ec9cc2f1f250720ce4f16e82a2672bc..56e388072fa9708f1cbcd00e1fd027bbc969bb4c 100644
--- a/core/lib/Drupal/Core/Config/Action/Attribute/ActionMethod.php
+++ b/core/lib/Drupal/Core/Config/Action/Attribute/ActionMethod.php
@@ -5,7 +5,9 @@
 namespace Drupal\Core\Config\Action\Attribute;
 
 // cspell:ignore inflector
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
 use Drupal\Core\Config\Action\Exists;
+use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 /**
@@ -30,12 +32,23 @@ final class ActionMethod {
    *   ID. For example, if the method is called 'addArray' this can be set to
    *   'addMultipleArrays'. Set to FALSE if a pluralized version does not make
    *   logical sense.
+   * @param string|null $name
+   *   The name of the action, if it should differ from the method name. Will be
+   *   pluralized if $pluralize is TRUE. Must follow the rules for a valid PHP
+   *   function name (e.g., no spaces, no Unicode characters, etc.). If used,
+   *   the actual name of the method will NOT be available as an action name.
+   *
+   * @see https://www.php.net/manual/en/functions.user-defined.php
    */
   public function __construct(
     public readonly Exists $exists = Exists::ErrorIfNotExists,
     public readonly TranslatableMarkup|string $adminLabel = '',
     public readonly bool|string $pluralize = TRUE,
+    public readonly ?string $name = NULL,
   ) {
+    if ($name && !preg_match(ExtensionDiscovery::PHP_FUNCTION_PATTERN, $name)) {
+      throw new InvalidPluginDefinitionException('entity_method', sprintf("'%s' is not a valid PHP function name.", $name));
+    }
   }
 
 }
diff --git a/core/lib/Drupal/Core/Config/Action/Plugin/ConfigAction/Deriver/EntityMethodDeriver.php b/core/lib/Drupal/Core/Config/Action/Plugin/ConfigAction/Deriver/EntityMethodDeriver.php
index 2577d8d7b923847be2d54a61abfd8fb4a16f8cf1..b1c5ccff3841e7da2cdc2f31357b49048e013976 100644
--- a/core/lib/Drupal/Core/Config/Action/Plugin/ConfigAction/Deriver/EntityMethodDeriver.php
+++ b/core/lib/Drupal/Core/Config/Action/Plugin/ConfigAction/Deriver/EntityMethodDeriver.php
@@ -102,15 +102,16 @@ private function processMethod(\ReflectionMethod $method, ActionMethod $action_a
       'pluralized' => FALSE,
     ];
     $derivative['entity_types'] = [$entity_type->id()];
+    $action_name = $action_attribute->name ?: $method->name;
     // Build a config action identifier from the entity type's config
     // prefix  and the method name. For example, the Role entity adds a
     // 'user.role:grantPermission' action.
-    $this->addDerivative($method->name, $entity_type, $derivative, $method->name);
+    $this->addDerivative($action_name, $entity_type, $derivative, $method->name);
 
     $pluralized_name = match(TRUE) {
       is_string($action_attribute->pluralize) => $action_attribute->pluralize,
       $action_attribute->pluralize === FALSE => '',
-      default => $this->inflector->pluralize($method->name)[0]
+      default => $this->inflector->pluralize($action_name)[0]
     };
     // Add a pluralized version of the plugin.
     if (strlen($pluralized_name) > 0) {
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index 22e56ac3bc6462cd70d03677e7f3795959c1f81b..41fb1d630b14e31a7bd5bd62c3d2673786363378 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -160,6 +160,7 @@ public function get($property_name) {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set a value'), pluralize: 'setMultiple')]
   public function set($property_name, $value) {
     if ($this instanceof EntityWithPluginCollectionInterface && !$this->isSyncing()) {
       $plugin_collections = $this->getPluginCollections();
@@ -177,6 +178,7 @@ public function set($property_name, $value) {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Enable'), pluralize: FALSE)]
   public function enable() {
     return $this->setStatus(TRUE);
   }
@@ -184,6 +186,7 @@ public function enable() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Disable'), pluralize: FALSE)]
   public function disable() {
     return $this->setStatus(FALSE);
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
index 4951ef32d72d8121910cf698823fbf2889be1101..c1b80ac8487b5f7bca85746e30250cfd02e153a7 100644
--- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
@@ -373,6 +373,7 @@ public function setComponent($name, array $options = []) {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Hide component'), name: 'hideComponent')]
   public function removeComponent($name) {
     $this->hidden[$name] = TRUE;
     unset($this->content[$name]);
diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php
index 988f510729483dc7927b18573c8c02e24055c251..56cd5b497a02a798ad199aca8f6da8fa1469edd3 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigBase.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php
@@ -329,7 +329,7 @@ public function getLabel() {
   /**
    * {@inheritdoc}
    */
-  #[ActionMethod(adminLabel: new TranslatableMarkup('Change field label'))]
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set field label'), pluralize: FALSE)]
   public function setLabel($label) {
     $this->label = $label;
     return $this;
@@ -345,6 +345,7 @@ public function getDescription() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set field description'), pluralize: FALSE)]
   public function setDescription($description) {
     $this->description = $description;
     return $this;
@@ -361,6 +362,7 @@ public function isTranslatable() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set whether field is translatable'), pluralize: FALSE)]
   public function setTranslatable($translatable) {
     $this->translatable = $translatable;
     return $this;
@@ -376,6 +378,7 @@ public function getSettings() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set field settings'), pluralize: FALSE)]
   public function setSettings(array $settings) {
     $this->settings = $settings + $this->settings;
     return $this;
@@ -411,6 +414,7 @@ public function isRequired() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set whether field is required'), pluralize: FALSE)]
   public function setRequired($required) {
     $this->required = $required;
     return $this;
@@ -443,6 +447,7 @@ public function getDefaultValueLiteral() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set default value'), pluralize: FALSE)]
   public function setDefaultValue($value) {
     $this->default_value = $this->normalizeValue($value, $this->getFieldStorageDefinition()->getMainPropertyName());
     return $this;
diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php
index 72184ed9ae3149b9040f883b006bbb19f11cc339..61c24fcead372f9f566d2dad80b49a97e3835d18 100644
--- a/core/modules/block/src/Entity/Block.php
+++ b/core/modules/block/src/Entity/Block.php
@@ -312,7 +312,7 @@ protected function conditionPluginManager() {
   /**
    * {@inheritdoc}
    */
-  #[ActionMethod(adminLabel: new TranslatableMarkup('Set region'), pluralize: FALSE)]
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set block region'), pluralize: FALSE)]
   public function setRegion($region) {
     $this->region = $region;
     return $this;
@@ -321,7 +321,7 @@ public function setRegion($region) {
   /**
    * {@inheritdoc}
    */
-  #[ActionMethod(adminLabel: new TranslatableMarkup('Set weight'), pluralize: FALSE)]
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set block weight'), pluralize: FALSE)]
   public function setWeight($weight) {
     $this->weight = $weight;
     return $this;
diff --git a/core/modules/block/tests/src/Kernel/ConfigActionsTest.php b/core/modules/block/tests/src/Kernel/ConfigActionsTest.php
index e4078943f9b5d782128c8d3516af8afbb9a8bc59..5fa62b12082d602c647f76bbbe5062a308a1ff9e 100644
--- a/core/modules/block/tests/src/Kernel/ConfigActionsTest.php
+++ b/core/modules/block/tests/src/Kernel/ConfigActionsTest.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ThemeInstallerInterface;
 use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\block\Traits\BlockCreationTrait;
 
 /**
  * @covers \Drupal\block\Plugin\ConfigAction\PlaceBlock
@@ -19,10 +20,12 @@
  */
 class ConfigActionsTest extends KernelTestBase {
 
+  use BlockCreationTrait;
+
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['block', 'user', 'system'];
+  protected static $modules = ['block', 'system', 'user'];
 
   private readonly ConfigActionManager $configActionManager;
 
@@ -40,21 +43,41 @@ protected function setUp(): void {
       ->set('default', 'olivero')
       ->set('admin', 'claro')
       ->save();
-
     $this->configActionManager = $this->container->get('plugin.manager.config_action');
   }
 
+  public function testEntityMethodActions(): void {
+    $block = $this->placeBlock('system_messages_block', ['theme' => 'olivero']);
+    $this->assertSame('content', $block->getRegion());
+    $this->assertSame(0, $block->getWeight());
+
+    $this->configActionManager->applyAction(
+      'entity_method:block.block:setRegion',
+      $block->getConfigDependencyName(),
+      'highlighted',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:block.block:setWeight',
+      $block->getConfigDependencyName(),
+      -10,
+    );
+
+    $block = Block::load($block->id());
+    $this->assertSame('highlighted', $block->getRegion());
+    $this->assertSame(-10, $block->getWeight());
+  }
+
   /**
    * @testWith ["placeBlockInDefaultTheme"]
    *           ["placeBlockInAdminTheme"]
    */
-  public function testActionOnlyWorksOnBlocks(string $action): void {
+  public function testPlaceBlockActionOnlyWorksOnBlocks(string $action): void {
     $this->expectException(PluginNotFoundException::class);
     $this->expectExceptionMessage("The \"$action\" plugin does not exist.");
     $this->configActionManager->applyAction($action, 'user.role.anonymous', []);
   }
 
-  public function testExistingBlockIsNotChanged(): void {
+  public function testPlaceBlockActionDoesNotChangeExistingBlock(): void {
     $extant_region = Block::load('olivero_powered')->getRegion();
     $this->assertNotSame('content', $extant_region);
 
diff --git a/core/modules/contact/src/Entity/ContactForm.php b/core/modules/contact/src/Entity/ContactForm.php
index 514455b4d7d964b04c76d604c1d33cdd963ed52a..16c6d1cc7d9e9a3640669d6e4f5b151ec43c6043 100644
--- a/core/modules/contact/src/Entity/ContactForm.php
+++ b/core/modules/contact/src/Entity/ContactForm.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\contact\Entity;
 
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
 use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
 use Drupal\contact\ContactFormInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Url;
 
 /**
@@ -117,6 +119,7 @@ public function getMessage() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set contact form message'), pluralize: FALSE)]
   public function setMessage($message) {
     $this->message = $message;
     return $this;
@@ -132,6 +135,7 @@ public function getRecipients() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set recipients'), pluralize: FALSE)]
   public function setRecipients($recipients) {
     $this->recipients = $recipients;
     return $this;
@@ -160,6 +164,7 @@ public function getRedirectUrl() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set redirect path'), pluralize: FALSE)]
   public function setRedirectPath($redirect) {
     $this->redirect = $redirect;
     return $this;
@@ -175,6 +180,7 @@ public function getReply() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set auto-reply message'), pluralize: FALSE)]
   public function setReply($reply) {
     $this->reply = $reply;
     return $this;
@@ -190,6 +196,7 @@ public function getWeight() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set weight'), pluralize: FALSE)]
   public function setWeight($weight) {
     $this->weight = $weight;
     return $this;
diff --git a/core/modules/contact/tests/src/Kernel/ConfigActionsTest.php b/core/modules/contact/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9a2eaada66baece899125dfd66ed83b3b3d374d
--- /dev/null
+++ b/core/modules/contact/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\contact\Kernel;
+
+use Drupal\contact\Entity\ContactForm;
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * @group contact
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['contact', 'system', 'user'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig('contact');
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $form = ContactForm::load('personal');
+    $this->assertSame('Your message has been sent.', $form->getMessage());
+    $this->assertEmpty($form->getRecipients());
+    $this->assertSame('/', $form->getRedirectUrl()->toString());
+    $this->assertEmpty($form->getReply());
+    $this->assertSame(0, $form->getWeight());
+
+    $this->configActionManager->applyAction(
+      'entity_method:contact.form:setMessage',
+      $form->getConfigDependencyName(),
+      'Fly, little message!',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:contact.form:setRecipients',
+      $form->getConfigDependencyName(),
+      ['ben@deep.space', 'jake@deep.space'],
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:contact.form:setRedirectPath',
+      $form->getConfigDependencyName(),
+      '/admin/appearance',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:contact.form:setReply',
+      $form->getConfigDependencyName(),
+      "From hell's heart, I reply to thee.",
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:contact.form:setWeight',
+      $form->getConfigDependencyName(),
+      -10,
+    );
+
+    $form = ContactForm::load($form->id());
+    $this->assertSame('Fly, little message!', $form->getMessage());
+    $this->assertSame(['ben@deep.space', 'jake@deep.space'], $form->getRecipients());
+    $this->assertSame('/admin/appearance', $form->getRedirectUrl()->toString());
+    $this->assertSame("From hell's heart, I reply to thee.", $form->getReply());
+    $this->assertSame(-10, $form->getWeight());
+  }
+
+}
diff --git a/core/modules/field/tests/src/Kernel/ConfigActionsTest.php b/core/modules/field/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..70a06101c6b5f005f9076d60775a4ccf95660129
--- /dev/null
+++ b/core/modules/field/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\field\Kernel;
+
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\entity_test\Entity\EntityTestBundle;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * @group field
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['entity_test', 'field'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    EntityTestBundle::create([
+      'id' => 'test',
+      'label' => $this->randomString(),
+    ])->save();
+
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'test',
+      'type' => 'boolean',
+      'entity_type' => 'entity_test_with_bundle',
+    ]);
+    $field_storage->save();
+
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'test',
+    ]);
+    $field->save();
+
+    $this->assertTrue($field->isTranslatable());
+    $this->assertFalse($field->isRequired());
+    $this->assertSame('On', (string) $field->getSetting('on_label'));
+    $this->assertSame('Off', (string) $field->getSetting('off_label'));
+    $this->assertEmpty($field->getDefaultValueLiteral());
+
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setLabel',
+      $field->getConfigDependencyName(),
+      'Not what you were expecting!',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setDescription',
+      $field->getConfigDependencyName(),
+      "Any ol' nonsense can go here.",
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setTranslatable',
+      $field->getConfigDependencyName(),
+      FALSE,
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setRequired',
+      $field->getConfigDependencyName(),
+      TRUE,
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setSettings',
+      $field->getConfigDependencyName(),
+      [
+        'on_label' => 'Zap!',
+        'off_label' => 'Zing!',
+      ],
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:field.field:setDefaultValue',
+      $field->getConfigDependencyName(),
+      [
+        'value' => FALSE,
+      ],
+    );
+
+    $field = FieldConfig::load($field->id());
+    $this->assertNotEmpty($field);
+    $this->assertSame('Not what you were expecting!', $field->getLabel());
+    $this->assertSame("Any ol' nonsense can go here.", $field->getDescription());
+    $this->assertFalse($field->isTranslatable());
+    $this->assertTrue($field->isRequired());
+    $this->assertSame('Zap!', $field->getSetting('on_label'));
+    $this->assertSame('Zing!', $field->getSetting('off_label'));
+    $this->assertSame([['value' => 0]], $field->getDefaultValueLiteral());
+  }
+
+}
diff --git a/core/modules/image/src/Entity/ImageStyle.php b/core/modules/image/src/Entity/ImageStyle.php
index abb6160dffd71612230183c602d8968ca9ebdea7..33d80b1dad6084beba13650afbc616c9ccab3982 100644
--- a/core/modules/image/src/Entity/ImageStyle.php
+++ b/core/modules/image/src/Entity/ImageStyle.php
@@ -3,6 +3,7 @@
 namespace Drupal\image\Entity;
 
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\Entity\EntityFormDisplay;
 use Drupal\Core\Entity\EntityStorageInterface;
@@ -12,6 +13,7 @@
 use Drupal\Core\Routing\RequestHelper;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\StreamWrapperManager;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Url;
 use Drupal\image\ImageEffectPluginCollection;
 use Drupal\image\ImageEffectInterface;
@@ -417,6 +419,7 @@ public function getPluginCollections() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Add an image effect'))]
   public function addImageEffect(array $configuration) {
     $configuration['uuid'] = $this->uuidGenerator()->generate();
     $this->getEffects()->addInstanceId($configuration['uuid'], $configuration);
diff --git a/core/modules/image/tests/src/Kernel/ConfigActionsTest.php b/core/modules/image/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e8391499c471ea93ecb8f642d154be21259fc904
--- /dev/null
+++ b/core/modules/image/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\image\Kernel;
+
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\image\Entity\ImageStyle;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * @group image
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['image', 'system'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig(['image', 'system']);
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $style = ImageStyle::load('large');
+    $this->assertCount(2, $style->getEffects());
+
+    $this->configActionManager->applyAction(
+      'entity_method:image.style:addImageEffect',
+      $style->getConfigDependencyName(),
+      ['id' => 'image_desaturate', 'weight' => 1],
+    );
+
+    $this->assertCount(3, ImageStyle::load('large')->getEffects());
+  }
+
+}
diff --git a/core/modules/language/src/Entity/ConfigurableLanguage.php b/core/modules/language/src/Entity/ConfigurableLanguage.php
index c8f246bf91c40e9a866f79c4e3e1bfdb39ad8fc4..a8235aa4fe2eddd7b5a8aaeaeba16114fa95bbd6 100644
--- a/core/modules/language/src/Entity/ConfigurableLanguage.php
+++ b/core/modules/language/src/Entity/ConfigurableLanguage.php
@@ -2,9 +2,11 @@
 
 namespace Drupal\language\Entity;
 
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\language\ConfigurableLanguageManager;
 use Drupal\language\ConfigurableLanguageManagerInterface;
 use Drupal\language\Exception\DeleteDefaultLanguageException;
@@ -224,6 +226,7 @@ public function getName() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set Language name'), pluralize: FALSE)]
   public function setName($name) {
     $this->label = $name;
 
@@ -254,6 +257,7 @@ public function getWeight() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set weight'), pluralize: FALSE)]
   public function setWeight($weight) {
     $this->weight = $weight;
     return $this;
diff --git a/core/modules/language/tests/src/Kernel/ConfigActionsTest.php b/core/modules/language/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..537678199bf15326149b7a2cfc7184ade51ac4d7
--- /dev/null
+++ b/core/modules/language/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\language\Kernel;
+
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\language\Entity\ConfigurableLanguage;
+
+/**
+ * @group language
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['language'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig('language');
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $language = ConfigurableLanguage::load('en');
+    $this->assertSame('English', $language->getName());
+    $this->assertSame(0, $language->getWeight());
+
+    $this->configActionManager->applyAction(
+      'entity_method:language.entity:setName',
+      $language->getConfigDependencyName(),
+      'Wacky language',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:language.entity:setWeight',
+      $language->getConfigDependencyName(),
+      39,
+    );
+
+    $language = ConfigurableLanguage::load('en');
+    $this->assertSame('Wacky language', $language->getName());
+    $this->assertSame(39, $language->getWeight());
+  }
+
+}
diff --git a/core/modules/media/src/Entity/MediaType.php b/core/modules/media/src/Entity/MediaType.php
index b0047fbeca413c45bd154ff987f2a0d8aca2c2e5..e80b2d3a1a38456fcde793c645c94b4c1fdc0239 100644
--- a/core/modules/media/src/Entity/MediaType.php
+++ b/core/modules/media/src/Entity/MediaType.php
@@ -2,9 +2,11 @@
 
 namespace Drupal\media\Entity;
 
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
 use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\media\MediaTypeInterface;
 
 /**
@@ -168,6 +170,7 @@ public function getDescription() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set description'), pluralize: FALSE)]
   public function setDescription($description) {
     return $this->set('description', $description);
   }
@@ -237,6 +240,7 @@ public function getFieldMap() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set field mapping'), pluralize: FALSE)]
   public function setFieldMap(array $map) {
     return $this->set('field_map', $map);
   }
diff --git a/core/modules/media/tests/src/Kernel/ConfigActionsTest.php b/core/modules/media/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9ec9d21495ce54a28e3fa01c0e109030fb14ec7f
--- /dev/null
+++ b/core/modules/media/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\media\Kernel;
+
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\Core\Extension\ModuleInstallerInterface;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\media\Entity\MediaType;
+
+/**
+ * @group media
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['media'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->container->get(ModuleInstallerInterface::class)->install([
+      'media_test_type',
+    ]);
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $media_type = MediaType::load('test');
+    $this->assertSame('Test type.', $media_type->getDescription());
+    $this->assertSame(['metadata_attribute' => 'field_attribute_config_test'], $media_type->getFieldMap());
+
+    $this->configActionManager->applyAction(
+      'entity_method:media.type:setDescription',
+      $media_type->getConfigDependencyName(),
+      'Changed by a config action...',
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:media.type:setFieldMap',
+      $media_type->getConfigDependencyName(),
+      ['foo' => 'baz'],
+    );
+
+    $media_type = MediaType::load('test');
+    $this->assertSame('Changed by a config action...', $media_type->getDescription());
+    $this->assertSame(['foo' => 'baz'], $media_type->getFieldMap());
+  }
+
+}
diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php
index a6a826f62975868489a8cded7b1b126c2b8155f8..934b4a2c38597b3dd936d93229b695628d42cefc 100644
--- a/core/modules/node/src/Entity/NodeType.php
+++ b/core/modules/node/src/Entity/NodeType.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\node\Entity;
 
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
 use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
 use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\node\NodeTypeInterface;
 
 /**
@@ -128,6 +130,7 @@ public function isLocked() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Automatically create new revisions'), pluralize: FALSE)]
   public function setNewRevision($new_revision) {
     $this->new_revision = $new_revision;
   }
@@ -142,6 +145,7 @@ public function displaySubmitted() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set whether to display submission information'), pluralize: FALSE)]
   public function setDisplaySubmitted($display_submitted) {
     $this->display_submitted = $display_submitted;
   }
@@ -156,6 +160,7 @@ public function getPreviewMode() {
   /**
    * {@inheritdoc}
    */
+  #[ActionMethod(adminLabel: new TranslatableMarkup('Set preview mode'), pluralize: FALSE)]
   public function setPreviewMode($preview_mode) {
     $this->preview_mode = $preview_mode;
   }
diff --git a/core/modules/node/tests/src/Kernel/ConfigActionsTest.php b/core/modules/node/tests/src/Kernel/ConfigActionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9164b0295fecbe633abc043a129bb98ef591a96
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/ConfigActionsTest.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\node\Kernel;
+
+use Drupal\Core\Config\Action\ConfigActionManager;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\node\Entity\NodeType;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+
+/**
+ * @group node
+ */
+class ConfigActionsTest extends KernelTestBase {
+
+  use ContentTypeCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['field', 'node', 'system', 'text', 'user'];
+
+  private readonly ConfigActionManager $configActionManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig('node');
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
+  }
+
+  public function testConfigActions(): void {
+    $node_type = $this->createContentType();
+
+    $this->assertTrue($node_type->shouldCreateNewRevision());
+    $this->assertSame(DRUPAL_OPTIONAL, $node_type->getPreviewMode());
+    $this->assertTrue($node_type->displaySubmitted());
+
+    $this->configActionManager->applyAction(
+      'entity_method:node.type:setNewRevision',
+      $node_type->getConfigDependencyName(),
+      FALSE,
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:node.type:setPreviewMode',
+      $node_type->getConfigDependencyName(),
+      DRUPAL_REQUIRED,
+    );
+    $this->configActionManager->applyAction(
+      'entity_method:node.type:setDisplaySubmitted',
+      $node_type->getConfigDependencyName(),
+      FALSE,
+    );
+
+    $node_type = NodeType::load($node_type->id());
+    $this->assertFalse($node_type->shouldCreateNewRevision());
+    $this->assertSame(DRUPAL_REQUIRED, $node_type->getPreviewMode());
+    $this->assertFalse($node_type->displaySubmitted());
+  }
+
+}
diff --git a/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml b/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
index 31aa1d614ca48cda1527816cb4a4df6ecb9d4778..eaf57abec3b379141bcf61b57998c238e4117ce7 100644
--- a/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
+++ b/core/modules/system/tests/modules/entity_test/config/schema/entity_test.schema.yml
@@ -5,6 +5,12 @@ core.entity_view_display.*.*.*.third_party.entity_test:
     foo:
       type: string
       label: 'Label for foo'
+    noun:
+      type: string
+      label: 'A noun'
+    verb:
+      type: string
+      label: 'A verb'
 
 field.storage_settings.shape:
   type: mapping
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithBundle.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithBundle.php
index 42d26e0e0a0a131b23231c3a3d31fcd7a77af578..baf0a45b856c25782a2eaab41cdd63b115ab9e36 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithBundle.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithBundle.php
@@ -60,6 +60,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setDescription(t('The name of the test entity.'))
       ->setTranslatable(TRUE)
       ->setSetting('max_length', 32)
+      ->setDisplayConfigurable('view', TRUE)
       ->setDisplayOptions('view', [
         'label' => 'hidden',
         'type' => 'string',
diff --git a/core/tests/Drupal/KernelTests/Core/Recipe/EntityMethodConfigActionsTest.php b/core/tests/Drupal/KernelTests/Core/Recipe/EntityMethodConfigActionsTest.php
index 5590fe0e75ad6a020c81d0601000bceee2b43053..4b68ee2855c550e3541e4e08808fe8b553fb23f7 100644
--- a/core/tests/Drupal/KernelTests/Core/Recipe/EntityMethodConfigActionsTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Recipe/EntityMethodConfigActionsTest.php
@@ -4,32 +4,23 @@
 
 namespace Drupal\KernelTests\Core\Recipe;
 
+use Drupal\Core\Config\Action\ConfigActionManager;
 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
-use Drupal\Core\Recipe\RecipeRunner;
-use Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\entity_test\Entity\EntityTestBundle;
 use Drupal\KernelTests\KernelTestBase;
-use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
 
 /**
  * @group Recipe
  */
 class EntityMethodConfigActionsTest extends KernelTestBase {
 
-  use ContentTypeCreationTrait;
-  use RecipeTestTrait;
-
   /**
    * {@inheritdoc}
    */
-  protected static $modules = [
-    'field',
-    'layout_builder',
-    'layout_discovery',
-    'node',
-    'system',
-    'text',
-    'user',
-  ];
+  protected static $modules = ['config_test', 'entity_test', 'system'];
+
+  private readonly ConfigActionManager $configActionManager;
 
   /**
    * {@inheritdoc}
@@ -37,58 +28,145 @@ class EntityMethodConfigActionsTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installConfig('node');
-    $this->createContentType(['type' => 'test']);
+    EntityTestBundle::create([
+      'id' => 'test',
+      'label' => $this->randomString(),
+    ])->save();
 
     $this->container->get(EntityDisplayRepositoryInterface::class)
-      ->getViewDisplay('node', 'test', 'full')
+      ->getViewDisplay('entity_test_with_bundle', 'test')
       ->save();
+
+    $this->configActionManager = $this->container->get('plugin.manager.config_action');
   }
 
   public function testSetSingleThirdPartySetting(): void {
-    $recipe = <<<YAML
-name: Third-party setting
-config:
-  actions:
-    core.entity_view_display.node.test.full:
-      setThirdPartySetting:
-        module: layout_builder
-        key: enabled
-        value: true
-YAML;
-    $recipe = $this->createRecipe($recipe);
-    RecipeRunner::processRecipe($recipe);
+    $this->configActionManager->applyAction(
+      'entity_method:core.entity_view_display:setThirdPartySetting',
+      'core.entity_view_display.entity_test_with_bundle.test.default',
+      [
+        'module' => 'entity_test',
+        'key' => 'verb',
+        'value' => 'Save',
+      ],
+    );
 
     /** @var \Drupal\Core\Config\Entity\ThirdPartySettingsInterface $display */
     $display = $this->container->get(EntityDisplayRepositoryInterface::class)
-      ->getViewDisplay('node', 'test', 'full');
-    $this->assertTrue($display->getThirdPartySetting('layout_builder', 'enabled'));
+      ->getViewDisplay('entity_test_with_bundle', 'test');
+    $this->assertSame('Save', $display->getThirdPartySetting('entity_test', 'verb'));
   }
 
   public function testSetMultipleThirdPartySettings(): void {
-    $recipe = <<<YAML
-name: Third-party setting
-config:
-  actions:
-    core.entity_view_display.node.test.full:
-      setThirdPartySettings:
-        -
-          module: layout_builder
-          key: enabled
-          value: true
-        -
-          module: layout_builder
-          key: allow_custom
-          value: true
-YAML;
-    $recipe = $this->createRecipe($recipe);
-    RecipeRunner::processRecipe($recipe);
+    $this->configActionManager->applyAction(
+      'entity_method:core.entity_view_display:setThirdPartySettings',
+      'core.entity_view_display.entity_test_with_bundle.test.default',
+      [
+        [
+          'module' => 'entity_test',
+          'key' => 'noun',
+          'value' => 'Spaceship',
+        ],
+        [
+          'module' => 'entity_test',
+          'key' => 'verb',
+          'value' => 'Explode',
+        ],
+      ],
+    );
 
     /** @var \Drupal\Core\Config\Entity\ThirdPartySettingsInterface $display */
     $display = $this->container->get(EntityDisplayRepositoryInterface::class)
-      ->getViewDisplay('node', 'test', 'full');
-    $this->assertTrue($display->getThirdPartySetting('layout_builder', 'enabled'));
-    $this->assertTrue($display->getThirdPartySetting('layout_builder', 'allow_custom'));
+      ->getViewDisplay('entity_test_with_bundle', 'test');
+    $this->assertSame('Spaceship', $display->getThirdPartySetting('entity_test', 'noun'));
+    $this->assertSame('Explode', $display->getThirdPartySetting('entity_test', 'verb'));
+  }
+
+  /**
+   * @testWith ["set", {"property_name": "protected_property", "value": "Here be sandworms..."}]
+   *   ["setMultiple", [{"property_name": "protected_property", "value": "Here be sandworms..."}, {"property_name": "label", "value": "New face"}]]
+   */
+  public function testSet(string $action_name, array $value): void {
+    $storage = $this->container->get(EntityTypeManagerInterface::class)
+      ->getStorage('config_test');
+
+    $entity = $storage->create([
+      'id' => 'foo',
+      'label' => 'Behold!',
+      'protected_property' => 'Here be dragons...',
+    ]);
+    $this->assertSame('Behold!', $entity->get('label'));
+    $this->assertSame('Here be dragons...', $entity->get('protected_property'));
+    $entity->save();
+
+    $this->configActionManager->applyAction(
+      "entity_method:config_test.dynamic:$action_name",
+      $entity->getConfigDependencyName(),
+      $value,
+    );
+
+    $expected_values = array_is_list($value) ? $value : [$value];
+    $entity = $storage->load('foo');
+    foreach ($expected_values as ['property_name' => $name, 'value' => $value]) {
+      $this->assertSame($value, $entity->get($name));
+    }
+  }
+
+  /**
+   * @testWith [true, "setStatus", false, false]
+   *   [false, "setStatus", true, true]
+   *   [true, "disable", [], false]
+   *   [false, "enable", [], true]
+   */
+  public function testSetStatus(bool $initial_status, string $action_name, array|bool $value, bool $expected_status): void {
+    $storage = $this->container->get(EntityTypeManagerInterface::class)
+      ->getStorage('config_test');
+
+    $entity = $storage->create([
+      'id' => 'foo',
+      'label' => 'Behold!',
+      'status' => $initial_status,
+    ]);
+    $this->assertSame($initial_status, $entity->status());
+    $entity->save();
+
+    $this->configActionManager->applyAction(
+      "entity_method:config_test.dynamic:$action_name",
+      $entity->getConfigDependencyName(),
+      $value,
+    );
+
+    $this->assertSame($expected_status, $storage->load('foo')->status());
+  }
+
+  /**
+   * @testWith ["hideComponent"]
+   *   ["hideComponents"]
+   */
+  public function testRemoveComponentFromDisplay(string $action_name): void {
+    $this->assertStringStartsWith('hideComponent', $action_name);
+
+    /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $repository */
+    $repository = $this->container->get(EntityDisplayRepositoryInterface::class);
+
+    $view_display = $repository->getViewDisplay('entity_test_with_bundle', 'test');
+    $this->assertIsArray($view_display->getComponent('name'));
+
+    // The `hideComponent` action is an alias for `removeComponent`, proving
+    // that entity methods can be aliased.
+    $this->configActionManager->applyAction(
+      "entity_method:core.entity_view_display:$action_name",
+      $view_display->getConfigDependencyName(),
+      $action_name === 'hideComponents' ? ['name'] : 'name',
+    );
+
+    $view_display = $repository->getViewDisplay('entity_test_with_bundle', 'test');
+    $this->assertNull($view_display->getComponent('name'));
+
+    // The underlying action name should not be available. It should be hidden
+    // by the alias.
+    $plugin_id = str_replace('hide', 'remove', $action_name);
+    $this->assertFalse($this->configActionManager->hasDefinition($plugin_id));
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Config/Action/ActionMethodAttributeTest.php b/core/tests/Drupal/Tests/Core/Config/Action/ActionMethodAttributeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9dabacb5a5d7e2c26d320f13ba7e7e245b69bc5
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Action/ActionMethodAttributeTest.php
@@ -0,0 +1,27 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\Core\Config\Action;
+
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
+use Drupal\Core\Config\Action\Attribute\ActionMethod;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Config\Action\Attribute\ActionMethod
+ * @group Config
+ */
+class ActionMethodAttributeTest extends UnitTestCase {
+
+  /**
+   * @covers ::__construct
+   */
+  public function testInvalidFunctionName(): void {
+    $name = "hello Goodbye";
+    $this->expectException(InvalidPluginDefinitionException::class);
+    $this->expectExceptionMessage("'$name' is not a valid PHP function name.");
+    new ActionMethod(name: $name);
+  }
+
+}