Config Language Lock
config_language_lock ensures that site configuration is stored in one
explicitly chosen language regardless of request language, site default language,
or the source language of imported configuration.
Why this exists
Drupal is perfectly capable of storing configuration in any language and
translating it into others. The problem is that almost no config edit or list
form shows which language a config object is in. Only three core entity types
expose a language selector directly (menu, date_format, taxonomy_vocabulary),
and Views only surfaces one if you navigate into the edit-details subform. For
everything else — content types, image styles, text formats, roles, and most
contrib config — there is no visible indicator and no way to change the language
after creation. This is very different from content, where language is
prominently displayed and navigation by language is built in.
Because the language is invisible, a multilingual site can quietly accumulate configuration objects in a mixture of languages due to several gaps in core:
- UI forms save with whatever language the current request is in.
- Module and theme installs ship config in English (
en); the locale module rewritesento the site default — but only for extension-managed config, only when the site default is not English, and only by processing a batch that some install paths never run. - Recipes import config files as-is and may contain arbitrary or invalid langcodes.
- Config actions create entities using the current request language.
The result is configuration in a massive mix of languages with no way to see or fix it through the UI. This is confusing when setting up translations — the source language of each config object determines which language the translation UI shows as "original" — and becomes a practical problem when newer tooling such as Canvas relies on strict language consistency and breaks when it is not present.
This module provides a lock language — a single explicitly configured langcode — and enforces it consistently at every write path.
Opt-in model
Installing the module without configuring it has no side effects. The lock is
active only when an administrator explicitly selects a language on the settings
page at admin/config/regional/config-language-lock. Until then, Drupal's
default behavior is preserved unchanged.
Enforcement points
When a lock language is configured the module enforces it at five points:
| Point | Mechanism |
|---|---|
| Any config entity save | hook_entity_presave overwrites langcode to the lock language |
| Module install | hook_modules_installed queues a rewrite batch; locale's own hook is removed |
| Theme install | hook_themes_installed queues a rewrite batch; locale's own hook is removed |
| Recipe apply | RecipeAppliedEvent subscriber post-normalizes the recipe's own config/ files; config actions and module installs inside recipes are covered by hook_entity_presave |
| Settings form submit | A batch rewrites all existing active configuration |
| Site default change (optional) | When follow-site-default is enabled, hook_form_language_admin_overview_form_alter appends a submit handler that updates locked_langcode and queues the rewrite batch |
Settings UI
admin/config/regional/config-language-lock provides:
- A distribution table showing how many config items are currently in each langcode — useful for diagnosing drift.
- A follow site default language checkbox — when enabled, the lock language updates automatically whenever the site default is changed on the language admin overview page. The language selector below becomes read-only while this is checked.
- A lock language selector.
- A "do not lock" option (
- Do not lock configuration language -). - A confirmation checkbox required before the lock language can be changed, because changing it triggers a batch rewrite of all active configuration.
Follow site default language
The follow site default language option on the settings page makes the lock track the site default automatically. When it is enabled:
- Changing the site default on
admin/config/regional/languagetriggers a rewrite batch — the same batch used when the lock is changed manually on the settings page — and updateslocked_langcodeto match the new site default. - The language selector on the settings page is disabled while follow is enabled (the site default controls it instead).
- The confirmation checkbox is still required when enabling this option, because enabling it immediately rewrites all active config to the current site default.
- The lock language label on the language overview page continues to show "(Configuration language)" next to the current lock language, so administrators can see which language controls config writes at a glance.
This option is disabled by default. Without it, the lock language is a static value that changes only when an administrator manually updates it on the settings page. See Site default lifecycle for a comparison.
Locale interaction
When locale is enabled and no lock is set, locale's own extension install hooks
run as normal. When a lock is set, this module removes locale's
modules_installed and themes_installed hooks with #[RemoveHook] and
delegates back to locale only when no lock language is configured. This prevents
duplicate or conflicting rewrite behavior.
Detailed documentation pages
- Issues this module addresses — the specific Drupal core behaviors and error cases this module was written to fix
- Module install — how module installs affect config langcodes with and without a lock
- Theme install — same for themes, including the batch-not-processed edge case
- UI forms — how form submissions behave with and without a lock
- Config actions — programmatic entity creation and its langcode behavior
- Recipes — direct config files and extension config installed via recipes
- Lock switch lifecycle — what happens when the lock language is changed, including locale translation round-trips
- Site default lifecycle — how the site default language interacts with config langcodes compared to the lock
- Language management — language deletion protection and stale lock handling