Change record status: 
Project: 
Introduced in branch: 
8.x
Introduced in version: 
8.0
Description: 

Generalize language configuration on content types to apply to terms and other entities introduces a new form element, language_configuration, that can be used to specify the default language configuration settings for any entity type and bundle, as for example are the language configuration settings for the node types. Before introducing this form element, selecting the default language settings for a node type was implemented using two fields: a checkbox for specifying if the language select box should be hidden on the node add/edit form, and a select box to define the default language to be used on the node add form.

The new element basically encapsulates these two form elements making this feature much easier to be used on other forms (like on the account settings or taxonomy settings forms). And, on top of that, it also manages the storing and retrieving of these values. For users to properly use this field, the language module has to be enabled; the using code needs to accommodate for the case the module might not be available such as with using module_exists() to wrap the code or using ModuleHandlerInterface::invoke() to invoke API functions from language module. Procedural code can get a ModuleHandler using \Drupal::moduleHandler().

Below is an example of how it is used in core, on the node type edit form:

<?php
    if (module_exists('language')) {
      $language_configuration = language_get_default_configuration('node', $type->type);
      $form['language']['language_configuration'] = array(
        '#type' => 'language_configuration',
        '#entity_information' => array(
          'entity_type' => 'node',
          'bundle' => $type->type,
        ),
         '#default_value' => $language_configuration,
      );
      $form['#submit'][] = 'language_configuration_element_submit';
    }
?>

As it can be seen, there are some particularities of this new element. First, there is a new attribute, #entity_information, which is an array with two keys: entity_type that represents the type of the entity for which the configuration element is used (for example 'node', 'user', etc) and bundle that represents the bundle name ('page', 'article', etc). The other, very important thing, is that the submit function has to be added to the form in order to actually save the values that are selected in the element. The name of the function is language_configuration_element_submit. If the function is not added, the values will be submitted, but not saved. In this case, the code that uses the form element can decide what it wants to do with them.

The code above also shows how to get these values for a specific entity type and bundle. This can be done by using the language_get_default_configuration() function. The first parameter is the entity type and the second is the name of the bundle. The return is an array with two keys: language_hidden which specifies if the language select box should be hidden, and langcode which specifies the default language code. But the langcode is not always a fixed language code, it can be the site's default language, the language of the user or the current interface language.

Below, you can see how these values are used on the node add/edit form:

<?php
    $language_configuration = \Drupal::moduleHandler()->invoke('language', 'get_default_configuration', array('node', $node->getType()));
    $form['langcode'] = array(
      '#title' => t('Language'),
      '#type' => 'language_select',
      '#default_value' => $node->langcode,
      '#languages' => LANGUAGE_ALL,
      '#access' => isset($language_configuration['language_hidden']) && !$language_configuration['language_hidden'],
    );
?>

As it can be seen, it uses ModuleHandlerInterface::invoke() to call the language_get_default_configuration() function because the node module does not depend on the language module. In the example above, the #access attribute is set depending on the language_hidden value from the configuration settings. The default value is the language code of the node, that is determined in the node_add() function, before the node form is called:

<?php
  $langcode = \Drupal::moduleHandler()->invoke('language', 'get_default_langcode', 'node', $type);
  $node = Node::create(array(
    'uid' => $user->uid,
    'name' => (isset($user->name) ? $user->name : ''),
    'type' => $type,
    'langcode' => $langcode ? $langcode : language_default()->langcode,
  ));
?>

To get the default language code for an entity type and bundle, the language_get_default_langcode() function should be used, because the configuration might be set to use the site's default language, or the language of the user as the default value, so it is not always a language code that is saved into the configuration. Again, ModuleHandlerInterface::invoke() is used to call this function.

A working example.

Below is an example of how you could use this field in a real situation. Let's say that there is a module that manages an entity type called 'vehicle' and a bundle 'car'. If you have a settings form for your bundle, you can use the language configuration field like this:

<?php
  if (module_exists('language')) {
    $configuration = language_get_default_configuration('vehicle', 'car');

    $form['language_default_settings'] = array(
      '#type' => 'language_configuration',
      '#entity_information' => array(
        'entity_type' => 'vehicle',
        'bundle' => 'car',
      ),
      '#default_value' => $configuration,
    );
    $form['#submit'][] = 'language_configuration_element_submit';
  }
?>

Then, on the entity add/edit form, where you have the language select field, the settings can be used to check if the language field should be displayed or not, and what default value should have.

<?php
  if (module_exists('language')) {
    $configuration = language_get_default_configuration('vehicle', 'car');
    // The $vehicle is an object that is being edited (if on the
    // edit form) or an object with default values (if on the
    // add form).
    $default_langcode = isset($vehicle->langcode) ? $vehicle->langcode : language_get_default_langcode('vehicle', 'car');

    $form['langcode'] = array(
      '#title' => t('Language'),
      '#type' => 'language_select',
      '#default_value' => $default_langcode,
      '#languages' => LANGUAGE_ALL,
      '#access' => isset($configuration['language_hidden']) && !$configuration['language_hidden'],
    );
  }
?>

You can also check the documentation of the language_select element here: http://drupal.org/node/1749954

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done