diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index a94876e..10b94ec 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -200,6 +200,204 @@ 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, 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_configuration_submit_added'])) {
+    array_unshift($form['#submit'], 'language_configuration_element_submit');
+    $form['#language_configuration_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 => $values) {
+      language_save_configuration($values['entity_type'], $values['bundle'],  $form_state['values'][$element_name]);
+    }
+  }
+}
+
+/**
+ * Saves a language configuration that is attached to a bundle or entity type.
+ *
+ * @param string $entity_type
+ *   A string representing the entity type.
+ *
+ * @param string $bundle
+ *   A string representing the bundle.
+ *
+ * @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, $bundle,  $values = array()) {
+  config('language.settings')->set(language_get_configuration_settings_path($entity_type, $bundle), array('language' => $values['language'], 'language_hidden' => $values['language_hidden']))->save();
+}
+
+/**
+ * Returns the language configuration stored for an entity type (and bundle).
+ *
+ * @param string $entity_type
+ *   A string representing the entity type.
+ *
+ * @param string $bundle
+ *   A string representing the bundle.
+ *
+ * @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, $bundle) {
+  $configuration = config('language.settings')->get(language_get_configuration_settings_path($entity_type, $bundle));
+  if (is_null($configuration)) {
+    $configuration = array();
+  }
+  $configuration += array('language' => 'site_default', 'language_hidden' => TRUE);
+  return $configuration;
+}
+
+/**
+ * Returns the 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 string $entity_type
+ *   A string representing the entity type.
+ *
+ * @param string $bundle
+ *   A string representing the bundle.
+ *
+ * @return string
+ *   The root name of the variables.
+ */
+function language_get_configuration_settings_path($entity_type, $bundle) {
+  return 'language_configuration.' . $entity_type . '.' . $bundle;
+}
+
+/**
+ * Returns the default language code assigned to an entity type and a bundle.
+ *
+ * @param string $entity_type
+ *   The entity type.
+ *
+ * @param string $bundle
+ *   The bundle name.
+ *
+ * @return string
+ *   The language code.
+ *
+ */
+function language_get_default_langcode($entity_type, $bundle) {
+  $configuration = language_get_configuration($entity_type, $bundle);
+
+  if (!isset($configuration['language'])) {
+    $configuration['language'] = 'site_default';
+  }
+
+  $default_value = NULL;
+  $language_interface = language(LANGUAGE_TYPE_INTERFACE);
+  switch ($configuration['language']) {
+    case 'site_default':
+      $default_value = language_default()->langcode;
+      break;
+
+    case 'current_interface':
+      $default_value = $language_interface->langcode;
+      break;
+
+    case 'authors_default':
+      global $user;
+      if (!empty($user->preferred_langcode)) {
+        $default_value = $user->preferred_langcode;
+      }
+      else {
+        $default_value = $language_interface->langcode;
+      }
+      break;
+  }
+  if ($default_value) {
+    return $default_value;
+  }
+  // If we did not found a default value so far, invoke all other modules that
+  // may provide a special default language.
+  $default_value = module_invoke_all('language_default_langcode', $entity_type, $bundle);
+  $default_value = array_shift($default_value);
+  if ($default_value) {
+    return $default_value;
+  }
+
+  // If we still not have a default value, just return the value stored in the
+  // configuration, it has to be an actual language code.
+  return $configuration['language'];
+}
+
+/**
  * 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..24b81d0
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationElementTest.php
@@ -0,0 +1,55 @@
+<?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('some_custom_type', 'some_bundle');
+    // Check that the settings have been saved.
+    $this->assertEqual($lang_conf['language'], 'current_interface');
+    $this->assertTrue($lang_conf['language_hidden']);
+
+    // Reload the page and save again.
+    $this->drupalGet('language-tests/language_configuration_element');
+    $edit['lang_configuration[language]'] = 'authors_default';
+    $edit['lang_configuration[language_hidden]'] = FALSE;
+    $this->drupalPost(NULL, $edit, 'Save');
+    $lang_conf = language_get_configuration('some_custom_type', 'some_bundle');
+    // Check that the settings have been saved.
+    $this->assertEqual($lang_conf['language'], 'authors_default');
+    $this->assertFalse($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..5b3498a
--- /dev/null
+++ b/core/modules/language/tests/language_elements_test/language_elements_test.module
@@ -0,0 +1,39 @@
+<?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() {
+  $conf = language_get_configuration('some_custom_type', '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;
+}
diff --git a/core/modules/node/content_types.inc b/core/modules/node/content_types.inc
index 88495f4..7ab071a 100644
--- a/core/modules/node/content_types.inc
+++ b/core/modules/node/content_types.inc
@@ -184,40 +184,23 @@ function node_type_form($form, &$form_state, $type = NULL) {
     ),
     '#description' => t('Users with the <em>Administer content</em> permission will be able to override these options.'),
   );
-  if (module_exists('language')) {
-    $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"),
-    );
-
-    $form['language'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Language settings'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#group' => 'additional_settings',
-    );
-    $form['language']['node_type_language_default'] = array(
-      '#type' => 'select',
-      '#title' => t('Default language'),
-      '#options' => $lang_options,
-      '#default_value' => variable_get('node_type_language_default_' . $type->type, 'site_default'),
-      '#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'))),
-    );
-    $form['language']['node_type_language_hidden'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Hide language selector'),
-      '#default_value' => variable_get('node_type_language_hidden_' . $type->type, TRUE),
-    );
-  }
+  $form['language'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Language settings'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#group' => 'additional_settings',
+    '#access' => module_exists('language'),
+  );
+  $language_configuration = module_invoke('language', 'get_configuration', 'node', $type->type);
+  $form['language']['language_configuration'] = array(
+    '#type' => 'language_configuration',
+    '#config' => array(
+      'entity_type' => 'node',
+      'bundle' => $type->type,
+    ),
+    '#default_value' => $language_configuration,
+  );
   $form['display'] = array(
     '#type' => 'fieldset',
     '#title' => t('Display settings'),
diff --git a/core/modules/node/content_types.js b/core/modules/node/content_types.js
index 87fc460..bce9909 100644
--- a/core/modules/node/content_types.js
+++ b/core/modules/node/content_types.js
@@ -24,7 +24,7 @@ Drupal.behaviors.contentTypes = {
     $('fieldset#edit-language', context).drupalSetSummary(function(context) {
       var vals = [];
 
-      vals.push($(".form-item-node-type-language-default select option:selected", context).text());
+      vals.push($(".form-item-language-configuration-language select option:selected", context).text());
 
       $('input:checked', context).next('label').each(function() {
         vals.push(Drupal.checkPlain($(this).text()));
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index c5763e8..444f6f1 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -97,12 +97,13 @@ class NodeFormController extends EntityFormController {
       $form['title']['#weight'] = -5;
     }
 
+    $language_configuration = module_invoke('language', 'get_configuration', 'node', $node->type);
     $form['langcode'] = array(
       '#title' => t('Language'),
       '#type' => 'language_select',
       '#default_value' => $node->langcode,
       '#languages' => LANGUAGE_ALL,
-      '#access' => !variable_get('node_type_language_hidden_' . $node->type, TRUE),
+      '#access' => !is_null($language_configuration['language_hidden']) && !$language_configuration['language_hidden'],
     );
 
     $form['additional_settings'] = array(
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
index 3b8a8ae..88a64f7 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
@@ -68,7 +68,7 @@ class NodeFieldMultilingualTestCase extends WebTestBase {
    */
   function testMultilingualNodeForm() {
     // Create "Basic page" content.
-    $langcode = node_type_get_default_langcode('page');
+    $langcode = language_get_default_langcode('node', 'page');
     $title_key = "title";
     $title_value = $this->randomName(8);
     $body_key = "body[$langcode][0][value]";
@@ -116,7 +116,7 @@ class NodeFieldMultilingualTestCase extends WebTestBase {
    */
   function testMultilingualDisplaySettings() {
     // Create "Basic page" content.
-    $langcode = node_type_get_default_langcode('page');
+    $langcode = language_get_default_langcode('node', 'page');
     $title_key = "title";
     $title_value = $this->randomName(8);
     $body_key = "body[$langcode][0][value]";
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index 434384f..e04836c 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -42,8 +42,8 @@ class NodeTypeInitialLanguageTest extends NodeTestBase {
    */
   function testNodeTypeInitialLanguageDefaults() {
     $this->drupalGet('admin/structure/types/manage/article');
-    $this->assertOptionSelected('edit-node-type-language-default', 'site_default', 'The default inital language is the site default.');
-    $this->assertFieldChecked('edit-node-type-language-hidden', 'Language selector is hidden by default.');
+    $this->assertOptionSelected('edit-language-configuration-language', 'site_default', 'The default inital language is the site default.');
+    $this->assertFieldChecked('edit-language-configuration-language-hidden', 'Language selector is hidden by default.');
 
     $this->drupalGet('node/add/article');
     $this->assertNoField('langcode', 'Language is not selectable on node add/edit page by default.');
@@ -59,9 +59,9 @@ class NodeTypeInitialLanguageTest extends NodeTestBase {
     $this->drupalPost('admin/config/regional/language', $edit, t('Save configuration'));
 
     // Tests the initial language after changing the site default language.
-    // First unhide the language selector
+    // First unhide the language selector.
     $edit = array(
-      'node_type_language_hidden' => FALSE,
+      'language_configuration[language_hidden]' => FALSE,
     );
     $this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
     $this->drupalGet('node/add/article');
@@ -70,7 +70,7 @@ class NodeTypeInitialLanguageTest extends NodeTestBase {
 
     // Changes the inital language settings.
     $edit = array(
-      'node_type_language_default' => 'en',
+      'language_configuration[language]' => 'en',
     );
     $this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
     $this->drupalGet('node/add/article');
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 349aab5..71f7d39 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -667,47 +667,6 @@ function node_field_extra_fields() {
 }
 
 /**
- * Get the default language for a node type.
- *
- * @param string $node_type
- *   The type of node.
- *
- * @return string
- *   The language code of the node type's default langcode.
- */
-function node_type_get_default_langcode($node_type) {
-  $default_value = variable_get('node_type_language_default_' . $node_type, 'site_default');
-
-  $language_interface = language(LANGUAGE_TYPE_INTERFACE);
-
-  if ($default_value == LANGUAGE_NOT_SPECIFIED) {
-    return LANGUAGE_NOT_SPECIFIED;
-  }
-
-  switch ($default_value) {
-    case 'site_default':
-      $default_value = language_default()->langcode;
-      break;
-
-    case 'current_interface':
-      $default_value = $language_interface->langcode;
-      break;
-
-    case 'authors_default':
-      global $user;
-      if (!empty($user->preferred_langcode)) {
-        $default_value = $user->preferred_langcode;
-      }
-      else {
-        $default_value = $language_interface->langcode;
-      }
-      break;
-  }
-
-  return $default_value;
-}
-
-/**
  * Deletes a node type from the database.
  *
  * @param $name
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index b2e1e4b..ddada14 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -89,11 +89,12 @@ function node_add($node_type) {
   global $user;
 
   $type = $node_type->type;
+  $lang_code = module_invoke('language', 'get_default_langcode', 'node', $type);
   $node = entity_create('node', array(
     'uid' => $user->uid,
     'name' => (isset($user->name) ? $user->name : ''),
     'type' => $type,
-    'langcode' => node_type_get_default_langcode($type)
+    'langcode' => $lang_code ? $lang_code : language_default()->langcode,
   ));
   drupal_set_title(t('Create @name', array('@name' => $node_type->name)), PASS_THROUGH);
   $output = entity_get_form($node);
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
index 667041e..76a4fe2 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
@@ -50,6 +50,20 @@ class VocabularyFormController extends EntityFormController {
       '#languages' => LANGUAGE_ALL,
       '#default_value' => $vocabulary->langcode,
     );
+    if (module_exists('language')) {
+      $form['default_terms_language'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Default terms language'),
+      );
+      $form['default_terms_language']['default_language'] = array(
+        '#type' => 'language_configuration',
+        '#config' => array(
+          'entity_type' => 'vocabulary',
+          'bundle' => $vocabulary->machine_name,
+        ),
+        '#default_value' => module_invoke('language', 'get_configuration', 'vocabulary', $vocabulary->machine_name),
+      );
+    }
     // Set the hierarchy to "multiple parents" by default. This simplifies the
     // vocabulary form and standardizes the term form.
     $form['hierarchy'] = array(
@@ -72,6 +86,12 @@ class VocabularyFormController extends EntityFormController {
     if (empty($form_state['confirm_delete'])) {
       $actions = parent::actions($form, $form_state);
       array_unshift($actions['delete']['#submit'], array($this, 'submit'));
+      // Add the language configuration submit handler. This is needed because
+      // the submit buttons has custom submit handlers...
+      // @todo: find a solution to avoid this.
+      if (module_exists('language')) {
+        array_unshift($actions['submit']['#submit'],'language_configuration_element_submit');
+      }
       return $actions;
     }
     else {
