diff --git a/core/lib/Drupal/Core/Entity/ContentEntityForm.php b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
index 1fd99dcbc21de4159b609f248142dfab4ac1d54f..eed3cac3f9a369052a23063a8152c1afc47fb8e2 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityForm.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
@@ -62,6 +62,15 @@ public function form(array $form, FormStateInterface $form_state) {
     return $form;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    parent::submitForm($form, $form_state);
+    // Update the changed timestamp of the entity.
+    $this->updateChangedTime($this->entity);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -269,4 +278,18 @@ public function updateFormLangcode($entity_type_id, EntityInterface $entity, arr
     }
   }
 
+  /**
+   * Updates the changed time of the entity.
+   *
+   * Applies only if the entity implements the EntityChangedInterface.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity updated with the submitted values.
+   */
+  public function updateChangedTime(EntityInterface $entity) {
+    if ($entity->getEntityType()->isSubclassOf(EntityChangedInterface::class)) {
+      $entity->setChangedTime(REQUEST_TIME);
+    }
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityChangedInterface.php b/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
index 5f031a38ae6291466acf595dca984d4690dd2092..2bd29ed65ec2956f192452584a4fe623fb304ffc 100644
--- a/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
@@ -29,6 +29,16 @@ interface EntityChangedInterface {
    */
   public function getChangedTime();
 
+  /**
+   * Sets the timestamp of the last entity change for the current translation.
+   *
+   * @param int $timestamp
+   *   The timestamp of the last entity save operation.
+   *
+   * @return $this
+   */
+  public function setChangedTime($timestamp);
+
   /**
    * Gets the timestamp of the last entity change across all translations.
    *
diff --git a/core/lib/Drupal/Core/Entity/EntityChangedTrait.php b/core/lib/Drupal/Core/Entity/EntityChangedTrait.php
index 5b34d1abaf233ddd12af712662c5b3eaf412d51b..416d4aaf2e04d749212444df4e6ee00f874c8177 100644
--- a/core/lib/Drupal/Core/Entity/EntityChangedTrait.php
+++ b/core/lib/Drupal/Core/Entity/EntityChangedTrait.php
@@ -28,4 +28,26 @@ public function getChangedTimeAcrossTranslations() {
     return $changed;
   }
 
+  /**
+   * Gets the timestamp of the last entity change for the current translation.
+   *
+   * @return int
+   *   The timestamp of the last entity save operation.
+   */
+  public function getChangedTime() {
+    return $this->get('changed')->value;
+  }
+
+  /**
+   * Sets the timestamp of the last entity change for the current translation.
+   *
+   * @param int $timestamp
+   *   The timestamp of the last entity save operation.
+   *
+   * @return $this
+   */
+  public function setChangedTime($timestamp) {
+    $this->set('changed', $timestamp);
+    return $this;
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
index 8fd44dacc07019d689852360b42965c649bb7049..1d26d0b868c233d536809c9b7af1330d562301a5 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
@@ -25,7 +25,7 @@ public function validate($entity, Constraint $constraint) {
         $saved_entity = \Drupal::entityManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
         // A change to any other translation must add a violation to the current
         // translation because there might be untranslatable shared fields.
-        if ($saved_entity && $saved_entity->getChangedTimeAcrossTranslations() > $entity->getChangedTime()) {
+        if ($saved_entity && $saved_entity->getChangedTimeAcrossTranslations() > $entity->getChangedTimeAcrossTranslations()) {
           $this->context->addViolation($constraint->message);
         }
       }
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 7f572bd495b8b5917d5222daffdced5949b50f07..2a052027107bf6098c9fccafa7886108a3658764 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -219,13 +219,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     return $fields;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index 56930493a046281cc06b76368326330148884d44..b20d9bb0d77e0f5b61b466b45166b79dcdddc9d3 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -527,13 +527,6 @@ public function setThread($thread) {
     return $this;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php
index 3979fff518237154069262ef64623cc236c103c3..d7eb42ab3e6c15146c6dd5b9026eaa8c6d0d512d 100644
--- a/core/modules/content_translation/src/ContentTranslationHandler.php
+++ b/core/modules/content_translation/src/ContentTranslationHandler.php
@@ -479,6 +479,13 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
     if (isset($form['actions']['delete'])) {
       $form['actions']['delete']['#submit'][] = array($this, 'entityFormDelete');
     }
+
+    // Handle entity form submission before the entity has been saved.
+    foreach (Element::children($form['actions']) as $action) {
+      if (isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] == 'submit') {
+        array_unshift($form['actions'][$action]['#submit'], [$this, 'entityFormSubmit']);
+      }
+    }
   }
 
   /**
@@ -579,7 +586,6 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr
     $metadata->setAuthor(!empty($values['uid']) ? User::load($values['uid']) : User::load(0));
     $metadata->setPublished(!empty($values['status']));
     $metadata->setCreatedTime(!empty($values['created']) ? strtotime($values['created']) : REQUEST_TIME);
-    $metadata->setChangedTime(REQUEST_TIME);
 
     $source_langcode = $this->getSourceLangcode($form_state);
     if ($source_langcode) {
@@ -611,6 +617,30 @@ function entityFormValidate($form, FormStateInterface $form_state) {
     }
   }
 
+  /**
+   * Form submission handler for ContentTranslationHandler::entityFormAlter().
+   *
+   * Updates metadata fields, which should be updated only after the validation
+   * has run and before the entity is saved.
+   */
+  function entityFormSubmit($form, FormStateInterface $form_state) {
+    /** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */
+    $form_object = $form_state->getFormObject();
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity = $form_object->getEntity();
+
+    // ContentEntityForm::submit will update the changed timestamp on submit
+    // after the entity has been validated, so that it does not break the
+    // EntityChanged constraint validator. The content translation metadata
+    // field for the changed timestamp  does not have such a constraint defined
+    // at the moment, but it is correct to update it's value in a submission
+    // handler as well and have the same logic like in the Form API.
+    if ($entity->hasField('content_translation_changed')) {
+      $metadata = $this->manager->getTranslationMetadata($entity);
+      $metadata->setChangedTime(REQUEST_TIME);
+    }
+  }
+
   /**
    * Form submission handler for ContentTranslationHandler::entityFormAlter().
    *
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
index a5d6d09c15550d35efedb65d2d1308d2cf287c94..de8c349ece50536a710d83a81146f744ce0b933d 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
@@ -65,6 +65,7 @@ function testTranslationUI() {
     $this->doTestAuthoringInfo();
     $this->doTestTranslationEdit();
     $this->doTestTranslationChanged();
+    $this->doTestChangedTimeAfterSaveWithoutChanges();
     $this->doTestTranslationDeletion();
   }
 
@@ -546,4 +547,30 @@ protected function doTestTranslationChanged() {
     }
   }
 
+  /**
+   * Test the changed time after API and FORM save without changes.
+   */
+  public function doTestChangedTimeAfterSaveWithoutChanges() {
+    $entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
+    // Test only entities, which implement the EntityChangedInterface.
+    if ($entity->getEntityType()->isSubclassOf('Drupal\Core\Entity\EntityChangedInterface')) {
+      $changed_timestamp = $entity->getChangedTime();
+
+      $entity->save();
+      $entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
+      $this->assertEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time wasn\'t updated after API save without changes.');
+
+      // Ensure different save timestamps.
+      sleep(1);
+
+      // Save the entity on the regular edit form.
+      $language = $entity->language();
+      $edit_path = $entity->urlInfo('edit-form', array('language' => $language));
+      $this->drupalPostForm($edit_path, [], $this->getFormSubmitAction($entity, $language->getId()));
+
+      $entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
+      $this->assertNotEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time was updated after form save without changes.');
+    }
+  }
+
 }
diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php
index 1a38c16132a136563dc18b8852874038fa281a90..ae5ca764b2183cc8cd891df3f753bf13c4a87a38 100644
--- a/core/modules/file/src/Entity/File.php
+++ b/core/modules/file/src/Entity/File.php
@@ -110,13 +110,6 @@ public function getCreatedTime() {
     return $this->get('created')->value;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
index 7d51ae292147c057e4e01bbae364eb9ce159c613..d83f87115214797b381533e02159751237cee3de 100644
--- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -132,13 +132,6 @@ public function getWeight() {
     return (int) $this->get('weight')->value;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 1e5e5ef8210e05870c04d838c6527d208adba8c8..34d57b46ecaf276572bfb8d029a0ed4af8db076f 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -231,13 +231,6 @@ public function setCreatedTime($timestamp) {
     return $this;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -498,6 +491,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setDescription(t('Briefly describe the changes you have made.'))
       ->setRevisionable(TRUE)
       ->setTranslatable(TRUE)
+      ->setDefaultValue('')
       ->setDisplayOptions('form', array(
         'type' => 'string_textarea',
         'weight' => 25,
diff --git a/core/modules/node/src/Tests/NodeFormSaveChangedTimeTest.php b/core/modules/node/src/Tests/NodeFormSaveChangedTimeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..285a743746f0c89e89793547cdb9363bc471270e
--- /dev/null
+++ b/core/modules/node/src/Tests/NodeFormSaveChangedTimeTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\node\Tests\NodeFormSaveChangedTimeTest.
+ */
+
+namespace Drupal\node\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests updating the changed time after API and FORM entity save.
+ *
+ * @group node
+ */
+class NodeFormSaveChangedTimeTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array(
+    'node',
+  );
+
+  /**
+   * An user with permissions to create and edit articles.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $authorUser;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Create a node type.
+    $this->drupalCreateContentType(array(
+      'type' => 'article',
+      'name' => 'Article',
+    ));
+
+    $this->authorUser = $this->drupalCreateUser(['access content', 'create article content', 'edit any article content'], 'author');
+    $this->drupalLogin($this->authorUser);
+
+    // Create one node of the above node type .
+    $this->drupalCreateNode(array(
+      'type' => 'article',
+    ));
+  }
+
+  /**
+   * Test the changed time after API and FORM save without changes.
+   */
+  public function testChangedTimeAfterSaveWithoutChanges() {
+    $node = entity_load('node', 1);
+    $changed_timestamp = $node->getChangedTime();
+
+    $node->save();
+    $node = entity_load('node', 1, TRUE);
+    $this->assertEqual($changed_timestamp, $node->getChangedTime(), "The entity's changed time wasn't updated after API save without changes.");
+
+    // Ensure different save timestamps.
+    sleep(1);
+
+    // Save the node on the regular node edit form.
+    $this->drupalPostForm('node/1/edit', array(), t('Save'));
+
+    $node = entity_load('node', 1, TRUE);
+    $this->assertNotEqual($changed_timestamp, $node->getChangedTime(), "The entity's changed time was updated after form save without changes.");
+  }
+}
diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php
index 5e84827a9c181a079c07b7cb4540c2a4fcc889c2..b6eb46a7716f6c3e867bd13b2f04fafbf5522149 100644
--- a/core/modules/rest/src/Tests/RESTTestBase.php
+++ b/core/modules/rest/src/Tests/RESTTestBase.php
@@ -389,6 +389,7 @@ protected function removeNodeFieldsForNonAdminUsers(NodeInterface $node) {
     $node->set('promote', NULL);
     $node->set('sticky', NULL);
     $node->set('revision_timestamp', NULL);
+    $node->set('revision_log', NULL);
     $node->set('uid', NULL);
 
     return $node;
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestConstraints.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestConstraints.php
index 61200f7cb42eb23c7ba7b1513a14d47757359933..e9e9bbf00ab0bdff261d8e2703d37af4390c2f83 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestConstraints.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestConstraints.php
@@ -46,12 +46,4 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
 
     return $fields;
   }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php
index 48c3ddca9f05a0592183572f32bba775ed0fd7fe..67811ac925463c17419153aca254839aae1a6484 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php
@@ -72,12 +72,4 @@ public function save() {
     sleep(1);
     parent::save();
   }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
 }
diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php
index 2105a03b684c32153a7ba9bc24986583b29d228d..7020f0fdcf7c9de9de340ffd166a752da198406e 100644
--- a/core/modules/taxonomy/src/Entity/Term.php
+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -187,13 +187,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     return $fields;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 781061a7f28722bb97b703044e036bc5df79831c..1dcdefbef7994ac95a8704bee640e1287b18795c 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -389,13 +389,6 @@ public function setUsername($username) {
     return $this;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
   /**
    * {@inheritdoc}
    */