diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d9da94f64fe66ca48148a0c50873f7b274a6ee74..8beb4445464eb2b29c48c28305f23075ab5c42c9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -28,8 +28,8 @@ include:
 #   OPT_IN_TEST_NEXT_MAJOR: '1'
 #   _CURL_TEMPLATES_REF: 'main'
 variables:
-  SKIP_PHPUNIT: 1
-  _PHPUNIT_CONCURRENT: 1
+  SKIP_PHPUNIT: '0'
+  _PHPUNIT_CONCURRENT: '1'
   _CSPELL_IGNORE_PATHS: 'modules/js_example/templates/accordion.html.twig, **/*.svg'
 
 phpunit:
diff --git a/examples.module b/examples.module
index 4fe20a8910e3617a97f2980c40aaf2c48c6b2dc4..8f8a8cd2a6f11e31408d184da7da85e25a48a8d8 100644
--- a/examples.module
+++ b/examples.module
@@ -122,6 +122,7 @@ function _examples_toolbar_routes() {
     'block_example' => 'block_example.description',
     'cache_example' => 'cache_example.description',
     'config_entity_example' => 'entity.robot.list',
+    'config_simple_example' => 'config_simple_example.description',
     'content_entity_example' => 'entity.content_entity_example_contact.collection',
     'cron_example' => 'cron_example.description',
     'dbtng_example' => 'dbtng_example.generate_entry_list',
diff --git a/modules/config_simple_example/config/install/config_simple_example.settings.yml b/modules/config_simple_example/config/install/config_simple_example.settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9f13574e1da2afda1d80fea63990820d2616c1a0
--- /dev/null
+++ b/modules/config_simple_example/config/install/config_simple_example.settings.yml
@@ -0,0 +1 @@
+message: 'Awesome settings'
diff --git a/modules/config_simple_example/config/schema/config_simple_example.schema.yml b/modules/config_simple_example/config/schema/config_simple_example.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9c8491c8243fc19032c4cbfcf9bc24cf6bc56a83
--- /dev/null
+++ b/modules/config_simple_example/config/schema/config_simple_example.schema.yml
@@ -0,0 +1,16 @@
+config_simple_example.settings:
+  # A config_object is a configuration object which can store fields.
+  # You have to map all field types the object stores: string, boolean, etc.
+  # The "text" field type is special because it's translatable by default.
+  # Checkout how to define schema and all available data types in:
+  # https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-schemametadata
+  # Direct link to cheat sheet:
+  # https://www.drupal.org/files/ConfigSchemaCheatSheet2.0.pdf
+  # Use Configuration Inspector to validate schema files:
+  # https://drupal.org/project/config_inspector
+  type: config_object
+  label: 'Example config'
+  mapping:
+    message:
+      type: text
+      label: 'Message'
diff --git a/modules/config_simple_example/config_simple_example.config_translation.yml b/modules/config_simple_example/config_simple_example.config_translation.yml
new file mode 100644
index 0000000000000000000000000000000000000000..726854a510bef4e0280fb753d200922985cb26be
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.config_translation.yml
@@ -0,0 +1,7 @@
+config_simple_example.settings:
+  title: 'Config Simple Example Translatable config'
+  # Route for the translatable configuration form.
+  base_route_name: config_simple_example.settings
+  # The name of all yml files that have to be translatable.
+  names:
+    - config_simple_example.settings
diff --git a/modules/config_simple_example/config_simple_example.info.yml b/modules/config_simple_example/config_simple_example.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..87756fbaa539d11b78eb9902de1c31294004b367
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.info.yml
@@ -0,0 +1,8 @@
+name: 'Config Simple Example'
+type: module
+description: 'Demonstrates how to create a custom translatable config form.'
+package: Example modules
+core_version_requirement: ^10.3
+dependencies:
+  - config_translation:config_translation
+  - examples:examples
diff --git a/modules/config_simple_example/config_simple_example.links.menu.yml b/modules/config_simple_example/config_simple_example.links.menu.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8a1bf80dfb3cefa0c8c2c7bf5052574144d59dd4
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.links.menu.yml
@@ -0,0 +1,11 @@
+config_simple_example.description:
+  title: 'Config Simple Example'
+  description: 'Custom translatable config form'
+  route_name: config_simple_example.description
+  expanded: TRUE
+config_simple_example.settings:
+  title: 'Config Simple Example Settings'
+  route_name: config_simple_example.settings
+  parent: config_simple_example.description
+  description: ''
+  weight: -15
diff --git a/modules/config_simple_example/config_simple_example.links.task.yml b/modules/config_simple_example/config_simple_example.links.task.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8ecf7356d7989c902daf162544d04be26cff0943
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.links.task.yml
@@ -0,0 +1,8 @@
+# This file is necessary so the configuration form translation tab is shown.
+config_simple_example.settings:
+  # Route of the form.
+  route_name: config_simple_example.settings
+  title: 'Config Simple Example Settings'
+  # Route of the form.
+  base_route: config_simple_example.settings
+  weight: 0
diff --git a/modules/config_simple_example/config_simple_example.module b/modules/config_simple_example/config_simple_example.module
new file mode 100644
index 0000000000000000000000000000000000000000..79c96c25f5500d80bf0cee632e3c86e91646b8c7
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.module
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Demonstrates how to create a translatable custom configuration form.
+ */
+
+/**
+ * @defgroup config_simple_example Example: Config Simple
+ * @ingroup examples
+ * @{
+ * Implement a Config Entity.
+ *
+ * This module demonstrates implementing a Simple Translatable Config Form.
+ *
+ * This is an example of a simple translatable configuration form, the kind you
+ * might create to store configuration data. This form can store different data
+ * for each site enabled language.
+ */
+
+/**
+ * @} End of "defgroup config_simple_example".
+ */
diff --git a/modules/config_simple_example/config_simple_example.routing.yml b/modules/config_simple_example/config_simple_example.routing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a4b0befaafb26695ccc9ffd3dd1498610e4590d2
--- /dev/null
+++ b/modules/config_simple_example/config_simple_example.routing.yml
@@ -0,0 +1,14 @@
+config_simple_example.description:
+  path: '/examples/config_simple_example'
+  defaults:
+    _controller: '\Drupal\config_simple_example\Controller\ConfigSimpleController::description'
+    _title: 'Config Simple Example'
+  requirements:
+    _permission: 'access content'
+config_simple_example.settings:
+  path: '/admin/config/form-api-example/config-simple-form'
+  defaults:
+    _form: '\Drupal\config_simple_example\Form\ConfigSimpleExampleSettingsForm'
+    _title: 'Config Simple Example'
+  requirements:
+    _permission: 'administer site configuration'
diff --git a/modules/config_simple_example/src/Controller/ConfigSimpleController.php b/modules/config_simple_example/src/Controller/ConfigSimpleController.php
new file mode 100644
index 0000000000000000000000000000000000000000..10ad0a00803b82b6fbd15518d94d5c8ce79b9a8f
--- /dev/null
+++ b/modules/config_simple_example/src/Controller/ConfigSimpleController.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\config_simple_example\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\examples\Utility\DescriptionTemplateTrait;
+
+/**
+ * Controller routines for Config Simple Example routes.
+ */
+class ConfigSimpleController extends ControllerBase {
+
+  use DescriptionTemplateTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getModuleName() {
+    return 'config_simple_example';
+  }
+
+}
diff --git a/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php b/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..260d345605369c9af5da87c787f25232a73de66a
--- /dev/null
+++ b/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\config_simple_example\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Configure example settings for this site.
+ */
+class ConfigSimpleExampleSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'config_simple_example_settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return [
+      'config_simple_example.settings',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('config_simple_example.settings');
+
+    $form['message'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('Message'),
+      '#default_value' => $config->get('message'),
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Retrieve the configuration.
+    $this->config('config_simple_example.settings')
+      // Set the submitted configuration setting.
+      ->set('message', $form_state->getValue('message'))
+      ->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/modules/config_simple_example/templates/description.html.twig b/modules/config_simple_example/templates/description.html.twig
new file mode 100644
index 0000000000000000000000000000000000000000..f9d1a683590d3f7fcfa731bc2dea323f7d7f868f
--- /dev/null
+++ b/modules/config_simple_example/templates/description.html.twig
@@ -0,0 +1,17 @@
+{#
+
+Description text for the Config Simple Example.
+
+#}
+
+{% set config_simple_form = path('config_simple_example.settings') %}
+
+{% trans %}
+
+<p>The Config Simple Example module defines a simple translatable config
+   form. You need "Administer site configuration" permission to test it.
+   You will need at least two language enabled to test the translation
+   of the configuration.</p>
+<p><a href={{ config_simple_form }}>Config Simple Form</a></p>
+
+{% endtrans %}
diff --git a/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php b/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd88de1b48d58f9a8710567722683881a88b9de7
--- /dev/null
+++ b/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace Drupal\Tests\form_api_example\Functional;
+
+use Drupal\Core\Url;
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\Tests\examples\Functional\ExamplesBrowserTestBase;
+
+/**
+ * Ensure that the form_api_example forms work properly.
+ *
+ * @group config_simple_example
+ * @group examples
+ *
+ * @ingroup form_api_example
+ */
+class ConfigExampleTest extends ExamplesBrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * Our module dependencies.
+   *
+   * @var string[]
+   */
+  protected static $modules = [
+    'language',
+    'locale',
+    'config_simple_example',
+  ];
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    // We need more language than default English.
+    $language = ConfigurableLanguage::createFromLangcode('es');
+    $language->save();
+  }
+
+  /**
+   * Aggregate all the tests.
+   *
+   * Since this is a functional test, and we don't expect to need isolation
+   * between these form tests, we'll aggregate them here for speed's sake. That
+   * way the testing system doesn't have to rebuild a new Drupal for us for each
+   * test.
+   */
+  public function testFunctional() {
+    // Please fail this one first.
+    $this->doTestMainPage();
+    $this->doTestConfigSimpleForm();
+  }
+
+  /**
+   * Test the main page.
+   */
+  public function doTestMainPage() {
+    $assert = $this->assertSession();
+    $example_page = Url::fromRoute('config_simple_example.description');
+    $this->drupalGet($example_page);
+
+    $assert->pageTextContains('The Config Simple Example module defines a simple translatable config form.');
+    $assert->linkExists('Config Simple Form');
+  }
+
+  /**
+   * Test the config simple form.
+   */
+  public function doTestConfigSimpleForm() {
+    $assert = $this->assertSession();
+    $config_page = Url::fromRoute('config_simple_example.settings');
+    $this->drupalGet($config_page);
+
+    $assert->fieldEnabled('edit-message');
+    $assert->buttonExists('edit-submit');
+
+    // Ensure the 'Save configuration' action performs the save.
+    $this->drupalGet($config_page);
+    $edit = [
+      'message' => 'Message in EN',
+    ];
+    $this->submitForm($edit, 'Save configuration');
+    $assert->pageTextContains('Message in EN');
+
+    // Go to Spanish version.
+    $es_lang_object = \Drupal::languageManager()->getLanguage('es');
+    $config_page_es = Url::fromRoute('config_simple_example.settings', [], ['language' => $es_lang_object]);
+    $this->drupalGet($config_page_es);
+
+    $assert->fieldEnabled('edit-message');
+    $assert->buttonExists('edit-submit');
+
+    // Ensure the 'Save configuration' action performs the save.
+    $this->drupalGet($config_page);
+    $edit = [
+      'message' => 'Message in ES',
+    ];
+    $this->submitForm($edit, 'Save configuration');
+    $assert->pageTextContains('Message in ES');
+
+    // Go back to original English version.
+    $this->drupalGet($config_page);
+    $assert->pageTextContains('Message in EN');
+  }
+
+}