diff --git a/core/modules/block/block.js b/core/modules/block/block.js
index 72b5673..1e41f4a 100644
--- a/core/modules/block/block.js
+++ b/core/modules/block/block.js
@@ -32,6 +32,17 @@ Drupal.behaviors.blockSettingsSummary = {
       return vals.join(', ');
     });
 
+    $('fieldset#edit-language', context).drupalSetSummary(function (context) {
+      var vals = [];
+      $('input[type="checkbox"]:checked', context).each(function () {
+        vals.push($.trim($(this).next('label').text()));
+      });
+      if (!vals.length) {
+        vals.push(Drupal.t('Not restricted'));
+      }
+      return vals.join(', ');
+    });
+
     $('fieldset#edit-role', context).drupalSetSummary(function (context) {
       var vals = [];
       $('input[type="checkbox"]:checked', context).each(function () {
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index ecf637d..f9da474 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -71,6 +71,33 @@ function language_schema() {
       'list' => array('weight', 'name'),
     ),
   );
+  $schema['block_language'] = array(
+    'description' => 'Sets up display criteria for blocks based on language',
+    'fields' => array(
+      'module' => array(
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'description' => "The block's origin module, from {block}.module.",
+      ),
+      'delta' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'description' => "The block's unique delta within module, from {block}.delta.",
+      ),
+      'language' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'description' => "The machine-readable name of this language from {language}.langcode.",
+      ),
+    ),
+    'primary key' => array('module', 'delta', 'language'),
+    'indexes' => array(
+      'language' => array('language'),
+    ),
+  );
   return $schema;
 }
 
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 20f7c62..9ebbe80 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -211,3 +211,95 @@ function language_css_alter(&$css) {
     }
   }
 }
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Adds per language block visibility options to block configuration form.
+ *
+ * @see language_form_block_admin_configure_submit()
+ * @see block_admin_configure()
+ */
+function language_form_block_admin_configure_alter(&$form, &$form_state) {
+  $default_language_options = db_query("SELECT language FROM {block_language} WHERE module = :module AND delta = :delta", array(
+    ':module' => $form['module']['#value'],
+    ':delta' => $form['delta']['#value'],
+  ))->fetchCol();
+
+  // Fetch the enabled languages.
+  $enabled_languages = language_list(TRUE);
+  foreach ($enabled_languages as $language) {
+    $languages_options[$language->langcode] = t($language->name);
+  }
+  $form['visibility']['language'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Languages'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#group' => 'visibility',
+    '#weight' => 5,
+  );
+  $form['visibility']['language']['languages'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Show block for specific languages'),
+    '#default_value' => $default_language_options,
+    '#options' => $languages_options,
+    '#description' => t('Show this block only if the current language is of the given language(s). If you select no types, there will be no language-specific limitation.'),
+  );
+  $form['#submit'][] = 'language_form_block_admin_configure_submit';
+}
+
+/**
+ * Form submission handler for locale_form_block_admin_configure_alter().
+ */
+function language_form_block_admin_configure_submit($form, &$form_state) {
+  db_delete('block_language')
+      ->condition('module', $form_state['values']['module'])
+      ->condition('delta', $form_state['values']['delta'])
+      ->execute();
+  $query = db_insert('block_language')->fields(array(
+    'language', 'module', 'delta'
+  ));
+  foreach (array_filter($form_state['values']['languages']) as $language) {
+    $query->values(array(
+      'language' => $language,
+      'module' => $form_state['values']['module'],
+      'delta' => $form_state['values']['delta'],
+    ));
+  }
+  $query->execute();
+}
+
+/**
+ * Implements hook_block_list_alter().
+ *
+ * Hide the blocks that have been disabled for languages visibility setting.
+ */
+function language_block_list_alter(&$blocks) {
+  global $language_interface, $theme_key;
+
+  $result = db_query('SELECT module, delta, language FROM {block_language}');
+  $block_languages = array();
+  foreach ($result as $record) {
+    $block_languages[$record->module][$record->delta][$record->language] = TRUE;
+  }
+  foreach ($blocks as $key => $block) {
+    // Any module using this alter should inspect the data before changing it,
+    // to ensure it is what they expect.
+    if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {
+      // This block was added by a contrib module, leave it in the list.
+      continue;
+    }
+
+    if (!isset($block_languages[$block->module][$block->delta])) {
+      // No language setting for this block, leave it in the list.
+      continue;
+    }
+
+    if (!isset($block_languages[$block->module][$block->delta][$language_interface->langcode])) {
+      // This block should not be displayed with the active language, remove
+      // from the list.
+      unset($blocks[$key]);
+    }
+  }
+}
