diff --git a/core/modules/block_content/migration_templates/d6_custom_block_translation.yml b/core/modules/block_content/migration_templates/d6_custom_block_translation.yml
new file mode 100644
index 0000000..3d4bce0
--- /dev/null
+++ b/core/modules/block_content/migration_templates/d6_custom_block_translation.yml
@@ -0,0 +1,39 @@
+id: d6_custom_block_translation
+label: Custom block translations
+migration_tags:
+  - Drupal 6
+source:
+  plugin: d6_box_translation
+  constants:
+    type: basic
+process:
+  id:
+    plugin: migration
+    migration: d6_custom_block
+    source:
+      - bid
+  langcode: language
+  type: 'constants/type'
+  info:
+    plugin: i18n_translation
+    source:
+      - title_untranslated
+      - title_translated
+  'body/value':
+    plugin: i18n_translation
+    source:
+      - body_untranslated
+      - body_translated
+  'body/format':
+    plugin: migration
+    migration: d6_filter_format
+    source: format
+destination:
+  plugin: entity:block_content
+  no_stub: true
+  translations: true
+migration_dependencies:
+  required:
+    - d6_filter_format
+    - block_content_body_field
+    - d6_custom_block
diff --git a/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php b/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php
new file mode 100644
index 0000000..8149991
--- /dev/null
+++ b/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Drupal\block_content\Plugin\migrate\source\d6;
+
+use Drupal\Component\Utility\Unicode;
+use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Gets Drupal 6 i18n custom block translations from database.
+ *
+ * @MigrateSource(
+ *   id = "d6_box_translation",
+ *   source_module = "block"
+ * )
+ */
+class BoxTranslation extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    // Build a query based on 18n_strings table where each row has the
+    // translation for only one property, either title or description. The
+    // method prepareRow() is then used to obtain the translation for the other
+    // property.
+    $query = $this->select('boxes', 'b')
+      ->fields('b', ['bid', 'body', 'info', 'format'])
+      ->fields('i18n', ['lid', 'property'])
+      ->fields('lt', ['lid', 'translation', 'language'])
+      ->orderBy('b.bid');
+
+    // Add in the property, which is either title or body.
+    $query->leftJoin('i18n_strings', 'i18n', 'i18n.objectid = b.bid');
+    $query->isNotNull('i18n.lid');
+
+    // Add in the translation for the property.
+    $query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    $language = $row->getSourceProperty('language');
+    $bid = $row->getSourceProperty('bid');
+    if (empty($this->idMap->lookupDestinationIds(['bid' => $bid, 'language' => $language]))) {
+      $row->setSourceProperty('migrate', TRUE);
+    }
+    // Set untranslated values as defaults.
+    $row->setSourceProperty('title_untranslated', $row->getSourceProperty('info'));
+    $row->setSourceProperty('body_untranslated', Unicode::truncate($row->getSourceProperty('options/attributes/title'), 255));
+
+    // Save the translation for this property.
+    $property = $row->getSourceProperty('property');
+    $row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation'));
+
+    // Get the translation for the property not already in the row.
+    $property2 = ($property == 'title') ? 'body' : 'title';
+    $query = $this->select('i18n_strings', 'i18n')
+      ->fields('i18n', ['lid'])
+      ->condition('i18n.property', $property2)
+      ->condition('i18n.objectid', $bid);
+    $query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid');
+    $query->condition('lt.language', $language)
+      ->addField('lt', 'translation');
+    $results = $query->execute()->fetchAssoc();
+    $row->setSourceProperty($property2 . '_translated', $results['translation']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return [
+      'bid' => $this->t('The block numeric identifier.'),
+      'language' => $this->t('Language for this field.'),
+      'title' => $this->t('Block title translation.'),
+      'body' => $this->t('Block body translation.'),
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['bid']['type'] = 'integer';
+    $ids['bid']['alias'] = 'b';
+    $ids['language']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/block_content/tests/src/Kernel/Migrate/d6/MigrateCustomBlockContentTranslationTest.php b/core/modules/block_content/tests/src/Kernel/Migrate/d6/MigrateCustomBlockContentTranslationTest.php
new file mode 100644
index 0000000..a9bd6d9
--- /dev/null
+++ b/core/modules/block_content/tests/src/Kernel/Migrate/d6/MigrateCustomBlockContentTranslationTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
+
+use Drupal\block_content\Entity\BlockContent;
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
+
+/**
+ * Tests migration of i18n custom block strings.
+ *
+ * @group migrate_drupal_6
+ */
+class MigrateCustomBlockContentTranslationTest extends MigrateDrupal6TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'block_content',
+    'content_translation',
+    'language',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installConfig(['block_content']);
+    $this->installEntitySchema('block_content');
+    $this->executeMigrations([
+      'language',
+      'd6_filter_format',
+      'block_content_type',
+      'block_content_body_field',
+      'd6_custom_block',
+      'd6_custom_block_translation',
+    ]);
+  }
+
+  /**
+   * Tests the Drupal 6 i18n custom block strings to Drupal 8 migration.
+   */
+  public function testCustomBlockContentTranslation() {
+    /** @var BlockContent $block */
+    $block = BlockContent::load(1)->getTranslation('fr');
+    $this->assertSame('fr - Static Block', $block->label());
+    $this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
+    $this->assertSame('fr', $block->language()->getId());
+    $this->assertSame('<h3>fr - My first custom block body</h3>', $block->body->value);
+    $this->assertSame('full_html', $block->body->format);
+
+    $block = BlockContent::load(1)->getTranslation('zu');
+    $this->assertSame('My block 1', $block->label());
+    $this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
+    $this->assertSame('zu', $block->language()->getId());
+    $this->assertSame('<h3>zu - My first custom block body</h3>', $block->body->value);
+    $this->assertSame('full_html', $block->body->format);
+
+    $block = BlockContent::load(2)->getTranslation('fr');
+    $this->assertSame('Encore un bloc statique', $block->label());
+    $this->assertTrue(REQUEST_TIME <= $block->getChangedTime() && $block->getChangedTime() <= time());
+    $this->assertSame('fr', $block->language()->getId());
+    $this->assertSame('Nom de vocabulaire beaucoup plus long que trente-deux caractères', $block->body->value);
+    $this->assertSame('full_html', $block->body->format);
+  }
+
+}
diff --git a/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d6/BoxTranslationTest.php b/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d6/BoxTranslationTest.php
new file mode 100644
index 0000000..d8205fa
--- /dev/null
+++ b/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d6/BoxTranslationTest.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
+
+use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
+
+/**
+ * Tests i18n custom block translations source plugin.
+ *
+ * @covers Drupal\block_content\Plugin\migrate\source\d6\BoxTranslation
+ *
+ * @group content_translation
+ */
+class BoxTranslationTest extends MigrateSqlSourceTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['block_content', 'migrate_drupal'];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function providerSource() {
+    $tests = [];
+
+    // The source data.
+    $tests[0]['database']['boxes'] = [
+      [
+        'bid' => 1,
+        'body' => 'box 1 body',
+        'info' => 'box 1 info',
+        'format' => '2',
+      ],
+      [
+        'bid' => 2,
+        'body' => 'box 2 body',
+        'info' => 'box 2 info',
+        'format' => '2',
+      ],
+    ];
+
+    $tests[0]['database']['i18n_strings'] = [
+      [
+        'lid' => 1,
+        'objectid' => 1,
+        'type' => 'block',
+        'property' => 'title',
+        'objectindex' => 1,
+        'format' => 0,
+      ],
+      [
+        'lid' => 2,
+        'objectid' => 1,
+        'type' => 'block',
+        'property' => 'body',
+        'objectindex' => 1,
+        'format' => 0,
+      ],
+      [
+        'lid' => 3,
+        'objectid' => 2,
+        'type' => 'block',
+        'property' => 'body',
+        'objectindex' => 2,
+        'format' => 2,
+      ],
+    ];
+
+    $tests[0]['database']['locales_target'] = [
+      [
+        'lid' => 1,
+        'language' => 'fr',
+        'translation' => 'fr - info translation',
+        'plid' => 0,
+        'plural' => 0,
+        'i18n_status' => 0,
+      ],
+      [
+        'lid' => 2,
+        'language' => 'fr',
+        'translation' => 'fr - body translation',
+        'plid' => 0,
+        'plural' => 0,
+        'i18n_status' => 0,
+      ],
+      [
+        'lid' => 3,
+        'language' => 'zu',
+        'translation' => 'zu - body translation',
+        'plid' => 0,
+        'plural' => 0,
+        'i18n_status' => 0,
+      ],
+    ];
+
+    // The expected results.
+    $tests[0]['expected_results'] = [
+      [
+        'lid' => '1',
+        'property' => 'title',
+        'language' => 'fr',
+        'translation' => 'fr - info translation',
+        'bid' => '1',
+        'body' => 'box 1 body',
+        'info' => 'box 1 info',
+        'format' => '2',
+      ],
+      [
+        'lid' => '2',
+        'property' => 'body',
+        'language' => 'fr',
+        'translation' => 'fr - body translation',
+        'bid' => '1',
+        'body' => 'box 1 body',
+        'info' => 'box 1 info',
+        'format' => '2',
+      ],
+      [
+        'lid' => '3',
+        'property' => 'body',
+        'language' => 'zu',
+        'translation' => 'zu - body translation',
+        'bid' => '2',
+        'body' => 'box 2 body',
+        'info' => 'box 2 info',
+        'format' => '2',
+      ],
+    ];
+
+    return $tests;
+  }
+
+}
diff --git a/core/modules/content_translation/src/Plugin/migrate/process/d6/i18nTranslation.php b/core/modules/content_translation/src/Plugin/migrate/process/d6/i18nTranslation.php
new file mode 100644
index 0000000..3399315
--- /dev/null
+++ b/core/modules/content_translation/src/Plugin/migrate/process/d6/i18nTranslation.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\content_translation\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Processes an i18n translation.
+ *
+ * The i18n_translation plugin will return the translated value, if provided,
+ * otherwise it will return the untranslated value.
+ *
+ * Example:
+ * @code
+ * process:
+ *   bar:
+ *     plugin: i18n_translation
+ *     source:
+ *       - foo
+ *       - oof
+ * @endcode
+ *
+ * @MigrateProcessPlugin(
+ *   id = "i18n_translation"
+ * )
+ */
+class i18nTranslation extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    if (!is_array($value) || count($value) !== 2) {
+      throw new MigrateException('You need to specify both the translated and untranslated values on the i18n_translation plugin.');
+    }
+    list($untranslated, $translated) = $value;
+    if ($translated) {
+      return $translated;
+    }
+    else {
+      return $untranslated;
+    }
+  }
+
+}
