diff --git a/core/modules/locale/lib/Drupal/locale/LocaleProjectStorage.php b/core/modules/locale/lib/Drupal/locale/LocaleProjectStorage.php
new file mode 100644
index 0000000..a0282eb
--- /dev/null
+++ b/core/modules/locale/lib/Drupal/locale/LocaleProjectStorage.php
@@ -0,0 +1,140 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\locale\ProjectStorage.
+ */
+
+namespace Drupal\Core\KeyValueStore;
+
+/**
+ * Provides the locale project storage system using a key value store.
+ */
+class LocaleProjectStorage {
+
+  /**
+   * The key value store to use.
+   *
+   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
+   */
+  protected $keyValueStore;
+
+  /**
+   * Static state cache.
+   *
+   * @var array
+   */
+  protected $cache = array();
+
+  /**
+   * Constructs a State object.
+   *
+   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
+   *   The key value store to use.
+   */
+  function __construct(KeyValueFactoryInterface $key_value_factory) {
+    $this->keyValueStore = $key_value_factory->get('locale.project');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($key, $default = NULL) {
+    $values = $this->getMultiple(array($key));
+    return isset($values[$key]) ? $values[$key] : $default;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getMultiple(array $keys) {
+    $values = array();
+    $load = array();
+    foreach ($keys as $key) {
+      // Check if we have a value in the cache.
+      if (isset($this->cache[$key])) {
+        $values[$key] = $this->cache[$key];
+      }
+      // Load the value if we don't have an explicit NULL value.
+      elseif (!array_key_exists($key, $this->cache)) {
+        $load[] = $key;
+      }
+    }
+
+    if ($load) {
+      $loaded_values = $this->keyValueStore->getMultiple($load);
+      foreach ($load as $key) {
+        // If we find a value, even one that is NULL, add it to the cache and
+        // return it.
+        if (isset($loaded_values[$key]) || array_key_exists($key, $loaded_values)) {
+          $values[$key] = $loaded_values[$key];
+          $this->cache[$key] = $loaded_values[$key];
+        }
+        else {
+          $this->cache[$key] = NULL;
+        }
+      }
+    }
+
+    return $values;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function set($key, $value) {
+    $this->cache[$key] = $value;
+    $this->keyValueStore->set($key, $value);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setMultiple(array $data) {
+    foreach ($data as $key => $value) {
+      $this->cache[$key] = $value;
+    }
+    $this->keyValueStore->setMultiple($data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete($key) {
+    $this->deleteMultiple(array($key));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteMultiple(array $keys) {
+    foreach ($keys as $key) {
+      unset($this->cache[$key]);
+    }
+    $this->keyValueStore->deleteMultiple($keys);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resetCache() {
+    $this->cache = array();
+  }
+
+  public function deleteAll() {
+    $this->keyValueStore->deleteAll();
+  }
+
+  public function disableAll() {
+    $projects = $this->keyValueStore->getAll();
+    array_walk($projects, function($project){
+      $project['status'] = 0;
+    });
+    $this->keyValueStore->setMultiple($projects);
+  }
+
+  public function count() {
+    return count($this->keyValueStore->getAll());
+  }
+
+}
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
index dad67a8..f27001d 100644
--- a/core/modules/locale/locale.compare.inc
+++ b/core/modules/locale/locale.compare.inc
@@ -19,9 +19,7 @@
  * Clear the project data table.
  */
 function locale_translation_flush_projects() {
-  // Followup issue: http://drupal.org/node/1842362
-  // Replace {locale_project} table by \Drupal::state() variable(s).
-  db_truncate('locale_project')->execute();
+  Drupal::service('locale.project')->deleteAll();
 }
 
 /**
@@ -55,11 +53,7 @@ function locale_translation_build_projects() {
   $projects = locale_translation_project_list();
 
   // Mark all previous projects as disabled and store new project data.
-  db_update('locale_project')
-    ->fields(array(
-      'status' => 0,
-    ))
-    ->execute();
+  \Drupal::service('locale.project')->disableAll();
 
   $default_server = locale_translation_default_translation_server();
 
@@ -102,20 +96,11 @@ function locale_translation_build_projects() {
     $projects[$name] = $project;
 
     // Create or update the project record.
-    db_merge('locale_project')
-      ->key('name', $project->name)
-      ->fields(array(
-        'name' => $project->name,
-        'project_type' => $project->project_type,
-        'core' => $project->core,
-        'version' => $project->version,
-        'server_pattern' => $project->server_pattern,
-        'status' => $project->status,
-      ))
-      ->execute();
+    $data['name'] = $name;
+    \Drupal::service('locale.project')->set($project->name, $data);
 
-      // Invalidate the cache of translatable projects.
-      locale_translation_clear_cache_projects();
+    // Invalidate the cache of translatable projects.
+    locale_translation_clear_cache_projects();
   }
   return $projects;
 }
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index c62c842..3392959 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -228,55 +228,6 @@ function locale_schema() {
     ),
     'primary key' => array('project', 'langcode'),
   );
-
-  $schema['locale_project'] = array(
-    'description' => 'Translation status information for projects and server data.',
-    'fields' => array(
-      'name' => array(
-        'description' => 'A unique short name to identify the project.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
-      'project_type' => array(
-        'description' => 'Project type: core, module, or theme.',
-        'type' => 'varchar',
-        'length' => 15,
-        'not null' => TRUE,
-      ),
-      'core' => array(
-        // http://drupal.org/node/542202#core has an example.
-        'description' => 'Core compatibility string for this project, for example: 8.x',
-        'type' => 'varchar',
-        'length' => 4,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'version' => array(
-        // http://drupal.org/node/467026 has examples.
-        'description' => 'The version release of the project, for example: 8.x-2.1 or 8.x-1.0-dev',
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'server_pattern' => array(
-        'description' => 'Pattern of path and name of the gettext file at the translation server.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'status' => array(
-        // locale.compare.inc gives possible values for status.
-        'description' => 'The status of the project. Possible values are: 1 = enabled, 0 = disabled.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 1,
-      ),
-    ),
-    'primary key' => array('name'),
-  );
   return $schema;
 }
 
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 79bf982..821319e 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -519,9 +519,7 @@ function locale_system_remove($components) {
       // Remove translatable projects.
       // Followup issue http://drupal.org/node/1842362 to replace the
       // {locale_project} table. Then change this to a function call.
-      db_delete('locale_project')
-        ->condition('name', $list)
-        ->execute();
+      \Drupal::service('locale.project')->deleteMultiple($list);
 
       // Clear the translation status.
       locale_translation_status_delete_projects($list);
diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml
index 85ee070..3af4b34 100644
--- a/core/modules/locale/locale.services.yml
+++ b/core/modules/locale/locale.services.yml
@@ -10,6 +10,9 @@ services:
   locale.storage:
     class: Drupal\locale\StringDatabaseStorage
     arguments: ['@database']
+  locale.project:
+    class: Drupal\locale\LocaleProjectStorage
+    arguments: ['@keyvalue']
   string_translator.locale.lookup:
     class: Drupal\locale\LocaleTranslation
     arguments: ['@locale.storage', '@cache.cache', '@lock', '@config.factory', '@language_manager']
diff --git a/core/modules/locale/locale.translation.inc b/core/modules/locale/locale.translation.inc
index fab2a21..7298364 100644
--- a/core/modules/locale/locale.translation.inc
+++ b/core/modules/locale/locale.translation.inc
@@ -64,11 +64,10 @@ function locale_translation_get_projects($project_names = array()) {
       // data if none are found.
       locale_translation_build_projects();
     }
-    $result = db_query('SELECT name, project_type, core, version, server_pattern, status FROM {locale_project}');
-
-    foreach ($result as $project) {
-      $projects[$project->name] = $project;
-    }
+    $projects = \Drupal::service('locale.project')->getAll();
+    array_walk($projects, function(&$project) {
+      $project = (object) $project;
+    });
   }
 
   // Return the requested project names or all projects.
@@ -326,13 +325,17 @@ function locale_cron_fill_queue() {
 
   // Determine which project+language should be updated.
   $last = REQUEST_TIME - $config->get('translation.update_interval_days') * 3600 * 24;
-  $query = db_select('locale_file', 'f');
-  $query->join('locale_project', 'p', 'p.name = f.project');
-  $query->condition('f.last_checked', $last, '<');
-  $query->fields('f', array('project', 'langcode'));
-  // Only currently installed / enabled components should be checked for.
-  $query->condition('p.status', 1);
-  $files = $query->execute()->fetchAll();
+  $projects = \Drupal::service('locale.project')->getAll();
+  $projects = array_filter($projects, function($project) {
+    return $project['status'] == 1;
+  });
+  $files = db_select('locale_file', 'f')
+    ->condition('f.project', array_keys($projects))
+    ->condition('f.last_checked', $last, '<')
+    ->fields('f', array('project', 'langcode'))
+    // Only currently installed / enabled components should be checked for.
+    ->condition('p.status', 1)
+    ->execute()->fetchAll();
   foreach ($files as $file) {
     $updates[$file->project][] = $file->langcode;
 
