diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareUnitTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareUnitTest.php
new file mode 100644
index 0000000..cee8439
--- /dev/null
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareUnitTest.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\locale\Tests\LocaleCompareUnitTestCase.
+ */
+
+namespace Drupal\locale\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests for comparing existing translation with available translations.
+ */
+class LocaleCompareUnitTest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Locale Compare',
+      'description' => 'Test handling of translation comparison.',
+      'group' => 'Locale',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('locale', 'locale_test'));
+
+    // Create Article node type.
+    $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+
+    // Create and login user.
+    $admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages', 'create article content'));
+    $this->drupalLogin($admin_user);
+  }
+
+  /**
+   * Functional tests for localizing date formats.
+   */
+  function testLocaleCompare() {
+    module_load_include('compare.inc', 'locale');
+    variable_set('locale_check_disabled', 1);
+
+
+    // Check if hidden modules are not included.
+    $projects = locale_project_list();
+    $this->assertFalse(isset($projects['locale_test']), t('Hidden module not found'));
+
+    // Make the test module look like a normale custom module. i.e. the module
+    // is not hidden. This variable is used in locale_test_system_info_alter to
+    // modify the project info of the locale_test module.
+    variable_set('locale_test_system_info_alter', TRUE);
+
+    // Check if interface translation data is collected from .info file.
+    variable_set('locale_check_disabled', 1);
+    drupal_static_reset('locale_project_list');
+    $projects = locale_project_list();
+    $this->assertEqual($projects['locale_test']['info']['interface translation url'], 'http://locale_example.com/files/translations/l10n_server.xml', t('%key found in project info.', array('%key' => 'interface translation url')));
+    $this->assertEqual($projects['locale_test']['info']['interface translation pattern'], 'http://locale_example.com/files/translations/%core/%project/%project-%release.%language.po', t('%key found in project info.', array('%key' => 'interface translation pattern')));
+    $this->assertEqual($projects['locale_test']['name'] , 'locale_test', t('%key found in project info.', array('%key' => 'interface translation project')));
+
+    // Check if disabled modules are detected.
+    // @todo A real disabled module would be better. But if no second
+    // locale test module is available, this will do.
+    variable_set('locale_test_disable_locale_test', TRUE);
+    drupal_static('locale_project_list', array(), TRUE);
+    $projects = locale_project_list();
+    $this->assertTrue(isset($projects['locale_test']), t('Disabled module found'));
+    variable_del('locale_test_disable_locale_test');
+
+    variable_del('locale_test_system_info_alter');
+  }
+
+}
diff --git a/core/modules/locale/locale.api.php b/core/modules/locale/locale.api.php
new file mode 100644
index 0000000..50f6fb6
--- /dev/null
+++ b/core/modules/locale/locale.api.php
@@ -0,0 +1,10 @@
+<?php
+
+/**
+ * @todo
+ *
+ * @see locale_project_list().
+ */
+function hook_locale_projects_alter(&$projects) {
+  // @todo
+}
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
new file mode 100644
index 0000000..8ffc66e
--- /dev/null
+++ b/core/modules/locale/locale.compare.inc
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * @file
+ * @todo
+ */
+
+/**
+ * Default update server, filename and URL.
+ * @see locale_default_translation_server().
+ */
+define('LOCALE_DEFAULT_SERVER', 'localize.drupal.org');
+define('LOCALE_DEFAULT_SERVER_URL', 'http://localize.drupal.org/l10n_server.xml');
+define('LOCALE_DEFAULT_PATTERN', 'http://ftp.drupal.org/files/translations/%core/%project/%project-%release.%language.po');
+
+/**
+ * @todo
+ * Based on l10n_update_project_list().
+ */
+function locale_project_list() {
+  // @todo Can/should we cache this data?
+  $projects = &drupal_static(__FUNCTION__, array());
+  if (empty($projects)) {
+    module_load_include('compare.inc', 'update');
+    $projects = array();
+
+    $additional_whitelist = array(
+      'interface translation server',
+      'interface translation url',
+      'interface translation pattern',
+      'interface translation project',
+    );
+    $module_data = _locale_prepare_project_list($foo = system_rebuild_module_data());
+    $theme_data = _locale_prepare_project_list(system_rebuild_theme_data());
+    update_process_info_list($projects, $module_data, 'module', TRUE, $additional_whitelist);
+    update_process_info_list($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
+    if (variable_get('locale_check_disabled', 0)) {
+      update_process_info_list($projects, $module_data, 'module', FALSE, $additional_whitelist);
+      update_process_info_list($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
+    }
+
+    // Allow other modules to alter projects before fetching and comparing.
+    drupal_alter('locale_projects', $projects);
+  }
+  return $projects;
+}
+
+/**
+ * Prepare module and theme data.
+ * @todo
+ */
+function _locale_prepare_project_list($data) {
+  foreach ($data as $name => $file) {
+    // @todo Do we need to add hidden projects for interface translation?
+    //       Hidden projects are mainly used in automated tests.
+
+    // Include interface translation projects.
+    // Custom modules can bring their own gettext translation file.
+    // To enable import of this file the module must define
+    // 'interface translation project = myproject' in its .info file.
+    // To allow update_process_info_list() to identify this as a project
+    // the 'project' property is filled with the 'interface translation project'
+    // value.
+    if (isset($file->info['interface translation project'])) {
+      $data[$name]->info['project'] = $file->info['interface translation project'];
+    }
+  }
+  return $data;
+}
+
+/**
+ * @todo
+ * based on l10n_update_default_server().
+ */
+function locale_default_translation_server() {
+  return array(
+    // @todo Review the naming!
+    'name' => variable_get('locale_default_server', LOCALE_DEFAULT_SERVER),
+    'server_url' => variable_get('locale_default_server_url', LOCALE_DEFAULT_SERVER_URL),
+    'update_url' => variable_get('locale_default_pattern', LOCALE_DEFAULT_PATTERN),
+  );
+}
diff --git a/core/modules/locale/locale.info b/core/modules/locale/locale.info
index e0749db..b4c46ca 100644
--- a/core/modules/locale/locale.info
+++ b/core/modules/locale/locale.info
@@ -4,3 +4,4 @@ package = Core
 version = VERSION
 core = 8.x
 dependencies[] = language
+dependencies[] = update
diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.info b/core/modules/locale/tests/modules/locale_test/locale_test.info
new file mode 100644
index 0000000..a54a775
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test/locale_test.info
@@ -0,0 +1,12 @@
+name = Locale test
+description = Support module for locale module testing.
+package = Testing
+version = VERSION
+core = 8.x
+hidden = TRUE
+
+; Definitions for interface translations.
+interface translation server = http://locale_example.com
+interface translation url = http://locale_example.com/files/translations/l10n_server.xml
+interface translation pattern = http://locale_example.com/files/translations/%core/%project/%project-%release.%language.po
+interface translation project = locale_test
\ No newline at end of file
diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.module b/core/modules/locale/tests/modules/locale_test/locale_test.module
new file mode 100644
index 0000000..6a72393
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test/locale_test.module
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * Implements hook_system_info_alter().
+ */
+function locale_test_system_info_alter(&$info, $file, $type) {
+  // Only modify the system info if required.
+  // By default the locale_test module is hidden and has a project specified.
+  // To test the module detection proces by locale_project_list() we need a
+  // custom module to be non-hidden.
+  if (!variable_get('locale_test_system_info_alter', FALSE)) {
+    return;
+  }
+
+  // Make the locale_test module appear as not-disabled.
+  if ($file->name == 'locale_test') {
+    $info['hidden'] = FALSE;
+  }
+
+  // Mark the locale_test module as disabled.
+  if (variable_get('locale_test_disable_locale_test', FALSE)) {
+    $info['project_status'] = FALSE;
+  }
+}
