diff --git a/src/Entity/ExternalEntity.php b/src/Entity/ExternalEntity.php
index ca917dbdb07a94279e072a5213f1daa39030010b..46a3e8774fa327f4d606972eabf571c14109a718 100644
--- a/src/Entity/ExternalEntity.php
+++ b/src/Entity/ExternalEntity.php
@@ -127,6 +127,7 @@ class ExternalEntity extends ContentEntityBase implements ExternalEntityInterfac
         'type' => 'string',
         'label' => 'hidden',
       ])
+      ->setTranslatable(TRUE)
       ->setDisplayConfigurable('view', TRUE)
       ->setDisplayOptions('form', [
         'type' => 'string_textfield',
diff --git a/src/ExternalEntityStorage.php b/src/ExternalEntityStorage.php
index 144dceb857dfb9e9ee4dce926785815cb9b5abe2..c56b95257e935ce834e20330521fc41d8a76ace5 100644
--- a/src/ExternalEntityStorage.php
+++ b/src/ExternalEntityStorage.php
@@ -106,6 +106,14 @@ class ExternalEntityStorage extends ContentEntityStorageBase implements External
    */
   protected $xnttIdFieldName;
 
+  /**
+   * Prefix to detect translation data in remote source raw data.
+   *
+   * If found the trailing langcode after the prefix is used to populate an
+   * entity translation.
+   */
+  public const EXTERNAL_ENTITY_TRANSLATION_SUB_FIELD_PREFIX = '__external_entity_translation__';
+
   /**
    * Constructs a new ExternalEntityStorage object.
    *
@@ -717,6 +725,24 @@ class ExternalEntityStorage extends ContentEntityStorageBase implements External
       catch (EntityStorageException $exception) {
         DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '10.1.0', fn() => Error::logException(\Drupal::logger('external_entities'), $exception), fn() => watchdog_exception('external_entities', $exception));
       }
+
+      // Check if there are translation data available.
+      foreach ($all_raw_data[$id] as $key => $raw_translation_data) {
+        if (str_starts_with($key, self::EXTERNAL_ENTITY_TRANSLATION_SUB_FIELD_PREFIX)) {
+          try {
+            $langcode = str_replace(self::EXTERNAL_ENTITY_TRANSLATION_SUB_FIELD_PREFIX, '', $key);
+            $entity_translation_data = $this->extractEntityValuesFromRawData($raw_translation_data[$id]);
+            $entities[$id]->addTranslation($langcode, $entity_translation_data);
+          } catch (\Throwable $exception) {
+            // Don't completely fail if a translation can't be handled.
+            $this->logger->error(
+              'Error while mapping translation data for external entity @entity_id: @message',
+              ['@entity_id' => $id, '@message' => $exception->getMessage()]
+            );
+          }
+        }
+      }
+
       $entities[$id]->enforceIsNew(FALSE);
     }
 
diff --git a/src/Plugin/ExternalEntities/DataAggregator/GroupAggregator.php b/src/Plugin/ExternalEntities/DataAggregator/GroupAggregator.php
index cc8f624258b0f2ae48922280bb04c5ae55bc42b3..d21bdc4e9f8fc7e500321cffe89e4365e53f5cfe 100644
--- a/src/Plugin/ExternalEntities/DataAggregator/GroupAggregator.php
+++ b/src/Plugin/ExternalEntities/DataAggregator/GroupAggregator.php
@@ -640,7 +640,7 @@ class GroupAggregator extends DataAggregatorBase implements DataAggregatorInterf
       // matching ids which is given by $client_ids values.
       // Sets default merge behavior.
       $config['storage_clients'][$client_index]['aggr']['merge'] ??= 'keep';
-      if ('sub' == $config['storage_clients'][$client_index]['aggr']['merge']) {
+      if (in_array($config['storage_clients'][$client_index]['aggr']['merge'], ['sub', 'translation'])) {
         // Store corresponding client entities as member.
         $member =
           ($config['storage_clients'][$client_index]['aggr']['merge_as_member'] ?? '')
diff --git a/src/Plugin/ExternalEntities/DataAggregator/VerticalDataAggregator.php b/src/Plugin/ExternalEntities/DataAggregator/VerticalDataAggregator.php
index 0de5ebbcbf13afae24ecf2c91963b1f6d497b5c3..ea608dfdf97eab615fcff40189b5cd775f9973a1 100644
--- a/src/Plugin/ExternalEntities/DataAggregator/VerticalDataAggregator.php
+++ b/src/Plugin/ExternalEntities/DataAggregator/VerticalDataAggregator.php
@@ -3,6 +3,8 @@
 namespace Drupal\external_entities\Plugin\ExternalEntities\DataAggregator;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Language\Language;
+use Drupal\external_entities\ExternalEntityStorage;
 
 /**
  * External entities data aggregator by groups.
@@ -83,6 +85,7 @@ class VerticalDataAggregator extends GroupAggregator {
           'over' => $this->t('Override previous field values'),
           'ovem' => $this->t('Override previous field values if empty'),
           'sub'  => $this->t('As a sub-object'),
+          'translation'  => $this->t('As a translation'),
         ],
         '#description' => $this->t(
           'If set, entity field values provided by this storage client will override existing values with the same field name provided by previous storage clients (except for the identifier and join fields).'
@@ -106,6 +109,20 @@ class VerticalDataAggregator extends GroupAggregator {
           ],
         ],
       ];
+      $storage_client_form['merge_as_member_translation'] = [
+        '#type' => 'language_select',
+        '#languages' => Language::STATE_ALL,
+        '#title' => $this->t('Language'),
+        '#description' => $this->t(
+          'Select the language this source is used for. The data from the first source are used as values for the sites default language!'
+        ),
+        '#default_value' => str_replace(ExternalEntityStorage::EXTERNAL_ENTITY_TRANSLATION_SUB_FIELD_PREFIX, '', $aggr_config[$client_index]['aggr']['merge_as_member'] ?? ''),
+        '#states' => [
+          'visible' => [
+            ':input[id="' . $aggr_selector . '_merge"]' => ['value' => 'translation'],
+          ],
+        ],
+      ];
     }
     else {
       // First storage client.
@@ -141,6 +158,13 @@ class VerticalDataAggregator extends GroupAggregator {
     $aggr_settings = $form_state->getValue(['storage_clients', $client_index, 'aggr'], []);
     $aggr_settings['groups'] = [];
     $aggr_settings['group_prefix_strip'] = FALSE;
+
+    // If translation aggregation is enabled create a compound merge_as_member
+    // value.
+    if (($aggr_settings['merge'] ?? '') == 'translation') {
+      $aggr_settings['merge_as_member'] = ExternalEntityStorage::EXTERNAL_ENTITY_TRANSLATION_SUB_FIELD_PREFIX .$aggr_settings['merge_as_member_translation'] ?? '';
+    }
+
     $form_state->setValue(['storage_clients', $client_index, 'aggr'], $aggr_settings);
   }