# Drupal 8 – How to translate the Config API

> When creating applications using Drupal 8, there are many cases when the configuration forms containing data have to be managed by the client. The most concrete case is – for example – all the links of the social networks must be different according to the language. I will explain here the whole process to enable configuration translation with a ConfigFormBase.

Source: https://antistatique.net/en/blog/drupal-8-how-to-translate-the-config-api

Category: Development

# Drupal 8 – How to translate the Config API

Author(s)

[

![Kevin](https://images.statique.ch/t/w_750,h_750,c_fill,f_jpeg,q_70/wp/app/uploads/2020/12/Kevin-300x300.jpg)



](/en/agence/kevin)

[Kevin](/en/agence/kevin)1 May 2018

As you probably already know, I live in Switzerland and - beside chocolate & cheese - this country has one another singularity: 4 official national languages. As result, more than 90% of our web creations need to be **localized in at least 2 languages**.  
This peculiarity makes us **experts in the creation of multilingual websites**.

When creating applications using Drupal 8, there are many cases when the **configuration forms containing data have to be managed by the client**. The most concrete case is - for example - all the links of the social networks must be different according to the language.

I will explain here the whole process to enable configuration translation with a `ConfigFormBase` form. I will go through the [creation of the structure](https://antistatique.net/en/we/blog/2018/05/01/drupal-8-how-to-translate-the-config-api#config-install) and the [schema generation](https://antistatique.net/en/we/blog/2018/05/01/drupal-8-how-to-translate-the-config-api#config-schema) as well as the [activation of the translation system](https://antistatique.net/en/we/blog/2018/05/01/drupal-8-how-to-translate-the-config-api#config-trans).

## Prerequisites

> “ Every solution to every problem is simple. It's the distance between the two where the mystery lies. ”
> 
> Derek Landy
> 
> Skulduggery Pleasant

If you do not know the Drupal 8 Config API system yet, check it out [Drupal 8 - Differences between Configuration API & State API](https://antistatique.net/en/we/blog/2016/06/14/drupal-8-differences-between-configuration-api-state-api). You may also find more help directly on the [official documentation](https://www.drupal.org/docs/8/api/configuration-api).

**This article is for experienced Drupal 8 developers.**

## Assets

> “ Give me matter and I will build a world out of it. ”
> 
> Immanuel Kant

Before explaining how it all works, you can download all the sample files below.

This article example is testable via the [downloadable test module here](https://antistatique.net/sites/default/files/my_module.zip).

To help you understand this article, **2 translatable configuration forms** will be created in our example:

-   The first one is a simple form demonstrating the translation system of several types of fields:
    
    -   Text - _translatable_
    -   Select - _untranslatable_
    -   Checkbox - _untranslatable_
    -   Checkboxes - _untranslatable_
    -   Radios - _untranslatable_
    -   Textarea - _translatable_
    -   CKeditor - _translatable_
    

-   The second is a complex form, demonstrating the translation system via mapping and structure in sequence:
    
    -   Nested fields with multiple children - _translatable_
    -   Entity reference field - _untranslatable_
    -   Textarea with preprocess in sequence (then stored as array) - _translatable_
    

As you can notice, several fields are "untranslatable". It's not a deliberate choice, but the Core Drupal requires this, and that's normal! Fields that are not translatable are fields called "key" -> "value". It is therefore normal to be unable to translate keys since they **have their own Business Logic**. As for the values, they are translatable via the [standard translation function exposed by the Core](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21StringTranslation%21StringTranslationTrait.php/trait/StringTranslationTrait).

## Setup default values

We have 2 files because we have 2 different configurations.

-   **SettingsForm** -> `my_module.settings.yml`
-   **SettingsAdvancedForm** -> `my_module.settings_advanced.yml`

These structure files are always found in the `config/install` folder of the module. They correspond to the **initialization of the configuration**, ie the default values. These files are not mandatory by default in Drupal 8, but are required once we want to make our configuration translatable.

These files must be named in a very specific way, depending on the name of the corresponding configuration. You can find this name **in the array of the `getEditableConfigNames`** method of your configuration forms.

Let's see what the definition of the structure of our 2 forms looks like:

**SettingsForm**

**SettingsAdvancedForm**

Did you notice **both content files correspond to what we save in database**?! All the fields saved in the database must be there. In addition, the structure of your configuration is also represented in this file.

**SettingsForm**

```
title: ''                # simple text field
select: ''               # select field
checkbox: FALSE          # boolean checkbox
checkboxes: { }          # array of checkboxes
radios: ''               # the value selected from radios
message: ''              # content of textarea
ckeditor:
  value: ''              # ckeditor content
  format: 'basic_html'   # ckeditor format
```

**SettingsAdvancedForm**

```
site:                   # array containing our data
  title: ''             # simple text field (nested)
  content:
    value: ''           # ckeditor content
    format: basic_html  # ckeditor format
mails: { }              # Values, formated as array, transformed from the textarea
entity_reference: ''    # entity reference field
```

## Setup the schema

The schema is **a single file**, regardless of how many configurations your module depends on. This file contains the tree structure corresponding to the previous step, but this time we don't add the default value to each key, but its type and a label.

![CheatSheet des formats et types utilisables dans un schema.yml Drupal 8.](https://images.statique.ch/t/w_750,f_jpeg,q_70/wp/app/uploads/2020/12/Drupal-8-configuration-cheatsheet-schema-1024x721.png)

Cheatsheet formats and types usable in a Drupal schema.yml 8.

Thanks to the schema configuration, we can declare which key is translatable and which is its Label in the interface of translation for the configuration!

Are you wondering why we need to provide a complete schema when we do not use all the keys for translation? Well **the schema is not used only for translations** ! For example, when you edit a configuration, the forms will use the schema to "type-cast" the data, which ensures that a field defined as a boolean in your schema is a boolean and not a string when it's manipulated. In addition, this file is used for the **automatic generation of the translation form**, hence the need to add a Label to each key.

The schema must be created directly in the `config/schema` folder and must be named following the module name:`my_module.schema.yml`.

Here is what the schema file of our 2 forms looks like:

In short, the schema system, just like the structure file, is **optional** as long as you do not need to translate your configuration.

## Activate the translation

Once you have created your structure file and schema file, you just have to declare to the translation system which forms expose the translations.

You just need to create the `my_module.config_translation.yml` file.

This file contains **all the configuration exposed by the translation form**. Each form must define a title, the path to access the form and finally all the configuration keys that it exposes.

You can now access the forms from the menu: Configuration > Regional and language > Configuration translation.

## Add a translation tab

Now that your form is translatable, it is sometimes disconcerting to access it throught the "Configuration translation" page, hidden behind 3 levels of links. It would be much more convenient to access this page from a **"Local task"**, exactly like the other pages and settings that Core Drupal 8 offers.

![Local task de traduction pour le formulaire Core - Basic Site.](https://images.statique.ch/t/w_750,f_jpeg,q_70/wp/app/uploads/2020/12/Drupal-8-Basic-Site-Settings.png)

Local task - Basic Site Translation.

By default, the translation system will generate a "Local task" - or a tab - for the translations of your form, but you may not see it, because to see this action you need to have at least 1 "Local task". I admit it's a little far-fetched, but here's a workaround.

-   Create a new "Local task" in your module using the `my_module.links.task.yml` file at the root of your module.
-   Add an entry for each configuration form exposing translations.

## Sources

For the most curious, here are some sources of additional information that inspired the creation of this article.

**Gábor Hojtsy** (29 october 2015). Configuration translation development. Retrieved from [hojtsy.hu](http://hojtsy.hu/blog/2014-may-26/drupal-8-multilingual-tidbits-16-configuration-translation-development)

**Alex Tkachev** (16 décembre 2014). Drupal 8 configuration management. Retrieved from [amazeelabs.com](https://www.amazeelabs.com/en/blog/drupal8-configuration-management-part1)

## More articles

Author(s)

[

![Anthony](https://images.statique.ch/t/w_750,h_750,c_fill,f_jpeg,q_70/wp/app/uploads/2024/11/anthony-1-300x300.png)



](/en/agence/anthony-salamone)

[Anthony](/en/agence/anthony-salamone)28 September 2026

### [Smashing Conference Freiburg 2026](/en/blog/smashing-conference-freiburg-2026)

Back in Freiburg for Smashing Conference 2026: AI and design systems, deeply technical CSS and HTML, and more human talks about teams and mindset. Here's what we took away.

Back in Freiburg for Smashing Conference 2026: AI and design systems, deeply technical CSS and HTML, and more human talks about teams and mindset. Here's what we took away.

[

![Smashing Conference Freiburg 2026 poster](https://images.statique.ch/t/w_750,h_500,c_fill,f_jpeg,q_70/assets/blog/smashing-2026.png)



](/en/blog/smashing-conference-freiburg-2026)

Author(s)

[

![Akira](https://images.statique.ch/t/w_750,h_750,c_fill,f_jpeg,q_70/wp/app/uploads/2025/03/akira-small-300x300.jpg)



](/en/agence/akira-kamata)

[Akira](/en/agence/akira-kamata)22 July 2026

### [Making of : “La nuit des Losers”](/en/blog/making-of-la-nuit-des-losers)

lanuitdeslosers.ch, built fast: paper wireframes, a bold hand-drawn identity, then Claude Code to prototype and ship. A mouse-tracking hero animation, a bowling game made of sponsor logos, and a few bugs we’re keeping.

lanuitdeslosers.ch, built fast: paper wireframes, a bold hand-drawn identity, then Claude Code to prototype and ship. A mouse-tracking hero animation, a bowling game made of sponsor logos, and a few bugs we’re keeping.

[

![Making of : “La nuit des Losers”](https://images.statique.ch/t/w_750,h_500,c_fill,f_jpeg,q_70/wp/app/uploads/2026/05/La-nuit-des-Losers-Teaser-1-768x576.png)



](/en/blog/making-of-la-nuit-des-losers)

Author(s)

[

![Pierre](https://images.statique.ch/t/w_750,h_750,c_fill,f_jpeg,q_70/wp/app/uploads/2020/12/Pierre-300x300.jpg)



](/en/agence/pierre)

[Pierre](/en/agence/pierre)7 July 2026

### [Dark mode: necessity or trend](/en/blog/dark-mode-necessity-or-trend)

Nous faisons le tri entre idées reçues, réalités techniques et bonnes pratiques de design.

Nous faisons le tri entre idées reçues, réalités techniques et bonnes pratiques de design.

[

![Dark mode: necessity or trend](https://images.statique.ch/t/w_750,h_500,c_fill,f_jpeg,q_70/wp/app/uploads/2026/07/1-768x384.png)



](/en/blog/dark-mode-necessity-or-trend)
