diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 2c54daa..e13c62a 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_TYPE_FORM = 'entity_language_form'; + +/** * Implements hook_help(). */ function entity_help($path, $arg) { @@ -467,9 +472,10 @@ 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['langcode'] = empty($langcode) ? language(LANGUAGE_TYPE_CONTENT)->langcode : $langcode; $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); @@ -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,16 @@ 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() { + return array( + ENTITY_LANGUAGE_TYPE_FORM => array( + 'name' => t('Form'), + 'description' => t('Order of language detection methods for form.'), + 'fixed' => array(LANGUAGE_NEGOTIATION_CONTENT), + ), + ); +} 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,