feat: #3588828 Split domain_config and domain_config_ui to make the language module optional

Summary

Closes #3588828.

Splits domain_config and domain_config_ui so the language module becomes optional for monolingual sites that only need per-domain overrides.

What this MR does

Structural split

  • domain_config stops requiring drupal:language. Only the domain-only override services and helpers stay.
  • New domain_config_language ships the language-aware override services (DomainLanguageConfigFactoryOverride, DomainConfigLanguageManager, DomainLanguageConfigOverride, DomainLanguageConfigCollectionNameTrait). Hard-deps on drupal:language and domain:domain_config.
  • domain_config_ui stops referencing the language override service. The inline language-override delete loop in DomainConfigFactory::deleteConfigurationOverridesForDomain() becomes an event subscriber on DomainConfigOverrideEvents::DELETE_OVERRIDE. The "Languages" column on the overview page becomes a new alter hook, hook_domain_config_ui_overview_alter(), documented in the module's .api.php.
  • New domain_config_language_ui carries the language_manager decorator (DomainConfigUILanguageManager), the cleanup subscriber, and the alter-hook implementation that restores the Languages column.

Service IDs are stable

domain.language.config_factory_override and domain.language_manager keep the same string IDs — only the module that registers them changes. Consumer code calling \Drupal::service('domain.language.config_factory_override') keeps working unchanged.

Storage layout is unchanged

The config-collection naming (domain.{id} and domain.{id}.language.{lang}) is preserved. No data migration needed.

Update hooks

  • domain_config_update_10002() auto-installs domain_config_language when the language module is enabled.
  • domain_config_ui_update_10002() auto-installs domain_config_language_ui when the language module is enabled.

Existing 3.x sites upgrade transparently — they always had language enabled (it was a hard dep), so they get both new submodules automatically.

Tests reorganized to match

  • DomainConfigTestBase is now language-agnostic.
  • New DomainConfigLanguageTestBase in domain_config_language adds the language module and a Spanish language during setUp.
  • Language-bound tests moved to the language modules: DomainConfigOverriderTest was split (the langcode-iterating method became DomainLanguageConfigOverriderTest); DomainConfigHomepageTest and 8 UI tests moved whole; DomainConfigUIOptionsTest was split (the testDisallowedRoutesHook half stayed in domain_config_ui as a new dedicated class).
  • Tests that previously installed 'language' without using it had the dep dropped.
  • New coverage for the new code paths:
    • DomainLanguageOverrideCleanupSubscriberTest (kernel) — locks in the per-language cleanup contract.
    • DomainConfigUIOverviewLanguageColumnTest (functional) — locks in the alter-hook column rendering.
    • DomainConfigOverrideEditableTest had its $modules array documented as the standalone-scenario lock-in (no language, no domain_config_language).

PHP namespaces

The moved classes are all marked @internal (#3584261) so the public API contract is the service IDs. Custom code typehinting the moved classes needs use updates from Drupal\domain_config\… to Drupal\domain_config_language\….

Docs

New docs/domain_config_language/ and docs/domain_config_language_ui/ pages (en/fr/es), mkdocs.yml nav updated for all three locales, CHANGELOG entry for 3.1.0.

Test plan

  • CI matrix runs the new submodules' tests automatically (DrupalCI discovers tests under tests/).
  • DomainConfigOverrideEditableTest proves domain_config works standalone (no language).
  • DomainLanguageOverrideCleanupSubscriberTest proves the cleanup subscriber removes per-language rows when their base override is deleted.
  • DomainConfigUIOverviewLanguageColumnTest proves the alter hook injects the Languages column with correct values.
  • All existing language-aware tests (overrides, translation, saved config, settings, cast value, multi-form, registered) keep passing under their new home in domain_config_language_ui.
  • #3586509 — original report that surfaced the coupling.
  • #3060758 — introduced the new Config/ class hierarchy in 3.x that made the cross-module coupling load-bearing.
  • #3584261 — marked the affected classes @internal, which makes the namespace move feasible without a public-API breaking change.
Edited by Frank Mably

Merge request reports

Loading