diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index 33bc147..f4c0480 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -173,14 +173,16 @@ function language_admin_overview_form_submit($form, &$form_state) {
  * User interface for the language addition screen.
  */
 function language_admin_add_form($form, &$form_state) {
-  $predefined_languages = language_admin_predefined_list();
-  $predefined_languages['custom'] = t('Custom language...');
+  $predefined_languages = language_predefined_list();
   $predefined_default = !empty($form_state['values']['predefined_langcode']) ? $form_state['values']['predefined_langcode'] : key($predefined_languages);
   $form['predefined_langcode'] = array(
-    '#type' => 'select',
+    '#type' => 'language_select',
     '#title' => t('Language name'),
+    '#only_predefined' => TRUE,
     '#default_value' => $predefined_default,
     '#options' => $predefined_languages,
+    '#empty_value' => 'custom',
+    '#empty_option' => t('Custom language...'),
   );
   $form['predefined_submit'] = array(
     '#type' => 'submit',
@@ -418,21 +420,3 @@ function language_admin_delete_form_submit($form, &$form_state) {
 
   $form_state['redirect'] = 'admin/config/regional/language';
 }
-
-/**
- * Prepare a language code list for unused predefined languages.
- */
-function language_admin_predefined_list() {
-  include_once DRUPAL_ROOT . '/core/includes/standard.inc';
-  $languages = language_list();
-  $predefined = standard_language_list();
-  foreach ($predefined as $key => $value) {
-    if (isset($languages[$key])) {
-      unset($predefined[$key]);
-      continue;
-    }
-    $predefined[$key] = t($value[0]);
-  }
-  asort($predefined);
-  return $predefined;
-}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 20f7c62..c53cd9d 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -100,6 +100,89 @@ function language_theme() {
   );
 }
 
+
+/**
+ * Implements hook_element_info().
+ */
+function language_element_info() {
+  $types['language_select'] = array(
+    '#input' => TRUE,
+    '#multiple' => FALSE,
+    '#process' => array('language_process_language_select', 'form_process_select', 'ajax_process_form'),
+    '#title' => t('Language'),
+    '#only_enabled' => FALSE,
+    '#only_predefined' => FALSE,
+    '#empty_value' => LANGUAGE_NOT_SPECIFIED,
+    '#empty_option' => t('- Language neutral -'),
+  );
+
+  return $types;
+}
+
+/**
+ * Processes a language select list form element.
+ *
+ * @param array $element
+ *   The form element to process.
+ * @return array $element
+ *   The processed form element.
+ */
+function language_process_language_select($element) {
+  // If #only_enabled => TRUE, show only the enabled
+  // languages in the select.
+  // Locale has a list of predefined languages. Use that if this option is true.
+  // Don't set the options if another module(translation for example) already
+  // set the options.
+  if (!isset($element['#options'])) {
+    if (!$element['#only_enabled']) {
+      if ($element['#only_predefined']) {
+        $predefined = language_predefined_list();
+      }
+      else {
+        $predefined = language_list_get_names(FALSE);
+      }
+      $element['#options'] = $predefined;
+    }
+    else {
+      $element['#options'] = language_list_get_names(TRUE);
+    }
+  }
+  $element['#theme'] = 'select';
+  $element['#theme_wrappers'] = array('form_element');
+  return $element;
+}
+
+/**
+ * Get all languages by name.
+ */
+function language_list_get_names($only_enabled = FALSE) {
+  $languages = language_list($only_enabled);
+  $names = array();
+  foreach ($languages as $langcode => $language) {
+    $names[$langcode] = $language->name;
+  }
+  return $names;
+}
+
+
+/**
+ * Prepare a language code list for unused predefined languages.
+ */
+function language_predefined_list() {
+  include_once DRUPAL_ROOT . '/core/includes/standard.inc';
+  $languages = language_list();
+  $predefined = standard_language_list();
+  foreach ($predefined as $key => $value) {
+    if (isset($languages[$key])) {
+      unset($predefined[$key]);
+      continue;
+    }
+    $predefined[$key] = t($value[0]);
+  }
+  asort($predefined);
+  return $predefined;
+}
+
 /**
  * API function to add or update a language.
  *
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index a4982e1..72adbb0 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -28,14 +28,14 @@ function locale_translate_import_form($form, &$form_state) {
   // the list of existing and then predefined languages.
   form_load_include($form_state, 'inc', 'language', 'language.admin');
   if (empty($existing_languages)) {
-    $language_options = language_admin_predefined_list();
+    $language_options = language_predefined_list();
     $default = key($language_options);
   }
   else {
     $default = key($existing_languages);
     $language_options = array(
       t('Already added languages') => $existing_languages,
-      t('Languages not yet added') => language_admin_predefined_list()
+      t('Languages not yet added') => language_predefined_list()
     );
   }
 
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 6d3ded0..f643752 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -599,10 +599,6 @@ function locale_language_delete($language) {
   cache()->delete('locale:' . $language->langcode);
 }
 
-
-// ---------------------------------------------------------------------------------
-// Locale core functionality
-
 /**
  * Provides interface translation services.
  *
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 4e94b26..d496a94 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -176,16 +176,10 @@ function node_form($form, &$form_state, $node) {
   $form['#node'] = $node;
 
   if (variable_get('node_type_language_' . $node->type, 0) && module_exists('language')) {
-    $languages = language_list(TRUE);
-    $language_options = array();
-    foreach ($languages as $langcode => $language) {
-      $language_options[$langcode] = $language->name;
-    }
     $form['langcode'] = array(
-      '#type' => 'select',
+      '#type' => 'language_select',
       '#title' => t('Language'),
       '#default_value' => (isset($node->langcode) ? $node->langcode : ''),
-      '#options' => $language_options,
       '#empty_value' => LANGUAGE_NOT_SPECIFIED,
     );
   }
diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc
index fe122cc..7d858af 100644
--- a/core/modules/path/path.admin.inc
+++ b/core/modules/path/path.admin.inc
@@ -133,20 +133,15 @@ function path_admin_form($form, &$form_state, $path = array('source' => '', 'ali
 
   // A hidden value unless language.module is enabled.
   if (module_exists('language')) {
-    $languages = language_list(TRUE);
-    foreach ($languages as $langcode => $language) {
-      $language_options[$langcode] = $language->name;
-    }
-
     $form['langcode'] = array(
-      '#type' => 'select',
+      '#type' => 'language_select',
+      '#only_enabled' => TRUE,
+      '#default_value' => $path['langcode'],
       '#title' => t('Language'),
-      '#options' => $language_options,
       '#empty_value' => LANGUAGE_NOT_SPECIFIED,
       '#empty_option' => t('- None -'),
-      '#default_value' => $path['langcode'],
       '#weight' => -10,
-      '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set as <em>- None -</em>.'),
+      '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set for <em>- None -</em>.'),
     );
   }
   else {
