diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index bc56c4271eb70fffba9f7e3235aa97384a3ced76..2eb7c2f6b91d26ac7c1f22c4f6be586c1b6e10d0 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -241,6 +241,8 @@ public function createRevision(RevisionableInterface $entity, $default = TRUE, $
     /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
     $new_revision = clone $entity;
 
+    $original_keep_untranslatable_fields = $keep_untranslatable_fields;
+
     // For translatable entities, create a merged revision of the active
     // translation and the other translations in the default revision. This
     // permits the creation of pending revisions that can always be saved as the
@@ -311,6 +313,11 @@ public function createRevision(RevisionableInterface $entity, $default = TRUE, $
     // to the correct translation.
     $new_revision->setRevisionTranslationAffected(TRUE);
 
+    // Notify modules about the new revision.
+    $arguments = [$new_revision, $entity, $original_keep_untranslatable_fields];
+    $this->moduleHandler()->invokeAll($this->entityTypeId . '_revision_create', $arguments);
+    $this->moduleHandler()->invokeAll('entity_revision_create', $arguments);
+
     return $new_revision;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php b/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
index b86317ff010d1f072b3fc92d681e7191e03c6873..b8a55659280efdff4a41adbb342a77047f21417e 100644
--- a/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
+++ b/core/lib/Drupal/Core/Entity/TranslatableRevisionableStorageInterface.php
@@ -20,7 +20,9 @@ interface TranslatableRevisionableStorageInterface extends TranslatableStorageIn
    *   to TRUE.
    * @param bool|null $keep_untranslatable_fields
    *   (optional) Whether untranslatable field values should be kept or copied
-   *   from the default revision when generating a merged revision.
+   *   from the default revision when generating a merged revision. Defaults to
+   *   TRUE if the provided entity is the default translation and untranslatable
+   *   fields should only affect the default translation, FALSE otherwise.
    *
    * @return \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface
    *   A new translatable entity revision object.
diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php
index b4eda00f1a883c3988abc543498be5ab11c4ade9..ac137330f8dc7e1ae1e82663dca095741c7ef76f 100644
--- a/core/lib/Drupal/Core/Entity/entity.api.php
+++ b/core/lib/Drupal/Core/Entity/entity.api.php
@@ -909,6 +909,54 @@ function hook_ENTITY_TYPE_create(\Drupal\Core\Entity\EntityInterface $entity) {
   \Drupal::logger('example')->info('ENTITY_TYPE created: @label', ['@label' => $entity->label()]);
 }
 
+/**
+ * Respond to entity revision creation.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $new_revision
+ *   The new revision that was created.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The original entity that was used to create the revision from.
+ * @param bool|null $keep_untranslatable_fields
+ *   Whether untranslatable field values were kept (TRUE) or copied from the
+ *   default revision (FALSE) when generating a merged revision. If no value was
+ *   explicitly specified (NULL), a default value of TRUE should be assumed if
+ *   the provided entity is the default translation and untranslatable fields
+ *   should only affect the default translation, FALSE otherwise.
+ *
+ * @ingroup entity_crud
+ * @see \Drupal\Core\Entity\RevisionableStorageInterface::createRevision()
+ * @see \Drupal\Core\Entity\TranslatableRevisionableStorageInterface::createRevision()
+ */
+function hook_entity_revision_create(Drupal\Core\Entity\EntityInterface $new_revision, Drupal\Core\Entity\EntityInterface $entity, $keep_untranslatable_fields) {
+  // Retain the value from an untranslatable field, which are by default
+  // synchronized from the default revision.
+  $new_revision->set('untranslatable_field', $entity->get('untranslatable_field'));
+}
+
+/**
+ * Respond to entity revision creation.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $new_revision
+ *   The new revision that was created.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The original entity that was used to create the revision from.
+ * @param bool|null $keep_untranslatable_fields
+ *   Whether untranslatable field values were kept (TRUE) or copied from the
+ *   default revision (FALSE) when generating a merged revision. If no value was
+ *   explicitly specified (NULL), a default value of TRUE should be assumed if
+ *   the provided entity is the default translation and untranslatable fields
+ *   should only affect the default translation, FALSE otherwise.
+ *
+ * @ingroup entity_crud
+ * @see \Drupal\Core\Entity\RevisionableStorageInterface::createRevision()
+ * @see \Drupal\Core\Entity\TranslatableRevisionableStorageInterface::createRevision()
+ */
+function hook_ENTITY_TYPE_revision_create(Drupal\Core\Entity\EntityInterface $new_revision, Drupal\Core\Entity\EntityInterface $entity, $keep_untranslatable_fields) {
+  // Retain the value from an untranslatable field, which are by default
+  // synchronized from the default revision.
+  $new_revision->set('untranslatable_field', $entity->get('untranslatable_field'));
+}
+
 /**
  * Act on entities when loaded.
  *
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index f98ae10b0440aeb9277f1711ca7bb3be0bcdf494..66a42e2931c68ca4620d9b7bc61effdfc101046c 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -680,6 +680,23 @@ function entity_test_entity_test_mul_langcode_key_translation_delete(EntityInter
   _entity_test_record_hooks('entity_test_mul_langcode_key_translation_delete', $translation->language()->getId());
 }
 
+/**
+ * Implements hook_entity_revision_create().
+ */
+function entity_test_entity_revision_create(EntityInterface $new_revision, EntityInterface $entity, $keep_untranslatable_fields) {
+  _entity_test_record_hooks('entity_revision_create', ['new_revision' => $new_revision, 'entity' => $entity, 'keep_untranslatable_fields' => $keep_untranslatable_fields]);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_revision_create() for 'entity_test_mulrev'.
+ */
+function entity_test_entity_test_mulrev_revision_create(EntityInterface $new_revision, EntityInterface $entity, $keep_untranslatable_fields) {
+  if ($new_revision->get('name')->value == 'revision_create_test_it') {
+    $new_revision->set('name', 'revision_create_test_it_altered');
+  }
+  _entity_test_record_hooks('entity_test_mulrev_revision_create', ['new_revision' => $new_revision, 'entity' => $entity, 'keep_untranslatable_fields' => $keep_untranslatable_fields]);
+}
+
 /**
  * Field default value callback.
  *
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
index 616ee1640d7c2ce9f6babb54cf2b8aede81cb450..d4fbcfcb205a9c13e067514ae3cf17081ddfabed 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php
@@ -588,4 +588,58 @@ public function testRemovedTranslations() {
     $this->assertFalse($en_revision->hasTranslation('it'));
   }
 
+  /**
+   * Checks that the revision create hook works as expected.
+   *
+   * @covers ::createRevision
+   */
+  public function testCreateRevisionHook() {
+    $entity = EntityTestMulRev::create();
+    $entity->get('name')->value = 'revision_create_test_en';
+    $this->storage->save($entity);
+
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $translation */
+    $translation = $entity->addTranslation('it');
+    $translation->set('name', 'revision_create_test_it');
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
+    $revision = $this->storage->createRevision($translation, FALSE, TRUE);
+
+    // Assert that the alter hook can alter the new revision.
+    $this->assertEquals('revision_create_test_it_altered', $revision->get('name')->value);
+
+    // Assert the data passed to the hook.
+    $data = $this->state->get('entity_test.hooks');
+    $this->assertEquals('revision_create_test_it', $data['entity_test_mulrev_revision_create']['entity']->get('name')->value);
+    $this->assertEquals('revision_create_test_it_altered', $data['entity_test_mulrev_revision_create']['new_revision']->get('name')->value);
+    $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
+    $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
+    $this->assertTrue($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
+    $this->assertFalse($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
+    $this->assertTrue($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
+
+    $this->assertEquals('revision_create_test_it', $data['entity_revision_create']['entity']->get('name')->value);
+    $this->assertEquals('revision_create_test_it_altered', $data['entity_revision_create']['new_revision']->get('name')->value);
+    $this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
+    $this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
+    $this->assertTrue($data['entity_revision_create']['entity']->isDefaultRevision());
+    $this->assertFalse($data['entity_revision_create']['new_revision']->isDefaultRevision());
+    $this->assertTrue($data['entity_revision_create']['keep_untranslatable_fields']);
+
+    // Test again with different arguments.
+    $translation->isDefaultRevision(FALSE);
+    $this->storage->createRevision($translation);
+    $data = $this->state->get('entity_test.hooks');
+    $this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
+    $this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
+    $this->assertFalse($data['entity_revision_create']['entity']->isDefaultRevision());
+    $this->assertTrue($data['entity_revision_create']['new_revision']->isDefaultRevision());
+    $this->assertNull($data['entity_revision_create']['keep_untranslatable_fields']);
+
+    $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
+    $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
+    $this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
+    $this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
+    $this->assertNull($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
+  }
+
 }