diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateInterfaceTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateInterfaceTest.php
new file mode 100644
index 0000000..7564bbd
--- /dev/null
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateInterfaceTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Tests for Drupal\locale\Tests\LocaleUpdateInterfaceTest.
+ */
+
+namespace Drupal\locale\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests for the translation status user interfaces.
+ */
+class LocaleUpdateInterfaceTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('update', 'locale', 'locale_test_translate');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Update translations user interface',
+      'description' => 'Tests for the user interface of project interface translations.',
+      'group' => 'Locale',
+    );
+  }
+
+  /**
+   * Setup the test environment.
+   *
+   * We use German as default test language. Due to hardcoded configurations in
+   * the locale_test module, the language can not be chosen randomly.
+   */
+  function setUp() {
+    parent::setUp();
+    $admin_user = $this->drupalCreateUser(array('administer modules', 'administer site configuration', 'administer languages', 'access administration pages', 'translate interface'));
+    $this->drupalLogin($admin_user);
+  }
+
+  /**
+   * Tests the user interfaces of the interface translation update system.
+   *
+   * Testing the Available updates summary on the side wide status page and the
+   * Avaiable translation updates page.
+   */
+  function testInterface() {
+    // No language added.
+    // Check status page and Available translation updates page.
+    $this->drupalGet('admin/reports/status');
+    $this->assertNoText(t('Translation update status'), 'No status message');
+
+    $this->drupalGet('admin/reports/translations');
+    $this->assertRaw(t('No translatable languages available. <a href="@add_language">Add a language</a> first.', array('@add_language' => url('admin/config/regional/language'))), 'Language message');
+
+    // Add German language
+    $edit = array(
+      'predefined_langcode' => 'de',
+    );
+    $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
+
+    // Drupal core is probably in 8.x, but tests may also be executed with
+    // stable releases. Therefore we will just ignore it here to make sure we
+    // have a controlled environment.
+    $status = state()->get('locale.translation_status');
+    unset($status['drupal']);
+    state()->set('locale.translation_status', $status);
+
+    // One language added, all translations up to date.
+    $this->drupalGet('admin/reports/status');
+    $this->assertText(t('Translation update status'), 'Status message');
+    $this->assertText(t('Up to date'), 'Translations up to date');
+    $this->drupalGet('admin/reports/translations');
+    $this->assertText(t('All translations up to date.'), 'Translations up to date');
+
+    // Set locale_test_translate module to have a local translation available.
+    $status = state()->get('locale.translation_status');
+    $status['locale_test_translate']['de']->type = 'local';
+    state()->set('locale.translation_status', $status);
+
+    // Check if updates are available for German.
+    $this->drupalGet('admin/reports/status');
+    $this->assertText(t('Translation update status'), 'Status message');
+    $this->assertRaw(t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => url('admin/reports/translations'))), 'Updates available message');
+    $this->drupalGet('admin/reports/translations');
+    $this->assertText(t('Updates for: @modules', array('@modules' => 'Locale test translate')), 'Translations avaiable');
+
+    // Set locale_test_translate module to have a dev release and no
+    // translation found.
+    $status = state()->get('locale.translation_status');
+    $status['locale_test_translate']['de']->version = '1.3-dev';
+    unset($status['locale_test_translate']['de']->type);
+    state()->set('locale.translation_status', $status);
+
+    // Check if no updates were found.
+    $this->drupalGet('admin/reports/status');
+    $this->assertText(t('Translation update status'), 'Status message');
+    $this->assertRaw(t('Updates not found for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => url('admin/reports/translations'))), 'Updates not found message');
+    $this->drupalGet('admin/reports/translations');
+    $this->assertText(t('No updates found for 1 project'), 'No updates found');
+    $this->assertText(t('@module (@version).', array('@module' => 'Locale test translate', '@version' => '1.3-dev')), 'Release details');
+    $this->assertText(t('No translation files are provided for development releases.'), 'Release info');
+  }
+
+}
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
index 6f96943..9896aa7 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\locale\Tests\LocaleCompareTest.
+ * Definition of Drupal\locale\Tests\LocaleUpdateTest.
  */
 
 namespace Drupal\locale\Tests;
@@ -51,7 +51,7 @@ class LocaleUpdateTest extends WebTestBase {
 
   public static function getInfo() {
     return array(
-      'name' => 'Update Interface translations',
+      'name' => 'Update translations',
       'description' => 'Tests for updating the interface translations of projects.',
       'group' => 'Locale',
     );
@@ -429,9 +429,18 @@ function testUpdateImportSourceRemote() {
     );
     $this->drupalPost('admin/config/regional/translate/settings', $edit, t('Save configuration'));
 
-    // Execute the translation update.
+    // Get the translation status.
     $this->drupalGet('admin/reports/translations/check');
-    $this->drupalPost('admin/reports/translations', array(), t('Update'));
+
+    // Check the status on the Available translation status page.
+    $this->assertRaw('<label for="edit-languages-de" class="language-name">German</label>', 'German language found');
+    $this->assertText('Updates for: Contributed module one, Contributed module two, Custom module one, Locale test', 'Updates found');
+    $this->assertText('Updates for: Contributed module one, Contributed module two, Custom module one, Locale test', 'Updates found');
+    $this->assertText('Contributed module one (' . format_date($this->timestamp_now, 'html_date') . ')', 'Updates for Contrib module one');
+    $this->assertText('Contributed module two (' . format_date($this->timestamp_new, 'html_date') . ')', 'Updates for Contrib module two');
+
+    // Execute the translation update.
+    $this->drupalPost('admin/reports/translations', array(), t('Update translations'));
 
     // Check if the translation has been updated, using the status cache.
     $status = state()->get('locale.translation_status');
@@ -486,7 +495,7 @@ function testUpdateImportSourceLocal() {
 
     // Execute the translation update.
     $this->drupalGet('admin/reports/translations/check');
-    $this->drupalPost('admin/reports/translations', array(), t('Update'));
+    $this->drupalPost('admin/reports/translations', array(), t('Update translations'));
 
     // Check if the translation has been updated, using the status cache.
     $status = state()->get('locale.translation_status');
@@ -542,7 +551,7 @@ function testUpdateImportWithoutDirectory() {
 
     // Execute the translation update.
     $this->drupalGet('admin/reports/translations/check');
-    $this->drupalPost('admin/reports/translations', array(), t('Update'));
+    $this->drupalPost('admin/reports/translations', array(), t('Update translations'));
 
     // Check if the translation has been updated, using the status cache.
     $status = state()->get('locale.translation_status');
@@ -597,7 +606,7 @@ function testUpdateImportModeNonCustomized() {
 
     // Execute translation update.
     $this->drupalGet('admin/reports/translations/check');
-    $this->drupalPost('admin/reports/translations', array(), t('Update'));
+    $this->drupalPost('admin/reports/translations', array(), t('Update translations'));
 
     // Check whether existing translations have (not) been overwritten.
     $this->assertEqual(t('January', array(), array('langcode' => 'de')), 'Januar_customized', 'Translation of January');
@@ -635,7 +644,7 @@ function testUpdateImportModeNone() {
 
     // Execute translation update.
     $this->drupalGet('admin/reports/translations/check');
-    $this->drupalPost('admin/reports/translations', array(), t('Update'));
+    $this->drupalPost('admin/reports/translations', array(), t('Update translations'));
 
     // Check whether existing translations have (not) been overwritten.
     $this->assertTranslation('January', 'Januar_customized', 'de');
diff --git a/core/modules/locale/locale.admin.css b/core/modules/locale/locale.admin.css
index 2452608..3a632b0 100644
--- a/core/modules/locale/locale.admin.css
+++ b/core/modules/locale/locale.admin.css
@@ -47,3 +47,77 @@
 .locale-translate-edit-form table.changed {
   margin-top: 0;
 }
+
+/**
+ * Available translation updates page.
+ */
+#locale-translation-status table {
+  table-layout: fixed;
+}
+#locale-translation-status th.select-all {
+  width: 4%;
+}
+#locale-translation-status th.title {
+  width: 25%;
+}
+#locale-translation-status th.description {
+}
+#locale-translation-status td {
+  vertical-align: top;
+}
+#locale-translation-status .expand .inner {
+  background: transparent url(../../misc/menu-collapsed.png) left .6em no-repeat;
+  margin-left: -12px;
+  padding-left: 12px;
+}
+#locale-translation-status .expanded .expand .inner {
+  background: transparent url(../../misc/menu-expanded.png) left .6em no-repeat;
+}
+
+#locale-translation-status label {
+  color: #1d1d1d;
+  font-size: 1.15em;
+}
+#locale-translation-status .description {
+  cursor: pointer;
+}
+#locale-translation-status .description .inner {
+  color: #5c5c5b;
+  line-height: 20px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+#locale-translation-status .expanded .description .inner {
+  height: auto;
+  overflow: visible;
+  white-space: normal;
+}
+#locale-translation-status .expanded .description .text {
+  -webkit-hyphens: auto;
+  -moz-hyphens: auto;
+  hyphens: auto;
+}
+.js #locale-translation-status .description .inner {
+  height: 20px;
+}
+#locale-translation-status .expanded .description .inner {
+  height: auto;
+  overflow: visible;
+  white-space: normal;
+}
+#locale-translation-status .details {
+  padding: 5px 0;
+  max-width: 490px;
+  white-space: normal;
+  font-size: 0.9em;
+  color: #666;
+}
+@media screen and (max-width: 40em) {
+  #locale-translation-status th.title {
+    width: 20%;
+  }
+  #locale-translation-status th.status {
+    width: 40%;
+  }
+}
diff --git a/core/modules/locale/locale.admin.js b/core/modules/locale/locale.admin.js
index a9ded86..0f7357e 100644
--- a/core/modules/locale/locale.admin.js
+++ b/core/modules/locale/locale.admin.js
@@ -40,6 +40,41 @@ Drupal.behaviors.localeTranslateDirty = {
   }
 };
 
+/**
+ * Show/hide the description details on Available translation updates page.
+ */
+Drupal.behaviors.hideUpdateInformation = {
+  attach: function (context, settings) {
+    var $table = $('#locale-translation-status').once('expand-updates');
+    var effect = settings.hideUpdates;
+    if ($table.length) {
+      var $tbodies = $table.find('tbody');
+
+      // Open/close the description details by toggling a tr class.
+      $tbodies.on('click keydown', '.description', function (e) {
+        if (e.keyCode && (e.keyCode !== 13 && e.keyCode !== 32)) {
+          return;
+        }
+        e.preventDefault();
+        var $tr = $(this).closest('tr');
+
+        $tr.toggleClass('expanded');
+
+        // Change screen reader text.
+        $tr.find('.udpate-description-prefix').text(function () {
+          if ($tr.hasClass('expanded')) {
+            return Drupal.t('Hide description');
+          }
+          else {
+            return Drupal.t('Show description');
+          }
+        });
+      });
+    }
+    $table.find('.requirements, .links').hide();
+  }
+};
+
 $.extend(Drupal.theme, {
   localeTranslateChangedMarker: function () {
     return '<abbr class="warning ajax-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index 2745f55..ef53f5a 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -283,6 +283,70 @@ function locale_schema() {
 }
 
 /**
+ * Implements hook_requirements().
+ */
+function locale_requirements($phase) {
+  $requirements = array();
+  if ($phase == 'runtime') {
+    $available_updates = array();
+    $updates_not_found = array();
+    $languages = locale_translatable_language_list();
+
+    if ($languages) {
+      // Determine the status of the translation updates per lanuage.
+      $status = state()->get('locale.translation_status');
+      if ($status) {
+        foreach ($status as $project_id => $project) {
+          foreach ($project as $langcode => $project_info) {
+            if (!isset($project_info->type)) {
+              $updates_not_found[$langcode] = $languages[$langcode]->name;
+            }
+            elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) {
+              $available_updates[$langcode] = $languages[$langcode]->name;
+            }
+          }
+        }
+
+        if ($available_updates || $updates_not_found) {
+          if ($available_updates) {
+            $requirements['locale_translation'] = array(
+              'title' => 'Translation update status',
+              'value' => l(t('Updates available'), 'admin/reports/translations'),
+              'severity' => REQUIREMENT_WARNING,
+              'description' => t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => implode(', ', $available_updates), '@updates' => url('admin/reports/translations'))),
+            );
+          }
+          else {
+            $requirements['locale_translation'] = array(
+              'title' => 'Translation update status',
+              'value' => t('Updates not found'),
+              'severity' => REQUIREMENT_OK,
+              'description' => t('Updates not found for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => implode(', ', $updates_not_found), '@updates' => url('admin/reports/translations'))),
+            );
+          }
+        }
+        else {
+          $requirements['locale_translation'] = array(
+            'title' => 'Translation update status',
+            'value' => t('Up to date'),
+            'severity' => REQUIREMENT_OK,
+          );
+        }
+      }
+      else {
+        $requirements['locale_translation'] = array(
+          'title' => 'Translation update status',
+          'value' => l(t('Can not determine status'), 'admin/reports/translations'),
+          'severity' => REQUIREMENT_WARNING,
+          'description' => t('No translation status is available. See the <a href="@updates">Available translation updates</a> page for more information.', array('@updates' => url('admin/reports/translations'))),
+        );
+      }
+    }
+  }
+  return $requirements;
+}
+
+/**
  * @addtogroup updates-7.x-to-8.x
  * @{
  */
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index dac0557..5cdcf3d 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -227,7 +227,7 @@ function locale_menu() {
     'title' => 'Available translation updates',
     'description' => 'Get a status report about available interface translations for your installed modules and themes.',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('locale_translation_status_form'),
+    'page arguments' => array('locale_translation_status'),
     'access arguments' => array('translate interface'),
     'file' => 'locale.pages.inc',
   );
@@ -263,6 +263,14 @@ function locale_theme() {
       'render element' => 'form',
       'file' => 'locale.pages.inc',
     ),
+    'locale_translation_last_check' => array(
+      'variables' => array('last' => NULL),
+      'file' => 'locale.pages.inc',
+    ),
+    'locale_translation_update_info' => array(
+      'arguments' => array('updates' => array(), 'not_found' => array()),
+      'file' => 'locale.pages.inc',
+    ),
   );
 }
 
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index cf4edce..a0dad62 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -595,46 +595,130 @@ function locale_translate_settings_submit($form, &$form_state) {
  *
  * @see locale_menu()
  */
-function locale_translation_status_form($form, &$form_state) {
+function locale_translation_status($form, &$form_state) {
+  module_load_include('translation.inc', 'locale');
   module_load_include('compare.inc', 'locale');
+  $updates = $options = array();
+  $languages_update = $languages_not_found = array();
 
+  // @todo Calling locale_translation_build_projects() is an expensive way to
+  //   get a module name. In follow-up issue http://drupal.org/node/1842362
+  //   the project name will be stored to display use, like here.
+  $project_data = locale_translation_build_projects();
   $languages = locale_translatable_language_list();
+  $projects = locale_translation_get_projects();
   $status = state()->get('locale.translation_status');
 
-  if (!$languages) {
-    drupal_set_message(t('No translatable languages available. <a href="@add_lanuage">Add language</a> first.', array('@add_lanuage' => url('admin/config/regional/language'))), 'warning');
+  // Prepare information about projects which have available translation
+  // updates.
+  if ($languages && $status) {
+    foreach ($status as $project_id => $project) {
+      foreach ($project as $langcode => $project_info) {
+        // No translation file found for this project-language combination.
+        if (!isset($project_info->type)) {
+          $updates[$langcode]['not_found'][] = array(
+            'name' => $project_info->name == 'drupal' ? t('Drupal core') : $project_data[$project_info->name]->info['name'],
+            'version' => $project_info->version,
+            'info' => _locale_translation_status_debug_info($project_info),
+          );
+          $languages_not_found[$langcode] = $langcode;
+        }
+        // Translation update found for this project-language combination.
+        elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE ) {
+          $local = isset($project_info->files[LOCALE_TRANSLATION_LOCAL]) ? $project_info->files[LOCALE_TRANSLATION_LOCAL] : NULL;
+          $remote = isset($project_info->files[LOCALE_TRANSLATION_REMOTE]) ? $project_info->files[LOCALE_TRANSLATION_REMOTE] : NULL;
+          $recent = _locale_translation_source_compare($local, $remote) == LOCALE_TRANSLATION_SOURCE_COMPARE_LT ? $remote : $local;
+          $updates[$langcode]['updates'][] = array(
+            'name' => $project_data[$project_info->name]->info['name'],
+            'version' => $project_info->version,
+            'timestamp' => $recent->timestamp,
+          );
+          $languages_update[$langcode] = $langcode;
+        }
+      }
+    }
+    $languages_not_found = array_diff($languages_not_found, $languages_update);
+
+    // Build data options for the select table.
+    foreach($updates as $langcode => $update) {
+      $options[$langcode] = array(
+        'title' => check_plain($languages[$langcode]->name),
+        'status' => array('class' => array('description', 'expand', 'priority-low'), 'data' => theme('locale_translation_update_info', $update)),
+      );
+    }
+    // Sort the table data on language name.
+    uasort($options, 'drupal_sort_title');
   }
 
-  $last = state()->get('locale.translation_last_checked');
-  $markup = '<div class="locale checked">';
-  $markup .= $last ? t('Last checked: @time ago', array('@time' => format_interval(REQUEST_TIME - $last))) : t('Last checked: never');
-  $markup .= ' <span class="check-manually">(' . l(t('Check manually'), 'admin/reports/translations/check', array('query' => drupal_get_destination())) . ')</span>';
-  $markup .= "</div>\n";
+  $last_checked = state()->get('locale.translation_last_checked');
   $form['last_checked'] = array(
-    '#markup' => '<p>' . $markup . '</p>',
+    '#markup' => '<p>' . theme('locale_translation_last_check', array('last' => $last_checked)) . '</p>',
   );
 
-  $form['langcodes'] = array(
-    '#type' => 'value',
-    '#value' => drupal_map_assoc(array_keys($languages)),
+  $header = array(
+    'title' => array(
+      'data' => t('Language'),
+      'class' => array('title'),
+    ),
+    'status' => array(
+      'data' => t('Status'),
+      'class' => array('status', 'priority-low'),
+    ),
   );
 
-  $form['actions'] = array(
-    '#type' => 'actions'
-  );
-  $form['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Update')
+  if (!$languages) {
+    $empty = t('No translatable languages available. <a href="@add_language">Add a language</a> first.', array('@add_language' => url('admin/config/regional/language')));
+  }
+  elseif ($status) {
+    $empty = t('All translations up to date.');
+  }
+  else  {
+    $empty = t('No translation status available. <a href="@check">Check manually</a>.', array('@check' => url('admin/reports/translations/check')));
+  }
+
+  $form['languages'] = array(
+    '#type' => 'tableselect',
+    '#header' => $header,
+    '#options' => $options,
+    '#default_value' => $languages_update,
+    '#empty' => $empty,
+    '#js_select' => TRUE,
+    '#multiple' => TRUE,
+    '#required' => TRUE,
+    '#not_found' => $languages_not_found,
+    '#after_build' => array('locale_translation_language_table'),
   );
+
+  $form['#attached']['library'][] = array('locale', 'drupal.locale.admin');
+  $form['#attached']['css'] = array(drupal_get_path('module', 'locale') . '/locale.admin.css');
+
+  $form['actions'] = array('#type' => 'actions');
+  if ($languages_update) {
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Update translations'),
+    );
+  }
+
   return $form;
 }
 
 /**
+ * Form validation handler for locale_translation_status().
+ */
+function locale_translation_status_validate($form, &$form_state) {
+  // Check if a language has been selected. tableselect fails to do so.
+  if (!array_filter($form_state['values']['languages'])) {
+     form_set_error('', t('Select a language to update.'));
+  }
+}
+
+/**
  * Form submission handler for locale_translation_status().
  */
-function locale_translation_status_form_submit($form, &$form_state) {
+function locale_translation_status_submit($form, &$form_state) {
   module_load_include('fetch.inc', 'locale');
-  $langcodes = array_filter($form_state['values']['langcodes']);
+  $langcodes = array_filter($form_state['values']['languages']);
 
   // Set the translation import options. This determines if existing
   // translations will be overwritten by imported strings.
@@ -656,7 +740,74 @@ function locale_translation_status_form_submit($form, &$form_state) {
 }
 
 /**
- * Default theme function for translation edit form.
+ * Form element callback: After build changes to the language update table.
+ *
+ * Adds labels to the languages and removes checkboxes from languages which have
+ * no updates ane one or more translation files could not be found.
+ */
+function locale_translation_language_table($form_element) {
+  // Add labels to Language names.
+  foreach ($form_element['#options'] as $langcode => $option) {
+    $id = $form_element[$langcode]['#id'];
+    $title = $option['title'];
+    $form_element['#options'][$langcode]['title'] = '<label for="' . $form_element[$langcode]['#id'] . '" class="language-name">' . $title . '</label>';
+  }
+
+  // Remove checkboxes of languages without updates.
+  if ($form_element['#not_found']) {
+    foreach ($form_element['#not_found'] as $langcode) {
+      $form_element[$langcode] = array();
+    }
+  }
+  return $form_element;
+}
+
+/**
+ * Provides debug info when translation update were not found for a project.
+ *
+ * Translations files are being fetched either from Drupal translation server
+ * and local files or only from the local filesystem depending on the
+ * "Translation source" setting at admin/config/regional/translate/settings.
+ * This method will produce debug information including the respective path(s)
+ * based on this setting.
+ *
+ * Translations for development versions are never fetched, so the debug info
+ * for that is a fixed message.
+ *
+ * @param array $source
+ *   An array which is the project information of the source.
+ *
+ * @return string
+ *   The string which contains debug information.
+ */
+function _locale_translation_status_debug_info($source) {
+  $remote_path = isset($source->files['remote']->uri) ? $source->files['remote']->uri : '';
+  $local_path = isset($source->files['local']->uri) ? $source->files['local']->uri : '';
+
+  if (strpos($source->version, 'dev') !== FALSE) {
+    return t('No translation files are provided for development releases.');
+  }
+  if (locale_translation_use_remote_source() && $remote_path && $local_path) {
+    return t('File not found at %remote_path nor at %local_path', array(
+      '%remote_path' => $remote_path,
+      '%local_path' => $local_path,
+    ));
+  }
+  elseif ($local_path) {
+    return t('File not found at %local_path', array('%local_path' => $local_path));
+  }
+  return t('Translation file location could not be determined.');
+}
+
+/**
+ * Returns HTML for translation edit form.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - form: The form that contains the language information.
+ *
+ * @see locale_translate_edit_form()
+ * @ingroup themeable
  */
 function theme_locale_translate_edit_form_strings($variables) {
   $output = '';
@@ -689,3 +840,78 @@ function theme_locale_translate_edit_form_strings($variables) {
   $output .= theme('pager');
   return $output;
 }
+
+/**
+ * Returns HTML for translation status information per language.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - updates: The projects which have updates.
+ *   - not_found: The projects which updates are not found.
+ *
+ * @see locale_translation_status()
+ * @ingroup themeable
+ */
+function theme_locale_translation_update_info($variables) {
+  $description = $details = '';
+
+  // Build output for available updates.
+  if (isset($variables['updates'])) {
+    if ($variables['updates']) {
+      $releases = array();
+      foreach ($variables['updates'] as $update) {
+        $modules[] = $update['name'];
+        $releases[] = t('@module (@date)', array('@module' => $update['name'], '@date' => format_date($update['timestamp'], 'html_date')));
+      }
+    }
+    $description = '<span class="text">' . t('Updates for: @modules', array('@modules' => implode(', ', $modules))) . '</span>';
+    $details = theme('item_list', array('items' => $releases));
+  }
+
+  // Build output for updates not found.
+  if (isset($variables['not_found'])) {
+    if (empty($description)) {
+      $description = '<span class="text">' . format_plural(count($variables['not_found']), 'No updates found for 1 project', 'No updates found for @count projects') . '</span>';
+    }
+    if ($variables['not_found']) {
+      $releases = array();
+      foreach ($variables['not_found'] as $update) {
+        $version = $update['version'] ? $update['version'] : t('no version');
+        $releases[] = t('@module (@version).', array('@module' => $update['name'], '@version' => $version)) . ' ' . $update['info'];
+      }
+    }
+    if ($details) {
+      $details .= t('No updates found for:');
+    }
+    $details .= theme('item_list', array('items' => $releases));
+  }
+
+  $output = '<div class="inner" tabindex="0" role="button">';
+  $output .= '<span class="udpate-description-prefix element-invisible">Show description</span>' . $description;
+  $output .= $details ? '<div class="details">' . $details . '</div>' : '';
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * Returns HTML for the last time we checked for update data.
+ *
+ * In addition to properly formatting the given timestamp, this function also
+ * provides a "Check manually" link that refreshes the available update and
+ * redirects back to the same page.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - last: The timestamp when the site last checked for available updates.
+ *
+ * @see locale_translation_status()
+ * @ingroup themeable
+ */
+function theme_locale_translation_last_check($variables) {
+  $last = $variables['last'];
+  $output = '<div class="locale checked">';
+  $output .= $last ? t('Last checked: @time ago', array('@time' => format_interval(REQUEST_TIME - $last))) : t('Last checked: never');
+  $output .= ' <span class="check-manually">(' . l(t('Check manually'), 'admin/reports/translations/check', array('query' => drupal_get_destination())) . ')</span>';
+  $output .= "</div>\n";
+  return $output;
+}
diff --git a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
index f4f1972..98eb358 100644
--- a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
+++ b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module
@@ -4,3 +4,17 @@
  * @file
  * Simulates a custom module with a local po file.
  */
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * By default this modules is hidden but once enabled it behaves like a normal
+ * (not hidden) module. This hook implementation changes the .info data by
+ * setting the hidden status to FALSE.
+ */
+function locale_test_translate_system_info_alter(&$info, $file, $type) {
+  if ($file->name == 'locale_test_translate') {
+    // Don't hide the module.
+    $info['hidden'] = FALSE;
+  }
+}
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index c5a82a8..7782617 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -1006,23 +1006,29 @@ div.add-or-remove-shortcuts {
 #system-modules .fieldset-wrapper {
   padding: 0;
 }
-#system-modules table {
+#system-modules table,
+#locale-translation-status table {
   border: 0;
 }
 #system-modules tr.even,
-#system-modules tr.odd {
+#system-modules tr.odd,
+#locale-translation-status tr.even,
+#locale-translation-status tr.odd {
   background: #f3f4ee;
   border: 0;
   border-bottom: 10px solid #fff;
 }
-#system-modules tr td:last-child {
+#system-modules tr td:last-child,
+#locale-translation-status tr td:last-child {
   border: 0;
 }
-#system-modules table th {
+#system-modules table th,
+#locale-translation-status table th {
   border: 0;
   border-bottom: 10px solid #fff;
 }
-#system-modules .sticky-header th {
+#system-modules .sticky-header th,
+#locale-translation-status .sticky-header th {
   border: 0;
 }
 /* Recent content block */
