diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 280d4d6..2e13417 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -13,6 +13,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\content_translation\Plugin\LanguageNegotiation\ContentTranslationFormLanguage;
 
 /**
  * Implements hook_help().
@@ -52,16 +53,37 @@ function content_translation_help($route_name, RouteMatchInterface $route_match)
  */
 function content_translation_module_implements_alter(&$implementations, $hook) {
   switch ($hook) {
-    // Move some of our hook implementations to the end of the list.
+    // Move our entity_type_alter hook implementation to the end of the list.
     case 'entity_type_alter':
       $group = $implementations['content_translation'];
       unset($implementations['content_translation']);
       $implementations['content_translation'] = $group;
       break;
+    // Move our entity_prepare_form hook implementation to the beginning of the
+    // list, so that the entity in the form object is exchanged with its
+    // requested translation before any other hook implementations have had
+    // access on it.
+    case 'entity_prepare_form':
+      $group = $implementations['content_translation'];
+      unset($implementations['content_translation']);
+      $implementations = array_merge(array('content_translation' => $group), $implementations);
+      break;
   }
 }
 
 /**
+ * Implements hook_language_types_info().
+ */
+function content_translation_language_types_info() {
+  return [
+    ContentTranslationFormLanguage::TYPE => array(
+      'fixed' => [ContentTranslationFormLanguage::METHOD_ID],
+      'locked' => TRUE,
+    ),
+  ];
+}
+
+/**
  * Implements hook_language_type_info_alter().
  */
 function content_translation_language_types_info_alter(array &$language_types) {
@@ -302,6 +324,24 @@ function content_translation_form_alter(array &$form, FormStateInterface $form_s
 }
 
 /**
+ * Implements hook_entity_prepare_form().
+ *
+ * Load an entity form in specific language as requested by URL query option.
+ */
+function content_translation_entity_prepare_form(EntityInterface $entity, $operation, FormStateInterface $form_state) {
+  if ($entity instanceof ContentEntityInterface && count($entity->getTranslationLanguages()) > 1) {
+    $langcode = \Drupal::languageManager()->getCurrentLanguage(ContentTranslationFormLanguage::TYPE)->getId();
+    if ($langcode && $entity->language()->getId() != $langcode && $entity->hasTranslation($langcode)) {
+      /** @var \Drupal\Core\Entity\EntityFormInterface $form_object*/
+      $form_object = $form_state->getFormObject();
+      $translation = $entity->getTranslation($langcode);
+      $form_object->setEntity($translation);
+      $form_state->set('langcode', $langcode);
+    }
+  }
+}
+
+/**
  * Implements hook_language_fallback_candidates_OPERATION_alter().
  *
  * Performs language fallback for inaccessible translations.
diff --git a/core/modules/content_translation/src/Controller/ContentTranslationController.php b/core/modules/content_translation/src/Controller/ContentTranslationController.php
index d00dee2..f552f4b 100644
--- a/core/modules/content_translation/src/Controller/ContentTranslationController.php
+++ b/core/modules/content_translation/src/Controller/ContentTranslationController.php
@@ -8,6 +8,7 @@
 namespace Drupal\content_translation\Controller;
 
 use Drupal\content_translation\ContentTranslationManagerInterface;
+use Drupal\content_translation\Plugin\LanguageNegotiation\ContentTranslationFormLanguage;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Language\LanguageInterface;
@@ -67,14 +68,17 @@ public function prepareTranslation(ContentEntityInterface $entity, LanguageInter
    *   The route match.
    * @param string $entity_type_id
    *   (optional) The entity type ID.
+   *
    * @return array Array of page elements to render.
-   * Array of page elements to render.
+   *   Array of page elements to render.
    */
   public function overview(RouteMatchInterface $route_match, $entity_type_id = NULL) {
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
     $entity = $route_match->getParameter($entity_type_id);
     $account = $this->currentUser();
     $handler = $this->entityManager()->getHandler($entity_type_id, 'translation');
     $manager = $this->manager;
+    $destination = $this->getDestinationArray();
 
     $languages = $this->languageManager()->getLanguages();
     $original = $entity->getUntranslated()->language()->getId();
@@ -165,8 +169,9 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
           // the entity form, otherwise if we are not dealing with the original
           // language we point the link to the translation form.
           if ($entity->access('update')) {
-            $links['edit']['url'] = $entity->urlInfo('edit-form');
-            $links['edit']['language'] = $language;
+            $url = $entity->urlInfo('edit-form');
+            $url->setOption('query', [ContentTranslationFormLanguage::QUERY_PARAMETER => $langcode] + $destination);
+            $links['edit']['url'] = $url;
           }
           elseif (!$is_original && $handler->getTranslationAccess($entity, 'update')->isAllowed()) {
             $links['edit']['url'] = $edit_url;
diff --git a/core/modules/content_translation/src/Plugin/LanguageNegotiation/ContentTranslationFormLanguage.php b/core/modules/content_translation/src/Plugin/LanguageNegotiation/ContentTranslationFormLanguage.php
new file mode 100644
index 0000000..ea0444e
--- /dev/null
+++ b/core/modules/content_translation/src/Plugin/LanguageNegotiation/ContentTranslationFormLanguage.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\content_translation\Plugin\LanguageNegotiation\ContentTranslationFormLanguage.
+ */
+
+namespace Drupal\content_translation\Plugin\LanguageNegotiation;
+
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\LanguageNegotiationMethodBase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Class for identifying the content translation form language.
+ *
+ * @Plugin(
+ *   id = \Drupal\content_translation\Plugin\LanguageNegotiation\ContentTranslationFormLanguage::METHOD_ID,
+ *   types = {\Drupal\content_translation\Plugin\LanguageNegotiation\ContentTranslationFormLanguage::TYPE},
+ *   weight = 0,
+ *   name = @Translation("Content Translation form language"),
+ *   description = @Translation("Determines the Content Translation form language from a request parameter."),
+ * )
+ */
+class ContentTranslationFormLanguage extends LanguageNegotiationMethodBase {
+
+  /**
+   * The language negotiation method id.
+   */
+  const METHOD_ID = 'content_translation_form_language';
+
+  /**
+   * The content translation form language type.
+   */
+  const TYPE = self::METHOD_ID;
+
+  /**
+   * The query string parameter.
+   */
+  const QUERY_PARAMETER = 'content_translation_target';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLangcode(Request $request = NULL) {
+    $content_translation_target = $request->get(static::QUERY_PARAMETER);
+    return $content_translation_target ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
+  }
+
+}
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
index 3c1bd78..d0fc4f6 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
@@ -42,6 +42,7 @@ function testTranslationUI() {
     $this->doTestPublishedStatus();
     $this->doTestAuthoringInfo();
     $this->doTestTranslationEdit();
+    $this->doTestFormLanguageSwitch();
     $this->doTestTranslationChanged();
     $this->doTestTranslationDeletion();
   }
@@ -249,6 +250,20 @@ protected function doTestAuthoringInfo() {
   }
 
   /**
+   * Tests the form language switch functionality.
+   */
+  protected function doTestFormLanguageSwitch() {
+    $entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
+
+    $message = 'The form language can be switched to @langcode through a query string parameter';
+    foreach ($entity->getTranslationLanguages() as $langcode => $language) {
+      $url = $entity->urlInfo('edit-form', ['query' => ['content_translation_target' => $langcode]]);
+      $this->drupalGet($url);
+      $this->assertRaw($entity->getTranslation($langcode)->{$this->fieldName}->value, format_string($message, array('@langcode' => $langcode)));
+    }
+  }
+
+  /**
    * Tests translation deletion.
    */
   protected function doTestTranslationDeletion() {
