diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index d315b27..5f36980 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -124,6 +124,16 @@
   protected $translationInitialize = FALSE;
 
   /**
+   * An array of entity translations marked as modified.
+   *
+   * An associative array keyed by translation language code. Every value is a
+   * boolean.
+   *
+   * @var array
+   */
+  protected $dirty = array();
+
+  /**
    * Boolean indicating whether a new revision should be created on save.
    *
    * @var bool
@@ -592,6 +602,30 @@ public function onChange($name) {
         }
         break;
     }
+
+    // @todo This detection of modifications is just a proof-of-concept
+    // and far away from beeing robust
+    if ($this->getFieldDefinition($name)->isTranslatable() &&
+      isset($this->values[$name]) && isset($this->values[$name][$this->activeLangcode]) &&
+      isset($this->values[$name][0]) && isset($this->values[$name][$this->activeLangcode][0]) &&
+      isset($this->values[$name][0]['value']) && isset($this->values[$name][$this->activeLangcode][0]['value']) &&
+      $this->{$name}->getValue()[0]['value'] != $this->values[$name][$this->activeLangcode][0]['value']
+  ) {
+      $this->dirty[$this->activeLangcode] = TRUE;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isTranslationDirty($langcode) {
+    // Ensure we always use the default language code when dealing with the
+    // original entity language.
+    if ($langcode != LanguageInterface::LANGCODE_DEFAULT && $langcode == $this->defaultLangcode) {
+      $langcode = LanguageInterface::LANGCODE_DEFAULT;
+    }
+
+    return isset($this->dirty[$langcode]);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
index 657a599..2ed780f 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php
@@ -38,4 +38,12 @@
    */
   public function initTranslation($langcode);
 
+  /**
+   * Determines if a translation has been modified.
+   *
+   * @param string $langcode
+   *   The language code identifying the translation.
+   */
+  public function isTranslationDirty($langcode);
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityChangedInterface.php b/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
index a8b1a61..81da867 100644
--- a/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityChangedInterface.php
@@ -18,9 +18,12 @@
   /**
    * Returns the timestamp of the last entity change.
    *
+   * @param bool $across_translations
+   *   Whether to get the latest changed time across all translations.
+   *
    * @return int
    *   The timestamp of the last entity save operation.
    */
-  public function getChangedTime();
+  public function getChangedTime($across_translations = FALSE);
 
 }
diff --git a/core/lib/Drupal/Core/Entity/Exception/EntityTranslationChangedException.php b/core/lib/Drupal/Core/Entity/Exception/EntityTranslationChangedException.php
new file mode 100644
index 0000000..2119497
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Exception/EntityTranslationChangedException.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Entity\Exception\EntityTranslationChangedException.
+ */
+
+namespace Drupal\Core\Entity\Exception;
+
+/**
+ * Exception thrown on erroneous usage of entity translation changed timestamps.
+ */
+class EntityTranslationChangedException extends \Exception {
+}
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 9dd3628..91d15df 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
@@ -26,7 +26,7 @@ public function validate($value, Constraint $constraint) {
       if (!$entity->isNew()) {
         $saved_entity = \Drupal::entityManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
 
-        if ($saved_entity && ($saved_entity instanceof EntityChangedInterface) && ($saved_entity->getChangedTime() > $value)) {
+        if ($saved_entity && ($saved_entity instanceof EntityChangedInterface) && ($saved_entity->getChangedTime(TRUE) > $value)) {
           $this->context->addViolation($constraint->message);
         }
       }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/ChangedItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/ChangedItem.php
index cafdde7..0f7e4a4 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/ChangedItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/ChangedItem.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
+use Drupal\Core\Entity\ContentEntityInterface;
 
 /**
  * Defines the 'changed' entity field type.
@@ -28,7 +29,30 @@ class ChangedItem extends CreatedItem {
    */
   public function preSave() {
     parent::preSave();
-    $this->value = REQUEST_TIME;
+
+    $entity = $this->getEntity();
+    if ($entity->isNew() || !$this->getFieldDefinition()->isTranslatable()) {
+      $this->value = REQUEST_TIME;
+    }
+    else {
+      $field_name = $this->getFieldDefinition()->getName();
+      $original = $this->getFieldDefinition()->isTranslatable() ?
+        $entity->original->getTranslation($entity->language()->getId()) :
+        $entity->original;
+      // If the timestamp has not been set explicitly auto detect a modification
+      // of the current translation and set the timestamp if needed.
+      if ($this->value == $original->{$field_name}->value) {
+        if (($entity instanceof ContentEntityInterface)) {
+          if ($entity->isTranslationDirty($entity->language()->getId())) {
+            $this->value = REQUEST_TIME;
+          }
+        }
+        else {
+          // @todo something else for non-ContentEntities?
+          $this->value = REQUEST_TIME;
+        }
+      }
+    }
   }
 
 }
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 046640c..c21fac5 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\Exception\EntityChangedTranslationException;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\block_content\BlockContentInterface;
 
@@ -210,7 +211,10 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = TRUE) {
+    if (!$across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/comment/src/CommentInterface.php b/core/modules/comment/src/CommentInterface.php
index c141706..b31c04a 100644
--- a/core/modules/comment/src/CommentInterface.php
+++ b/core/modules/comment/src/CommentInterface.php
@@ -199,10 +199,13 @@ public function setCreatedTime($created);
   /**
    * Returns the timestamp of when the comment was updated.
    *
+   * @param bool $across_translations
+   *   Whether to get the latest changed time across all translations.
+   *
    * @return int
    *   The timestamp of when the comment was updated.
    */
-  public function getChangedTime();
+  public function getChangedTime($across_translations = FALSE);
 
   /**
    * Checks if the comment is published.
diff --git a/core/modules/comment/src/CommentStatistics.php b/core/modules/comment/src/CommentStatistics.php
index f77a2c1..b1ec86f 100644
--- a/core/modules/comment/src/CommentStatistics.php
+++ b/core/modules/comment/src/CommentStatistics.php
@@ -127,7 +127,7 @@ public function create(FieldableEntityInterface $entity, $fields) {
       // Default to REQUEST_TIME when entity does not have a changed property.
       $last_comment_timestamp = REQUEST_TIME;
       if ($entity instanceof EntityChangedInterface) {
-        $last_comment_timestamp = $entity->getChangedTime();
+        $last_comment_timestamp = $entity->getChangedTime(TRUE);
       }
       $query->values(array(
         'entity_id' => $entity->id(),
@@ -241,9 +241,9 @@ public function update(CommentInterface $comment) {
         ->fields(array(
           'cid' => 0,
           'comment_count' => 0,
-          // Use the created date of the entity if it's set, or default to
+          // Use the changed date of the entity if it's set, or default to
           // REQUEST_TIME.
-          'last_comment_timestamp' => ($entity instanceof EntityChangedInterface) ? $entity->getChangedTime() : REQUEST_TIME,
+          'last_comment_timestamp' => ($entity instanceof EntityChangedInterface) ? $entity->getChangedTime(TRUE) : REQUEST_TIME,
           'last_comment_name' => '',
           'last_comment_uid' => $last_comment_uid,
         ))
diff --git a/core/modules/comment/src/CommentStorage.php b/core/modules/comment/src/CommentStorage.php
index b4977fa..af8e4eb 100644
--- a/core/modules/comment/src/CommentStorage.php
+++ b/core/modules/comment/src/CommentStorage.php
@@ -337,4 +337,13 @@ public function getUnapprovedCount() {
       ->fetchField();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getChangedTimeAcrossTranslations(CommentInterface $comment) {
+    return $this->database->query('SELECT MAX(changed) FROM {comment_field_data} WHERE cid = :cid',
+      array(':cid' => $comment->id())
+    )->fetchField();
+  }
+
 }
diff --git a/core/modules/comment/src/CommentStorageInterface.php b/core/modules/comment/src/CommentStorageInterface.php
index 5be4776..a52051e 100644
--- a/core/modules/comment/src/CommentStorageInterface.php
+++ b/core/modules/comment/src/CommentStorageInterface.php
@@ -115,4 +115,15 @@ public function loadThread(EntityInterface $entity, $field_name, $mode, $comment
    */
   public function getUnapprovedCount();
 
+  /**
+   * Retrieves the latest change time for a comment across all translations.
+   *
+   * @param \Drupal\comment\CommentInterface $comment
+   *   The comment.
+   *
+   * @return int
+   *   The latest changed time across all translations.
+   */
+  public function getChangedTimeAcrossTranslations(CommentInterface $comment);
+
 }
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index 909abc3..ce6eb4a 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -516,7 +516,11 @@ public function setThread($thread) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = FALSE) {
+    if ($across_translations) {
+      return $this->entityManager()->getStorage($this->getEntityTypeId())
+        ->getChangedTimeAcrossTranslations($this);
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/comment/src/Form/CommentAdminOverview.php b/core/modules/comment/src/Form/CommentAdminOverview.php
index 8db0ed3..e20d55c 100644
--- a/core/modules/comment/src/Form/CommentAdminOverview.php
+++ b/core/modules/comment/src/Form/CommentAdminOverview.php
@@ -213,7 +213,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $type = '
             '#url' => $commented_entity->urlInfo(),
           ),
         ),
-        'changed' => $this->dateFormatter->format($comment->getChangedTime(), 'short'),
+        'changed' => $this->dateFormatter->format($comment->getChangedTime(TRUE), 'short'),
       );
       $comment_uri_options = $comment->urlInfo()->getOptions();
       $links = array();
diff --git a/core/modules/comment/src/Tests/CommentTokenReplaceTest.php b/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
index 64cc9c3..9e67cc4 100644
--- a/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
+++ b/core/modules/comment/src/Tests/CommentTokenReplaceTest.php
@@ -61,7 +61,7 @@ function testCommentTokenReplacement() {
     $tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
     $tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
     $tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getCreatedTime(), 2, $language_interface->getId());
-    $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getChangedTime(), 2, $language_interface->getId());
+    $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getChangedTime(TRUE), 2, $language_interface->getId());
     $tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
     $tests['[comment:parent:title]'] = String::checkPlain($parent_comment->getSubject());
     $tests['[comment:entity]'] = String::checkPlain($node->getTitle());
diff --git a/core/modules/content_translation/src/ContentTranslationMetadataWrapper.php b/core/modules/content_translation/src/ContentTranslationMetadataWrapper.php
index 4b4d43e..7632f7a 100644
--- a/core/modules/content_translation/src/ContentTranslationMetadataWrapper.php
+++ b/core/modules/content_translation/src/ContentTranslationMetadataWrapper.php
@@ -129,7 +129,10 @@ public function setCreatedTime($timestamp) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = FALSE) {
+    if ($across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->translation->hasField('content_translation_changed') ? $this->translation->get('content_translation_changed')->value : $this->translation->getChangedTime();
   }
 
diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php
index 42de0ae..a51cba4 100644
--- a/core/modules/file/src/Entity/File.php
+++ b/core/modules/file/src/Entity/File.php
@@ -111,7 +111,10 @@ public function getCreatedTime() {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = TRUE) {
+    if (!$across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
index 5570a2a..2ade726 100644
--- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -132,7 +132,10 @@ public function getWeight() {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = TRUE) {
+    if (!$across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index d0a7bcf..fde8bab 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -757,7 +757,14 @@ function node_page_title(NodeInterface $node) {
  *       for validation, which will be done by EntityChangedConstraintValidator.
  */
 function node_last_changed($nid, $langcode = NULL) {
-  $changed = \Drupal::entityManager()->getStorage('node')->loadUnchanged($nid)->getChangedTime();
+  $changed = FALSE;
+  $node =  \Drupal::entityManager()->getStorage('node')->loadUnchanged($nid);
+  if ($langcode) {
+    $changed = $node->getTranslation($langcode)->getChangedTime();
+  }
+  else {
+    $node->getChangedTime(TRUE);
+  }
   return $changed ? $changed : FALSE;
 }
 
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 2621d82..1fc882c 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -217,7 +217,11 @@ public function setCreatedTime($timestamp) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = FALSE) {
+    if ($across_translations) {
+      return $this->entityManager()->getStorage($this->getEntityTypeId())
+        ->getChangedTimeAcrossTranslations($this);
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/node/src/NodeStorage.php b/core/modules/node/src/NodeStorage.php
index 830fc32..0baf905 100644
--- a/core/modules/node/src/NodeStorage.php
+++ b/core/modules/node/src/NodeStorage.php
@@ -66,4 +66,13 @@ public function clearRevisionsLanguage(LanguageInterface $language) {
       ->execute();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getChangedTimeAcrossTranslations(NodeInterface $node) {
+    return $this->database->query('SELECT MAX(changed) FROM {node_field_revision} WHERE vid = :vid',
+      array(':vid' => $node->getRevisionId())
+    )->fetchField();
+  }
+
 }
diff --git a/core/modules/node/src/NodeStorageInterface.php b/core/modules/node/src/NodeStorageInterface.php
index 1ca7fab..66df1b2 100644
--- a/core/modules/node/src/NodeStorageInterface.php
+++ b/core/modules/node/src/NodeStorageInterface.php
@@ -69,4 +69,16 @@ public function updateType($old_type, $new_type);
    *  The language object.
    */
   public function clearRevisionsLanguage(LanguageInterface $language);
+
+  /**
+   * Retrieves the latest change time for a node across all translations.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node.
+   *
+   * @return int
+   *   The latest changed time across all translations.
+   */
+  public function getChangedTimeAcrossTranslations(NodeInterface $node);
+
 }
diff --git a/core/modules/node/src/Tests/NodeLastChangedTest.php b/core/modules/node/src/Tests/NodeLastChangedTest.php
index 4444cc1..094631b 100644
--- a/core/modules/node/src/Tests/NodeLastChangedTest.php
+++ b/core/modules/node/src/Tests/NodeLastChangedTest.php
@@ -38,7 +38,7 @@ function testNodeLastChanged() {
 
     // Test node last changed timestamp.
     $changed_timestamp = node_last_changed($node->id());
-    $this->assertEqual($changed_timestamp, $node->getChangedTime(), 'Expected last changed timestamp returned.');
+    $this->assertEqual($changed_timestamp, $node->getChangedTime(TRUE), 'Expected last changed timestamp returned.');
 
     $changed_timestamp = node_last_changed($node->id(), $node->language()->getId());
     $this->assertEqual($changed_timestamp, $node->getChangedTime(), 'Expected last changed timestamp returned.');
diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php
index 7a1cc5f..75f2872 100644
--- a/core/modules/taxonomy/src/Entity/Term.php
+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -185,7 +185,10 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = TRUE) {
+    if (!$across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->get('changed')->value;
   }
 
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 1cecfdc..c7b9922 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -425,7 +425,10 @@ public function setUsername($username) {
   /**
    * {@inheritdoc}
    */
-  public function getChangedTime() {
+  public function getChangedTime($across_translations = TRUE) {
+    if (!$across_translations) {
+      throw new EntityChangedTranslationException();
+    }
     return $this->get('changed')->value;
   }
 
