diff --git a/core/core.services.yml b/core/core.services.yml
index 966ed3d..912e141 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -671,9 +671,7 @@ services:
       - { name: string_translator, priority: 30 }
   string_translation:
     class: Drupal\Core\StringTranslation\TranslationManager
-    arguments: ['@language_manager', '@state']
-    calls:
-      - [initLanguageManager]
+    arguments: ['@language.default']
     tags:
       - { name: service_collector, tag: string_translator, call: addTranslator }
   database.replica:
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index b25d28c..449b9e0 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -346,11 +346,8 @@ function install_begin_request($class_loader, &$install_state) {
     ->register('language.default', 'Drupal\Core\Language\LanguageDefault')
     ->addArgument('%language.default_values%');
   $container
-    ->register('language_manager', 'Drupal\Core\Language\LanguageManager')
-    ->addArgument(new Reference('language.default'));
-  $container
     ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
-    ->addArgument(new Reference('language_manager'));
+    ->addArgument(new Reference('language.default'));
 
   // Register the stream wrapper manager.
   $container
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index 2fd1597..76b23d1 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -20,13 +20,6 @@ class LanguageManager implements LanguageManagerInterface {
   use DependencySerializationTrait;
 
   /**
-   * The string translation service.
-   *
-   * @var \Drupal\Core\StringTranslation\TranslationInterface
-   */
-  protected $translation;
-
-  /**
    * A static cache of translated language lists.
    *
    * Array of arrays to cache the result of self::getLanguages() keyed by the
@@ -59,22 +52,6 @@ public function __construct(LanguageDefault $default_language) {
   /**
    * {@inheritdoc}
    */
-  public function setTranslation(TranslationInterface $translation) {
-    $this->translation = $translation;
-  }
-
-  /**
-   * Translates a string to the current language or to a given language.
-   *
-   * @see \Drupal\Core\StringTranslation\TranslationInterface()
-   */
-  protected function t($string, array $args = array(), array $options = array()) {
-    return $this->translation ? $this->translation->translate($string, $args, $options) : SafeMarkup::format($string, $args);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function isMultilingual() {
     return FALSE;
   }
@@ -187,15 +164,15 @@ public function getLanguage($langcode) {
    */
   public function getLanguageName($langcode) {
     if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
-      return $this->t('None');
+      return new TranslationWrapper('None');
     }
     if ($language = $this->getLanguage($langcode)) {
       return $language->getName();
     }
     if (empty($langcode)) {
-      return $this->t('Unknown');
+      return new TranslationWrapper('Unknown');
     }
-    return $this->t('Unknown (@langcode)', array('@langcode' => $langcode));
+    return new TranslationWrapper('Unknown (@langcode)', array('@langcode' => $langcode));
   }
 
   /**
@@ -377,7 +354,6 @@ public function getConfigOverrideLanguage() {
     return $this->getCurrentLanguage();
   }
 
-
   /**
    * Filters the full list of languages based on the value of the flag.
    *
@@ -409,7 +385,7 @@ protected function filterLanguages(array $languages, $flags = LanguageInterface:
       $default = new Language(
         array(
           'id' => $defaultLanguage->getId(),
-          'name' => $this->t("Site's default language (@lang_name)",
+          'name' => new TranslationWrapper("Site's default language (@lang_name)",
             array('@lang_name' => $defaultLanguage->getName())),
           'direction' => $defaultLanguage->getDirection(),
           'weight' => $defaultLanguage->getWeight(),
diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
index b536a00..950fc69 100644
--- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -16,14 +16,6 @@
 interface LanguageManagerInterface {
 
   /**
-   * Injects the string translation service.
-   *
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
-   *   The string translation service.
-   */
-  public function setTranslation(TranslationInterface $translation);
-
-  /**
    * Returns whether or not the site has more than one language added.
    *
    * @return bool
diff --git a/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php b/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
index fe7befc..824ca30 100644
--- a/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
+++ b/core/lib/Drupal/Core/StringTranslation/StringTranslationTrait.php
@@ -70,12 +70,17 @@ protected function formatPluralTranslated($count, $translated, array $args = arr
   /**
    * Returns the number of plurals supported by a given language.
    *
-   * See the
-   * \Drupal\Core\StringTranslation\TranslationInterface::getNumberOfPlurals()
+   * See the \Drupal\locale\PluralFormulaInterface::getNumberOfPlurals()
    * documentation for details.
+   *
+   * @see \Drupal\locale\PluralFormulaInterface::getNumberOfPlurals()
    */
   protected function getNumberOfPlurals($langcode = NULL) {
-    return $this->getStringTranslation()->getNumberOfPlurals($langcode);
+    if (\Drupal::hasService('locale.plural.forumla')) {
+      return \Drupal::service('locale.plural.forumla')->getNumberOfPlurals($langcode);
+    }
+    // We assume 2 plurals if Locale's services are not available.
+    return 2;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
index 836ad0b..57b61e9 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
@@ -135,16 +135,4 @@ public function formatPlural($count, $singular, $plural, array $args = array(),
    */
   public function formatPluralTranslated($count, $translation, array $args = array(), array $options = array());
 
-   /**
-    * Returns the number of plurals supported by a given language.
-    *
-    * @param null|string $langcode
-    *   (optional) The language code. If not provided, the current language
-    *   will be used.
-    *
-    * @return int
-    *   Number of plural variants supported by the given language.
-    */
-   public function getNumberOfPlurals($langcode = NULL);
-
 }
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
index 5bf6a9d..b29dd7c 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
@@ -8,8 +8,7 @@
 namespace Drupal\Core\StringTranslation;
 
 use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Core\Language\LanguageManagerInterface;
-use Drupal\Core\State\StateInterface;
+use Drupal\Core\Language\LanguageDefault;
 use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
 
 /**
@@ -18,13 +17,6 @@
 class TranslationManager implements TranslationInterface, TranslatorInterface {
 
   /**
-   * The language manager.
-   *
-   * @var \Drupal\Core\Language\LanguageManagerInterface
-   */
-  protected $languageManager;
-
-  /**
    * An array of active translators keyed by priority.
    *
    * @var array
@@ -54,35 +46,13 @@ class TranslationManager implements TranslationInterface, TranslatorInterface {
   protected $defaultLangcode;
 
   /**
-   * The state service.
-   *
-   * @var \Drupal\Core\State\StateInterface
-   */
-  protected $state;
-
-  /**
    * Constructs a TranslationManager object.
    *
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   *   The language manager.
-   * @param \Drupal\Core\State\StateInterface $state
-   *   (optional) The state service.
+   * @param \Drupal\Core\Language\LanguageDefault $default_language
+   *   The default language.
    */
-  public function __construct(LanguageManagerInterface $language_manager, StateInterface $state = NULL) {
-    $this->languageManager = $language_manager;
-    $this->defaultLangcode = $language_manager->getDefaultLanguage()->getId();
-    $this->state = $state;
-  }
-
-  /**
-   * Initializes the injected language manager with the translation manager.
-   *
-   * This should be called right after instantiating the translation manager to
-   * make it available to the language manager without introducing a circular
-   * dependency.
-   */
-  public function initLanguageManager() {
-    $this->languageManager->setTranslation($this);
+  public function __construct(LanguageDefault $default_language) {
+    $this->defaultLangcode = $default_language->get()->getId();
   }
 
   /**
@@ -252,21 +222,4 @@ public function reset() {
     }
   }
 
-  /**
-   * @inheritdoc.
-   */
-  public function getNumberOfPlurals($langcode = NULL) {
-    // If the state service is not injected, we assume 2 plural variants are
-    // allowed. This may happen in the installer for simplicity. We also assume
-    // 2 plurals if there is no explicit information yet.
-    if (isset($this->state)) {
-      $langcode = $langcode ?: $this->languageManager->getCurrentLanguage()->getId();
-      $plural_formulas = $this->state->get('locale.translation.plurals') ?: array();
-      if (isset($plural_formulas[$langcode]['plurals'])) {
-        return $plural_formulas[$langcode]['plurals'];
-      }
-    }
-    return 2;
-  }
-
 }
diff --git a/core/modules/language/src/ConfigurableLanguageManager.php b/core/modules/language/src/ConfigurableLanguageManager.php
index d51692f..7159f4e 100644
--- a/core/modules/language/src/ConfigurableLanguageManager.php
+++ b/core/modules/language/src/ConfigurableLanguageManager.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageDefault;
 use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\StringTranslation\TranslationWrapper;
 use Drupal\Core\Url;
 use Drupal\language\Config\LanguageConfigFactoryOverrideInterface;
 use Drupal\language\Entity\ConfigurableLanguage;
@@ -469,7 +470,7 @@ public function getStandardLanguageListWithoutConfigured() {
         unset($predefined[$key]);
         continue;
       }
-      $predefined[$key] = $this->t($value[0]);
+      $predefined[$key] = new TranslationWrapper($value[0]);
     }
     asort($predefined);
     return $predefined;
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 7259d35..23a1947 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -276,8 +276,6 @@ function locale_translatable_language_list() {
 function locale_get_plural($count, $langcode = NULL) {
   $language_interface = \Drupal::languageManager()->getCurrentLanguage();
 
-  // Used to locally cache the plural formulas for all languages.
-  $plural_formulas = &drupal_static(__FUNCTION__, array());
   // Used to store precomputed plural indexes corresponding to numbers
   // individually for each language.
   $plural_indexes = &drupal_static(__FUNCTION__ . ':plurals', array());
@@ -286,18 +284,17 @@ function locale_get_plural($count, $langcode = NULL) {
 
   if (!isset($plural_indexes[$langcode][$count])) {
     // Retrieve and statically cache the plural formulas for all languages.
-    if (empty($plural_formulas)) {
-      $plural_formulas = \Drupal::state()->get('locale.translation.plurals') ?: array();
-    }
+    $plural_formulas = \Drupal::service('locale.plural.forumla')->getFormula($langcode);
+
     // If there is a plural formula for the language, evaluate it for the given
     // $count and statically cache the result for the combination of language
     // and count, since the result will always be identical.
-    if (!empty($plural_formulas[$langcode])) {
+    if (!empty($plural_formulas)) {
       // Plural formulas are stored as an array for 0-199. 100 is the highest
       // modulo used but storing 0-99 is not enough because below 100 we often
       // find exceptions (1, 2, etc).
       $index = $count > 199 ? 100 + ($count % 100) : $count;
-      $plural_indexes[$langcode][$count] = isset($plural_formulas[$langcode]['formula'][$index]) ? $plural_formulas[$langcode]['formula'][$index] : $plural_formulas[$langcode]['formula']['default'];
+      $plural_indexes[$langcode][$count] = isset($plural_formulas[$index]) ? $plural_formulas[$index] : $plural_formulas['default'];
     }
     // In case there is no plural formula for English (no imported translation
     // for English), use a default formula.
@@ -1272,9 +1269,9 @@ function _locale_rebuild_js($langcode = NULL) {
       'strings' => $translations,
     );
 
-    $locale_plurals = \Drupal::state()->get('locale.translation.plurals') ?: array();
-    if (!empty($locale_plurals[$language->getId()]['formula'])) {
-      $data['pluralFormula'] = $locale_plurals[$language->getId()]['formula'];
+    $locale_plurals = \Drupal::service('locale.plural.forumla')->getFormula($language->getId());
+    if ($locale_plurals) {
+      $data['pluralFormula'] = $locale_plurals;
     }
 
     $data = 'window.drupalTranslations = ' . Json::encode($data) . ';';
diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml
index 393866b..00c836f 100644
--- a/core/modules/locale/locale.services.yml
+++ b/core/modules/locale/locale.services.yml
@@ -14,6 +14,9 @@ services:
   locale.project:
     class: Drupal\locale\LocaleProjectStorage
     arguments: ['@keyvalue']
+  locale.plural.forumla:
+    class: Drupal\locale\PluralFormula
+    arguments: ['@language_manager', '@state']
   string_translator.locale.lookup:
     class: Drupal\locale\LocaleTranslation
     arguments: ['@locale.storage', '@cache.default', '@lock', '@config.factory', '@language_manager', '@request_stack']
diff --git a/core/modules/locale/src/PluralFormula.php b/core/modules/locale/src/PluralFormula.php
new file mode 100644
index 0000000..a783f4e
--- /dev/null
+++ b/core/modules/locale/src/PluralFormula.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\locale\PluralFormula.
+ */
+
+namespace Drupal\locale;
+
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\State\StateInterface;
+
+/**
+ * Manages the storage of plural formula per language in state.
+ *
+ * @see \Drupal\locale\PoDatabaseWriter::setHeader()
+ */
+class PluralFormula implements PluralFormulaInterface {
+
+  /**
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * @var \Drupal\Core\State\StateInterface
+   */
+  protected $state;
+
+  /**
+   * The plural formula and count keyed by langcode.
+   *
+   * For example the structure looks like this:
+   * @code
+   * [
+   *   'de' => [
+   *     'plurals' => 2,
+   *     'formula' => [
+   *       // @todo
+   *     ]
+   *   ],
+   * ]
+   * @endcode
+   * @var []
+   */
+  protected $formulae;
+
+  /**
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   * @param \Drupal\Core\State\StateInterface $state
+   */
+  public function __construct(LanguageManagerInterface $language_manager, StateInterface $state) {
+    $this->languageManager = $language_manager;
+    $this->state = $state;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPluralFormula($langcode, $plural_count, array $formula) {
+    // Ensure that the formulae are loaded.
+    $this->loadFormulae();
+
+    $this->formulae[$langcode] = [
+      'plurals' => $plural_count,
+      'formula' => $formula,
+    ];
+    $this->state->set('locale.translation.plurals', $this->formulae);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getNumberOfPlurals($langcode = NULL) {
+    // Ensure that the formulae are loaded.
+    $this->loadFormulae();
+
+    // We also 2 plurals if there is no explicit information yet.
+    $langcode = $langcode ?: $this->languageManager->getCurrentLanguage()->getId();
+
+    // We assume 2 plurals if there is no explicit information yet.
+    if (!isset($this->formulae[$langcode]['plurals'])) {
+      return 2;
+    }
+    return $this->formulae[$langcode]['plurals'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormula($langcode) {
+    $this->loadFormulae();
+    return isset($this->formulae[$langcode]['formula']) ? $this->formulae[$langcode]['formula'] : FALSE;
+  }
+
+  /**
+   * Loads the formulae and stores them on the object if not set.
+   *
+   * @return []
+   */
+  protected function loadFormulae() {
+    if (!isset($this->formulae)) {
+      $this->formulae = $this->state->get('locale.translation.plurals', []);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function reset() {
+    $this->formulae = NULL;
+    return $this;
+  }
+
+}
diff --git a/core/modules/locale/src/PluralFormulaInterface.php b/core/modules/locale/src/PluralFormulaInterface.php
new file mode 100644
index 0000000..fb7b1d3
--- /dev/null
+++ b/core/modules/locale/src/PluralFormulaInterface.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\locale\PluralFormulaInterface.
+ */
+
+namespace Drupal\locale;
+
+/**
+ * An interface for a service providing plural formulae.
+ */
+interface PluralFormulaInterface {
+
+  /**
+   * @param string $langcode
+   *   The language code to get the formula for.
+   * @param int $plural_count
+   *   The number of plural forms.
+   * @param array $formula
+   *   An array for formulas.
+   *
+   * @return self
+   *   The PluralFormula object.
+   */
+  public function setPluralFormula($langcode, $plural_count, array $formula);
+
+  /**
+   * Returns the number of plurals supported by a given language.
+   *
+   * @param null|string $langcode
+   *   (optional) The language code. If not provided, the current language
+   *   will be used.
+   *
+   * @return int
+   *   Number of plural variants supported by the given language.
+   */
+  public function getNumberOfPlurals($langcode = NULL);
+
+  /**
+   * Gets the plural formula for a langcode.
+   *
+   * @param string $langcode
+   *   The language code to get the formula for.
+   *
+   * @return array
+   *   An array for formulas.
+   */
+  public function getFormula($langcode);
+
+  /**
+   * Resets the static formulae cache.
+   *
+   * @return self
+   *   The PluralFormula object.
+   */
+  public function reset();
+
+}
diff --git a/core/modules/locale/src/PoDatabaseWriter.php b/core/modules/locale/src/PoDatabaseWriter.php
index 1d875ca..c21c91e 100644
--- a/core/modules/locale/src/PoDatabaseWriter.php
+++ b/core/modules/locale/src/PoDatabaseWriter.php
@@ -175,11 +175,7 @@ public function setHeader(PoHeader $header) {
       $plural = $header->getPluralForms();
       if (isset($plural) && $p = $header->parsePluralForms($plural)) {
         list($nplurals, $formula) = $p;
-        $locale_plurals[$langcode] = array(
-          'plurals' => $nplurals,
-          'formula' => $formula,
-        );
-        \Drupal::state()->set('locale.translation.plurals', $locale_plurals);
+        \Drupal::service('locale.plural.forumla')->setPluralFormula($langcode, $nplurals, $formula);
       }
     }
   }
diff --git a/core/modules/locale/src/Tests/LocaleImportFunctionalTest.php b/core/modules/locale/src/Tests/LocaleImportFunctionalTest.php
index 1c13517..6bec4a5 100644
--- a/core/modules/locale/src/Tests/LocaleImportFunctionalTest.php
+++ b/core/modules/locale/src/Tests/LocaleImportFunctionalTest.php
@@ -76,8 +76,8 @@ public function testStandalonePoFile() {
     $this->assertRaw(t('One translation file imported. %number translations were added, %update translations were updated and %delete translations were removed.', array('%number' => 8, '%update' => 0, '%delete' => 0)), 'The translation file was successfully imported.');
 
     // This import should have saved plural forms to have 2 variants.
-    $locale_plurals = \Drupal::state()->get('locale.translation.plurals') ?: array();
-    $this->assert($locale_plurals['fr']['plurals'] == 2, 'Plural number initialized.');
+    $locale_plurals = \Drupal::service('locale.plural.forumla')->getNumberOfPlurals('fr');
+    $this->assertEqual(2, $locale_plurals, 'Plural number initialized.');
 
     // Ensure we were redirected correctly.
     $this->assertUrl(\Drupal::url('locale.translate_page', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
@@ -151,8 +151,8 @@ public function testStandalonePoFile() {
     $this->assertText(t('No strings available.'), 'String not overwritten by imported string.');
 
     // This import should not have changed number of plural forms.
-    $locale_plurals = \Drupal::state()->get('locale.translation.plurals') ?: array();
-    $this->assert($locale_plurals['fr']['plurals'] == 2, 'Plural numbers untouched.');
+    $locale_plurals = \Drupal::service('locale.plural.forumla')->getNumberOfPlurals('fr');
+    $this->assertEqual(2, $locale_plurals, 'Plural numbers untouched.');
 
     // Try importing a .po file with overriding strings, and ensure existing
     // strings are overwritten.
@@ -172,8 +172,8 @@ public function testStandalonePoFile() {
     $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), 'String overwritten by imported string.');
     // This import should have changed number of plural forms.
-    $locale_plurals = \Drupal::state()->get('locale.translation.plurals') ?: array();
-    $this->assert($locale_plurals['fr']['plurals'] == 3, 'Plural numbers changed.');
+    $locale_plurals = \Drupal::service('locale.plural.forumla')->reset()->getNumberOfPlurals('fr');
+    $this->assertEqual(3, $locale_plurals, 'Plural numbers changed.');
 
     // Importing a .po file and mark its strings as customized strings.
     $this->importPoFile($this->getCustomPoFile(), array(
diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php
index 45423c5..d57a7aa 100644
--- a/core/modules/user/src/AccountForm.php
+++ b/core/modules/user/src/AccountForm.php
@@ -159,7 +159,7 @@ public function form(array $form, FormStateInterface $form_state) {
           '#type' => 'password',
           '#title' => $this->t('Current password'),
           '#size' => 25,
-          '#access' => !empty($protected_values),
+          '#access' => !$form_state->get('user_pass_reset'),
           '#description' => $current_pass_description,
           '#weight' => -5,
           // Do not let web browsers remember this password, since we are
diff --git a/core/modules/views/src/Tests/Plugin/NumericFormatPluralTest.php b/core/modules/views/src/Tests/Plugin/NumericFormatPluralTest.php
index 97b9bb2..d6aefa3 100644
--- a/core/modules/views/src/Tests/Plugin/NumericFormatPluralTest.php
+++ b/core/modules/views/src/Tests/Plugin/NumericFormatPluralTest.php
@@ -86,7 +86,7 @@ function testNumericFormatPlural() {
     $formula = 'nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);';
     $header = new PoHeader();
     list($nplurals, $formula) = $header->parsePluralForms($formula);
-    \Drupal::state()->set('locale.translation.plurals', ['sl' => ['plurals' => $nplurals, 'formula' => $formula]]);
+    \Drupal::service('locale.plural.forumla')->setPluralFormula('sl', $nplurals, $formula);
 
     // Change the view to Slovenian.
     $config = $this->config('views.view.numeric_test');
diff --git a/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationWrapperTest.php b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationWrapperTest.php
new file mode 100644
index 0000000..d9775da
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationWrapperTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\KernelTests\Core\StringTranslation\TranslationWrapperTest.
+ */
+
+namespace Drupal\KernelTests\Core\StringTranslation;
+
+use Drupal\Core\Site\Settings;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\language\Entity\ConfigurableLanguage;
+
+/**
+ * Tests the TranslationWrapper class.
+ *
+ * @group StringTranslation
+ */
+class TranslationWrapperTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'language'
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    ConfigurableLanguage::createFromLangcode('de')->save();
+  }
+
+  /**
+   * Tests that TranslationWrappers can be compared.
+   */
+  public function testComparison() {
+    $this->rebootAndPrepareSettings();
+    $a = \Drupal::service('string_translation')->translate('Example @number', ['@number' => 42], ['langcode' => 'de']);
+
+    $this->rebootAndPrepareSettings();
+    $b = \Drupal::service('string_translation')->translate('Example @number', ['@number' => 42], ['langcode' => 'de']);
+    $c = \Drupal::service('string_translation')->translate('Example @number', ['@number' => 43], ['langcode' => 'de']);
+    $d = \Drupal::service('string_translation')->translate('Example @number', ['@number' => 42], ['langcode' => 'en']);
+
+    // The two objects have the same settings so == comparison will work.
+    $this->assertEquals($a, $b);
+    // The two objects are not the same object.
+    $this->assertNotSame($a, $b);
+    // TranslationWrappers which have different settings are not equal.
+    $this->assertNotEquals($a, $c);
+    $this->assertNotEquals($a, $d);
+  }
+
+  /**
+   * Reboots the kernel to set custom translations in Settings.
+   */
+  protected function rebootAndPrepareSettings() {
+    // Reboot the container so that difference services are injected and the new
+    // settings are picked.
+    $kernel = $this->container->get('kernel');
+    $kernel->shutdown();
+    $kernel->boot();
+    $settings = Settings::getAll();
+    $settings['locale_custom_strings_de'] = ['' => ['Example @number' => 'Example @number translated']];
+    // Recreate the settings static.
+    new Settings($settings);
+  }
+
+}
