diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index a94876e..3a7c54a 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -200,6 +200,150 @@ function language_process_language_select($element) {
 }
 
 /**
+ * Implements hook_element_info().
+ */
+function language_element_info() {
+  $types['language_configuration'] = array(
+    '#input' => TRUE,
+    '#tree' => TRUE,
+    '#process' => array('language_configuration_process'),
+  );
+  return $types;
+}
+
+/**
+ * Process handler for the language_configuration form element.
+ */
+function language_configuration_process($element, &$form_state, &$form) {
+  $lang_options = array();
+
+  $languages = language_list(LANGUAGE_ALL);
+  foreach ($languages as $langcode => $language) {
+    $lang_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name;
+  }
+
+  $lang_options += array(
+    'site_default' => t("Site's default language"),
+    'current_interface' => t('Current interface language'),
+    'authors_default' => t("Author's preferred language"),
+  );
+  // Some other module may want to alter the available options. For example, the
+  // on the vocabulary edit form, we may want to add the option that the term
+  // of that vocabulary have as default language the language of the entity to
+  // which they are assigned.
+  drupal_alter('language_configuration_element_options', $lang_options, $element['#config']);
+  $element['language'] = array(
+    '#type' => 'select',
+    '#title' => t('Default language'),
+    '#options' => $lang_options,
+    '#description' => t('Explanation of the language options is found on the <a href="@languages_list_page">languages list page</a>.', array('@languages_list_page' => url('admin/config/regional/language'))),
+    '#default_value' => isset($element['#default_value']['language']) ? $element['#default_value']['language'] : NULL,
+  );
+  $element['language_hidden'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Hide language selector'),
+    '#default_value' => isset($element['#default_value']['language_hidden']) ? $element['#default_value']['language_hidden'] : NULL,
+  );
+
+  // Add the entity type and bundle information to the form if they are set.
+  // They will be used, in the submit handler, to generate the names of the
+  // variables that will store the settings.
+  // @todo: #cofig is maybe not a very good key name...
+  if (isset($element['#config']['entity_type'])) {
+    $form['#language_configuration_elements'][$element['#name']]['entity_type'] = $element['#config']['entity_type'];
+  }
+  if (isset($element['#config']['bundle'])) {
+    $form['#language_configuration_elements'][$element['#name']]['bundle'] = $element['#config']['bundle'];
+  }
+
+  // Add a new submit handler, but only if it was not already added to the form.
+  if (!isset($form['#submit'])) {
+    $form['#submit'] = array();
+  }
+  if (!isset($form['#language_configation_submit_added'])) {
+    array_unshift($form['#submit'], 'language_configuration_element_submit');
+    $form['#language_configation_submit_added'] = TRUE;
+  }
+  return $element;
+}
+
+/**
+ * Submit handler for the forms that have a language_configuration element.
+ */
+function language_configuration_element_submit(&$form, &$form_state) {
+  // Iterate through all the language_configuration elements and save their
+  // values.
+  if (isset($form['#language_configuration_elements'])) {
+    foreach ($form['#language_configuration_elements'] as $element_name => $entity_types) {
+      language_save_configuration($entity_types, $form_state['values'][$element_name]);
+    }
+  }
+}
+
+/**
+ * Saves a language configuration that is attached to a bundle or entity type.
+ *
+ * @param array $entity_type
+ *   An array that contains information about the entity type (and bundle) for
+ *   which the settings are saved. It can have the following keys:
+ *   - entity_type: the type of the entity
+ *   - bundle: if the setting is attached to a bundle of an entity type, then
+ *   this should be specified by this value.
+ *
+ * @param array $values
+ *   An array with values to be saved. It has the following keys:
+ *   - language: the language code.
+ *   - language_hidden: if the language element should be hidden or not.
+ */
+function language_save_configuration($entity_type, $values) {
+  $variable_root_name = language_get_configuration_variable_root_name($entity_type);
+  variable_set($variable_root_name . '_language', $values['language']);
+  variable_set($variable_root_name . '_language_hidden', $values['language_hidden']);
+}
+
+/**
+ * Returns the language configuration stored for an entity type (and bundle).
+ *
+ * @param array $entity_type
+ *   An array with the same structure as in language_save_configuration().
+ *
+ * @return array
+ *   An array with the following keys:
+ *   - language: the language code.
+ *   - language_hidden: if the language element is hidden or not.
+ */
+function language_get_configuration($entity_type) {
+  $variable_root_name = language_get_configuration_variable_root_name($entity_type);
+  return array(
+    'language' => variable_get($variable_root_name . '_language', 'en'),
+    'language_hidden' => variable_get($variable_root_name . '_language_hidden', ''),
+  );
+}
+
+/**
+ * Returns that root name of the variables used to store the configuration.
+ *
+ * Based on the entity type (and if needed, bundle), the variables used to store
+ * the configuration will have a common root name.
+ *
+ * @param array $entity_type
+ *   An array with the same structure as in language_save_configuration().
+ *
+ * @return string
+ *   The root name of the variables.
+ */
+function language_get_configuration_variable_root_name($entity_type) {
+  $root_name = 'language_configuration';
+  if (isset($entity_types['entity_type'])) {
+    $root_name .= '_' . $entity_types['entity_type'];
+  }
+  if (isset($entity_types['bundle'])) {
+    $root_name .= '_' . $entity_types['bundle'];
+  }
+  return $root_name;
+}
+
+/**
  * API function to add or update a language.
  *
  * @param $language
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationElementTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationElementTest.php
new file mode 100644
index 0000000..e64078c
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationElementTest.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\language\Tests\LanguageConfigurationElementTest.
+ */
+
+namespace Drupal\language\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Functional tests for language configuration's effect on negotiation setup.
+ */
+class LanguageConfigurationElementTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('language', 'language_elements_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Language configuration form element tests',
+      'description' => 'Tests the features of the language configuration element field.',
+      'group' => 'Language',
+    );
+  }
+
+  public function testLanguageConfigurationElement() {
+    $this->drupalGet('language-tests/language_configuration_element');
+    $edit['lang_configuration[language]'] = 'current_interface';
+    $edit['lang_configuration[language_hidden]'] = TRUE;
+    $this->drupalPost(NULL, $edit, 'Save');
+    $lang_conf = language_get_configuration(array('entity_type' => 'some_custom_type', 'bundle' => 'some_bundle'));
+    // Check that the settings have been saved.
+    $this->assertEqual($lang_conf['language'], 'current_interface');
+    $this->assertTrue($lang_conf['language_hidden']);
+    // @todo: check also the interface and write more tests.
+  }
+}
diff --git a/core/modules/language/tests/language_elements_test/language_elements_test.info b/core/modules/language/tests/language_elements_test/language_elements_test.info
new file mode 100644
index 0000000..c88befb
--- /dev/null
+++ b/core/modules/language/tests/language_elements_test/language_elements_test.info
@@ -0,0 +1,6 @@
+name = "Language form elements test"
+description = "Support module for the language form elements tests."
+core = 8.x
+package = Testing
+version = VERSION
+hidden = TRUE
diff --git a/core/modules/language/tests/language_elements_test/language_elements_test.module b/core/modules/language/tests/language_elements_test/language_elements_test.module
new file mode 100644
index 0000000..428f14b
--- /dev/null
+++ b/core/modules/language/tests/language_elements_test/language_elements_test.module
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Mock module for language form elements test.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function language_elements_test_menu() {
+  $items['language-tests/language_configuration_element'] = array(
+    'title' => 'Language configuration form element',
+    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('language_elements_test_configuration_element'),
+  );
+  return $items;
+}
+
+function language_elements_test_configuration_element() {
+  //$form['#submit'] = array('_language_elements_test_submit_values_json');
+  $conf = language_get_configuration(array('entity_type' => 'some_custom_type', 'bundle' => 'some_bundle'));
+
+  $form['lang_configuration'] = array(
+    '#type' => 'language_configuration',
+    '#config' => array(
+      'entity_type' => 'some_custom_type',
+      'bundle' => 'some_bundle',
+    ),
+    '#default_value' => $conf,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Save',
+  );
+  return $form;
+}
+
+/**
+ * Form submit handler to return form values as JSON.
+ */
+function _language_elements_test_submit_values_json($form, &$form_state) {
+  // This won't have a proper JSON header, but Drupal doesn't check for that
+  // anyway so this is fine until it's replaced with a JsonResponse.
+  print drupal_json_encode($form_state['values']);
+  drupal_exit();
+}
