diff --git a/core/modules/block/block.js b/core/modules/block/block.js
index 72b5673..67cbb31 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-langcode', 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..3f1e74f 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_langcode'] = array(
+    'description' => 'Sets up display criteria for blocks based on langcode.',
+    '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.",
+      ),
+      'langcode' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'description' => "The machine-readable name of this language from {language}.langcode.",
+      ),
+    ),
+    'primary key' => array('module', 'delta', 'langcode'),
+    'indexes' => array(
+      'langcode' => array('langcode'),
+    ),
+  );
   return $schema;
 }
 
@@ -101,3 +128,38 @@ function language_update_8000() {
     variable_set('language_default', $language_default);
   }
 }
+
+/**
+ * Create the {block_langcode} table to store the langcode visibility settings
+ * per block.
+ */
+function language_update_8001() {
+  $schema = array(
+    'description' => 'Sets up display criteria for blocks based on langcode.',
+    '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.",
+      ),
+      'langcode' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'description' => "The machine-readable name of this language from {language}.langcode.",
+      ),
+    ),
+    'primary key' => array('module', 'delta', 'langcode'),
+    'indexes' => array(
+      'langcode' => array('langcode'),
+    ),
+  );
+  db_create_table('block_langcode', $schema);
+}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 20f7c62..feb57b1 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -211,3 +211,127 @@ 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_add_block_form_alter(&$form, &$form_state) {
+  // Fetch the enabled languages.
+  $enabled_languages = language_list(TRUE);
+  foreach ($enabled_languages as $language) {
+    $langcodes_options[$language->langcode] = t($language->name);
+  }
+  $form['visibility']['langcode'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Languages'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#group' => 'visibility',
+    '#weight' => 5,
+  );
+  $form['visibility']['langcode']['langcodes'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Show block for specific languages'),
+    '#default_value' => array(),
+    '#options' => $langcodes_options,
+    '#description' => t('Show this block only if the current language is of the given language(s). If you select no language, there will be no language-specific limitation.'),
+  );
+  $form['#submit'][] = 'language_form_block_admin_configure_submit';
+}
+
+/**
+ * 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_langcode_options = db_query("SELECT langcode FROM {block_langcode} 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) {
+    $langcodes_options[$language->langcode] = t($language->name);
+  }
+  $form['visibility']['langcode'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Languages'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#group' => 'visibility',
+    '#weight' => 5,
+  );
+  $form['visibility']['langcode']['langcodes'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Show block for specific languages'),
+    '#default_value' => $default_langcode_options,
+    '#options' => $langcodes_options,
+    '#description' => t('Show this block only if the current language is of the given language(s). If you select no language, 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_langcode')
+      ->condition('module', $form_state['values']['module'])
+      ->condition('delta', $form_state['values']['delta'])
+      ->execute();
+  $query = db_insert('block_langcode')->fields(array(
+    'langcode', 'module', 'delta'
+  ));
+  foreach (array_filter($form_state['values']['langcodes']) as $langcode) {
+    $query->values(array(
+      'langcode' => $langcode,
+      '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 langcodes visibility setting.
+ */
+function language_block_list_alter(&$blocks) {
+  global $language_interface, $theme_key;
+
+  $result = db_query('SELECT module, delta, langcode FROM {block_langcode}');
+  $block_langcodes = array();
+  foreach ($result as $record) {
+    $block_langcodes[$record->module][$record->delta][$record->langcode] = 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_langcodes[$block->module][$block->delta])) {
+      // No language setting for this block, leave it in the list.
+      continue;
+    }
+
+    if (!isset($block_langcodes[$block->module][$block->delta][$language_interface->langcode])) {
+      // This block should not be displayed with the active language, remove
+      // from the list.
+      unset($blocks[$key]);
+    }
+  }
+}
diff --git a/core/modules/language/language.test b/core/modules/language/language.test
index 0a59937..29437d2 100644
--- a/core/modules/language/language.test
+++ b/core/modules/language/language.test
@@ -179,3 +179,80 @@ class LanguageListTest extends DrupalWebTestCase {
     $this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), t('The English language has been removed.'));
   }
 }
+
+
+/**
+ * Functional tests for the language list configuration forms.
+ */
+class LanguageBlockVisibilityTest extends DrupalWebTestCase
+{
+  public static function getInfo() {
+    return array(
+      'name' => 'Language block visibility configuration',
+      'description' => 'Tests if a block can be configure to be only visibile on a particular language.',
+      'group' => 'Language',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('language', 'block', 'devel');
+  }
+
+  /**
+   * Tests the visibility settings for the blocks based on language.
+   */
+  public function testLanguageBlockVisibility() {
+    // Create a new language
+    // User to add and remove language.
+    $admin_user = $this->drupalCreateUser(array(
+      'administer languages', 'access administration pages',
+      'administer blocks', 'administer users',
+    ));
+    $this->drupalLogin($admin_user);
+
+    // Add predefined language.
+    $edit = array(
+      'predefined_langcode' => 'fr',
+    );
+    $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
+    $this->assertText('French', t('Language added successfully.'));
+    // Create a block
+    // Create a block and check if the visibility setting is available.
+    $info_name = $this->randomString(10);
+//    $body = $this->randomString(100);
+    $body = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
+    $edit = array(
+      'regions[stark]' => 'sidebar_first',
+      'info' => $info_name,
+      'body[value]' => $body,
+    );
+    $this->drupalPost('admin/structure/block/add', $edit, t('Save block'));
+
+    // Check that a page has a block
+    $this->drupalGet('<front>', array('language' => 'en'));
+    $this->assertText($body, t('The body of the custom block appears on the page. ' . $body));
+    $this->drupalGet('admin/structure/block/manage/custom/' . $info_name . '/configure');
+
+    // Set visibility settings for one language
+    $edit = array(
+      'langcodes[en]' => TRUE,
+    );
+    $this->drupalPost('admin/structure/block/manage/custom/' . $info_name . '/configure', $edit, t('Save block'));
+
+    // Check that a page has a block for the current language
+    $this->assertText($body, t('The body of the custom block appears on the page.'. url('user/2/edit', array('language' => language_load('en')))));
+
+    // Change the current language
+    $edit = array(
+      'site_default' => 'fr',
+    );
+    $this->drupalPost('admin/config/regional/language', $edit, t('Save configuration'));
+
+    // Check that a page doesn't has a block for the current language anymore
+    $this->drupalGet('user/2/edit');
+    $this->drupalGet('admin/config/regional/language');
+    $this->drupalGet('user/2/edit', array('language' => language_load('en')));
+    $this->drupalGet('user/2/edit', array('language' => language_load('en')));
+    $this->assertNoText($body, t('The body of the custom block does not appears on the page.'));
+  }
+}
diff --git a/core/modules/simpletest/tests/upgrade/upgrade.language.test b/core/modules/simpletest/tests/upgrade/upgrade.language.test
index 192f00c..7bb5234 100644
--- a/core/modules/simpletest/tests/upgrade/upgrade.language.test
+++ b/core/modules/simpletest/tests/upgrade/upgrade.language.test
@@ -150,4 +150,29 @@ class LanguageUpgradePathTestCase extends UpgradePathTestCase {
     // whether index 'plural' has been removed.
     $this->assertFalse(db_index_exists('locales_target', 'plural'), t('Translations without plurals upgraded.'));
   }
+
+  /**
+   * Tests block language visibility.
+   */
+  public function testLanguageBlockVisibilityUpgrade() {
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+    $languages = language_list(TRUE);
+
+    // Check that the language visibility can be set when a block is created.
+    $this->drupalGet('admin/structure/block/add');
+    foreach ($languages as $language) {
+      $this->assertFieldByName('langcodes[' . $language->langcode . ']', NULL, t('Block visibility can be set for the language !language', array('!language' => $language->name)));
+    }
+    // Create a block and check if the visibility setting is available.
+    $info_name = $this->randomString(10);
+    $edit = array(
+      'info' => $info_name,
+      'body[value]' => $this->randomString(100),
+    );
+    $this->drupalPost('admin/structure/block/add', $edit, t('Save block'));
+    $this->drupalGet('admin/structure/block/manage/custom/' . $info_name . '/configure');
+    foreach ($languages as $language) {
+      $this->assertFieldByName('langcodes[' . $language->langcode . ']', NULL, t('Block visibility can be edited for the language !language', array('!language' => $language->name)));
+    }
+  }
 }
