+ $storage = $this->entityManager->getStorage($entity_type_id);
+ $entity_definition = $this->entityManager->getDefinition($entity_type_id);
+
+ $entity = $storage->load($value);
+
+ // If the entity type is revisionable and the parameter has the
+ // "load_latest_revision" flag, load the latest revision.
+ if ($entity instanceof RevisionableInterface && !empty($definition['load_latest_revision']) && $entity_definition->isRevisionable()) {
+ // Retrieve the latest revision ID taking translations into account.
+ $langcode = $this->languageManager()
+ ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
+ ->getId();
+ $entity = $this->getLatestTranslationAffectedRevision($entity, $langcode);
+ }
+
+ // If the entity type is translatable, ensure we return the proper
+ // translation object for the current context.
+ if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) {
+ $entity = $this->entityManager->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']);
+ }
+
+ return $entity;
+ }
+
+ /**
+ * Returns the ID of the latest revision translation of the specified entity.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface $entity
+ * The default revision of the entity being converted.
+ * @param string $langcode
+ * The language of the revision translation to be loaded.
+ *
+ * @return \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface
+ * The latest translation-affecting revision for the specified entity, or
+ * just the latest revision, if the specified entity is not translatable or
+ * does not have a matching translation yet.
+ */
+ protected function getLatestTranslationAffectedRevision(RevisionableInterface $entity, $langcode) {
+ $revision = NULL;
+ $storage = $this->entityManager->getStorage($entity->getEntityTypeId());
+
+ if ($entity instanceof TranslatableRevisionableInterface && $entity->isTranslatable()) {
+ /** @var \Drupal\Core\Entity\TranslatableRevisionableStorageInterface $storage */
+ $revision_id = $storage->getLatestTranslationAffectedRevisionId($entity->id(), $langcode);
+
+ // If the latest translation-affecting revision was a default revision, it
+ // is fine to load the latest revision instead, because in this case the
+ // latest revision, regardless of it being default or pending, will always
+ // contain the most up-to-date values for the specified translation. This
+ // provides a BC behavior when the route is defined by a module always
+ // expecting the latest revision to be loaded and to be the default
+ // revision. In this particular case the latest revision is always going
+ // to be the default revision, since pending revisions would not be
+ // supported.
+ /** @var \Drupal\Core\Entity\TranslatableRevisionableInterface $revision */
+ $revision = $revision_id ? $this->loadRevision($entity, $revision_id) : NULL;
+ if (!$revision || ($revision->wasDefaultRevision() && !$revision->isDefaultRevision())) {
+ $revision = NULL;