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 @@ +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() {