diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 74f2fcf..58ebd5d 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -12,6 +12,11 @@ use Drupal\entity\EntityStorageException; use Drupal\entity\EntityInterface; /** + * The type of language used to define the form language. + */ +const ENTITY_LANGUAGE_CONTENT_EDIT = 'language_content_edit'; + +/** * Implements hook_help(). */ function entity_help($path, $arg) { @@ -467,12 +472,13 @@ function entity_form_id(EntityInterface $entity, $operation = 'default') { * @return * A $form_state array already filled the entity form controller. */ -function entity_form_state_defaults(EntityInterface $entity, $operation = 'default') { +function entity_form_state_defaults(EntityInterface $entity, $operation = 'default', $langcode = NULL) { $form_state = array(); $controller = entity_form_controller($entity->entityType(), $operation); $form_state['build_info']['callback'] = array($controller, 'build'); $form_state['build_info']['base_form_id'] = $entity->entityType() . '_form'; $form_state['build_info']['args'] = array($entity); + $form_state['langcode'] = empty($langcode) ? language(ENTITY_LANGUAGE_CONTENT_EDIT)->langcode : $langcode; return $form_state; } @@ -506,8 +512,8 @@ function entity_form_submit(EntityInterface $entity, $operation = 'default', &$f * @return * The processed form for the given entity and operation. */ -function entity_get_form(EntityInterface $entity, $operation = 'default') { - $form_state = entity_form_state_defaults($entity, $operation); +function entity_get_form(EntityInterface $entity, $operation = 'default', $langcode = NULL) { + $form_state = entity_form_state_defaults($entity, $operation, $langcode); $form_id = entity_form_id($entity, $operation); return drupal_build_form($form_id, $form_state); } @@ -556,3 +562,25 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st field_attach_submit($entity_type, $entity, $form, $form_state); } } + +/** + * Implements hook_language_types_info(). + */ +function entity_language_types_info() { + require_once DRUPAL_ROOT . '/core/modules/language/language.negotiation.inc'; + + return array( + ENTITY_LANGUAGE_CONTENT_EDIT => array( + 'name' => t('Form'), + 'description' => t('Order of language detection methods for form.'), + 'fixed' => array(LANGUAGE_NEGOTIATION_CONTENT), + ), + ); +} + +/** + * Implements hook_language_negotiation_info_alter(). + */ +function entity_language_negotiation_info_alter(&$negotiation_info) { + $negotiation_info['language-content']['types'][] = ENTITY_LANGUAGE_CONTENT_EDIT; +} diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormController.php b/core/modules/entity/lib/Drupal/entity/EntityFormController.php index 4f1263c..a611010 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityFormController.php +++ b/core/modules/entity/lib/Drupal/entity/EntityFormController.php @@ -208,11 +208,22 @@ class EntityFormController implements EntityFormControllerInterface { * Implements Drupal\entity\EntityFormControllerInterface::getFormLangcode(). */ public function getFormLangcode($form_state) { - // @todo Introduce a new form language type (see hook_language_types_info()) - // to be used as the default active form language, should it be missing, so - // that entity forms can be used to submit multilingual values. - $language = $this->getEntity($form_state)->language(); - return !empty($language->langcode) ? $language->langcode : NULL; + $entity = $this->getEntity($form_state); + $langcode = FALSE; + + if (language_multilingual()) { + $langcode = $form_state['langcode']; + $translations = $entity->translations(); + $fallback = language_fallback_get_candidates(ENTITY_LANGUAGE_TYPE_FORM); + + while (!empty($langcode) && !isset($translations->data[$langcode])) { + $langcode = array_shift($fallback); + } + } + + // If the site is not multilingual or no translation for the given form + // language is available, fall back to the entity language. + return !empty($langcode) ? $langcode : $entity->language(); } /** diff --git a/core/modules/language/language.module b/core/modules/language/language.module index a94876e..8613aa1 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -410,6 +410,15 @@ function language_language_negotiation_info() { 'description' => t('Use the detected interface language.'), ); + $negotiation_info[LANGUAGE_NEGOTIATION_CONTENT] = array( + 'types' => array(), + 'callbacks' => array('negotiation' => 'language_from_content'), + 'file' => $file, + 'weight' => 8, + 'name' => t('Content'), + 'description' => t('Use the detected content language.'), + ); + $negotiation_info[LANGUAGE_NEGOTIATION_URL_FALLBACK] = array( 'types' => array(LANGUAGE_TYPE_URL), 'callbacks' => array('negotiation' => 'language_url_fallback'), diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index 48a8083..ef90bb9 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -21,6 +21,11 @@ const LANGUAGE_NEGOTIATION_BROWSER = 'language-browser'; const LANGUAGE_NEGOTIATION_INTERFACE = 'language-interface'; /** + * The language is determined using the current content language. + */ +const LANGUAGE_NEGOTIATION_CONTENT = 'language-content'; + +/** * If no URL language, language is determined using an already detected one. */ const LANGUAGE_NEGOTIATION_URL_FALLBACK = 'language-url-fallback'; @@ -56,6 +61,16 @@ function language_from_interface() { } /** + * Identifies the language from the current content language. + * + * @return + * The current content language code. + */ +function language_from_content() { + return language(LANGUAGE_TYPE_CONTENT)->langcode; +} + +/** * Identify language from the Accept-language HTTP header we got. * * We perform browser accept-language parsing only if page cache is disabled, diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php index aa6774b..18b9aee 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php @@ -94,7 +94,8 @@ class LanguageNegotiationInfoTest extends WebTestBase { // Check language negotiation results. $this->drupalGet(''); $last = variable_get('language_test_language_negotiation_last', array()); - foreach (language_types_get_all() as $type) { + $language_types = array_keys(language_types_get_default()); + foreach ($language_types as $type) { $langcode = $last[$type]; $value = $type == LANGUAGE_TYPE_CONTENT || strpos($type, 'test') !== FALSE ? 'it' : 'en'; $this->assertEqual($langcode, $value, t('The negotiated language for %type is %language', array('%type' => $type, '%language' => $langcode)));