diff --git a/automatic_updates.module b/automatic_updates.module
index 42d886df60ea0b595b9b4d68d240a24cf7d20c06..c602db75cf9a40a5d13e96fed820317ea4703ac2 100644
--- a/automatic_updates.module
+++ b/automatic_updates.module
@@ -38,15 +38,20 @@ function automatic_updates_help($route_name, RouteMatchInterface $route_match) {
  * Implements hook_mail().
  */
 function automatic_updates_mail(string $key, array &$message, array $params): void {
+  // Explicitly pass the language code to all translated strings.
+  $options = [
+    'langcode' => $message['langcode'],
+  ];
+
   if ($key === 'cron_successful') {
-    $message['subject'] = t("Drupal core was successfully updated");
-    $message['body'][] = t('Congratulations!');
+    $message['subject'] = t("Drupal core was successfully updated", [], $options);
+    $message['body'][] = t('Congratulations!', [], $options);
     $message['body'][] = t('Drupal core was automatically updated from @previous_version to @updated_version.', [
       '@previous_version' => $params['previous_version'],
       '@updated_version' => $params['updated_version'],
-    ]);
-    $message['body'][] = t('This e-mail was sent by the Automatic Updates module. Unattended updates are not yet fully supported.');
-    $message['body'][] = t('If you are using this feature in production, it is strongly recommended for you to visit your site and ensure that everything still looks good.');
+    ], $options);
+    $message['body'][] = t('This e-mail was sent by the Automatic Updates module. Unattended updates are not yet fully supported.', [], $options);
+    $message['body'][] = t('If you are using this feature in production, it is strongly recommended for you to visit your site and ensure that everything still looks good.', [], $options);
   }
 }
 
diff --git a/src/CronUpdater.php b/src/CronUpdater.php
index 538e0c9bff48c1e180629432915e287d181d01df..23f6183eefbafad478fe086f3d33fd55f788b178 100644
--- a/src/CronUpdater.php
+++ b/src/CronUpdater.php
@@ -278,7 +278,7 @@ class CronUpdater extends Updater {
       $recipients = $this->configFactory->get('update.settings')
         ->get('notification.emails');
       foreach ($recipients as $recipient) {
-        $this->mailManager->mail('automatic_updates', 'cron_successful', $recipient, $this->languageManager->getDefaultLanguage()->getId(), $mail_params);
+        $this->mailManager->mail('automatic_updates', 'cron_successful', $recipient, $this->getEmailLangcode($recipient), $mail_params);
       }
     }
     catch (\Throwable $e) {
@@ -299,6 +299,23 @@ class CronUpdater extends Updater {
     return new Response();
   }
 
+  /**
+   * Retrieves preferred language to send email.
+   *
+   * @param string $recipient
+   *   The email address of the recipient.
+   *
+   * @return string
+   *   The preferred language of the recipient.
+   */
+  protected function getEmailLangcode(string $recipient): string {
+    $user = user_load_by_mail($recipient);
+    if ($user) {
+      return $user->getPreferredLangcode();
+    }
+    return $this->languageManager->getDefaultLanguage()->getId();
+  }
+
   /**
    * Gets the cron update mode.
    *
diff --git a/tests/modules/automatic_updates_test/automatic_updates_test.module b/tests/modules/automatic_updates_test/automatic_updates_test.module
new file mode 100644
index 0000000000000000000000000000000000000000..bd140ddb95a993b7e4547b45fad71232f5e65f5a
--- /dev/null
+++ b/tests/modules/automatic_updates_test/automatic_updates_test.module
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains hook implementations for testing Automatic Updates.
+ */
+
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Implements hook_mail_alter().
+ */
+function automatic_updates_test_mail_alter(array &$message): void {
+  if (str_starts_with($message['id'], 'automatic_updates_')) {
+    $line_langcodes = [];
+
+    // Get the langcode of every translated line in the mssage, including the
+    // subject line.
+    $lines = array_merge($message['body'], [
+      $message['subject'],
+    ]);
+    foreach ($lines as $line) {
+      if (!($line instanceof TranslatableMarkup)) {
+        // All lines need to be translated.
+        return;
+      }
+      $line_langcodes[] = $line->getOption('langcode');
+    }
+    $message['line_langcodes'] = array_unique($line_langcodes);
+  }
+}
diff --git a/tests/src/Kernel/CronUpdaterTest.php b/tests/src/Kernel/CronUpdaterTest.php
index 96373d3946ab12af9e06f4295f3b9c02cd1e4faf..c0e4c0c8c67e0a12210a214610756fb33261c483 100644
--- a/tests/src/Kernel/CronUpdaterTest.php
+++ b/tests/src/Kernel/CronUpdaterTest.php
@@ -19,6 +19,7 @@ use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Exception\StageValidationException;
 use Drupal\package_manager\ValidationResult;
 use Drupal\Tests\package_manager\Traits\PackageManagerBypassTestTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
 use Drupal\update\UpdateSettingsForm;
 use Psr\Log\Test\TestLogger;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -33,6 +34,7 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
 
   use AssertMailTrait;
   use PackageManagerBypassTestTrait;
+  use UserCreationTrait;
 
   /**
    * {@inheritdoc}
@@ -60,6 +62,8 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
     $this->container->get('logger.factory')
       ->get('automatic_updates')
       ->addLogger($this->logger);
+    $this->installEntitySchema('user');
+    $this->installSchema('user', ['users_data']);
   }
 
   /**
@@ -348,18 +352,48 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
    * Tests that user 1 is emailed when an unattended update succeeds.
    */
   public function testEmailOnSuccess(): void {
+    $default_language = $this->container->get('language_manager')
+      ->getDefaultLanguage()
+      ->getId();
+    $this->assertNotSame('fr', $default_language);
+
+    $account = $this->createUser([], NULL, FALSE, [
+      'preferred_langcode' => 'fr',
+    ]);
+
+    $recipients = [
+      'emissary@deep.space',
+      $account->getEmail(),
+    ];
+    $languages = [
+      $default_language,
+      $account->getPreferredLangcode(),
+    ];
+
     $this->config('update.settings')
-      ->set('notification.emails', [
-        'emissary@deep.space',
-      ])
+      ->set('notification.emails', $recipients)
       ->save();
 
     $this->container->get('cron')->run();
 
-    // Check that we actually sent a success email to the right person.
-    $this->assertMail('to', 'emissary@deep.space');
-    $this->assertMail('subject', "Drupal core was successfully updated");
-    $this->assertMailString('body', "Congratulations!\n\nDrupal core was automatically updated from 9.8.0 to 9.8.1.\n", 1);
+    // Ensure we sent a success message to all recipients.
+    $sent_messages = $this->getMails([
+      'subject' => "Drupal core was successfully updated",
+    ]);
+    $this->assertSame(count($recipients), count($sent_messages));
+    // Ensure the messages had the correct body text, and were sent to the right
+    // people.
+    foreach ($sent_messages as $i => $message) {
+      $this->assertSame($message['to'], $recipients[$i]);
+      $this->assertStringStartsWith("Congratulations!\n\nDrupal core was automatically updated from 9.8.0 to 9.8.1.\n", $message['body']);
+      // The message, and every line in it, should have been sent in the
+      // expected language.
+      $langcode = $message['langcode'];
+      $this->assertSame($langcode, $languages[$i]);
+      // @see automatic_updates_test_mail_alter()
+      $this->assertArrayHasKey('line_langcodes', $message);
+      $this->assertSame([$langcode], $message['line_langcodes']);
+    }
   }
 
 }