Problem/Motivation

When uninstalling a module that has translation project metadata (e.g., Lockr), stale entries can remain in the key_value table under the locale.project collection.

These cached entries are later reused by the Locale module when rebuilding translation status (for example, when visiting /admin/config/regional/translate), causing:

  • Re-creation of entries in locale_file
  • PHP warnings such as:

    Warning: Undefined array key "lockr" in TranslationStatusForm
  • Inconsistent translation state across environments

The issue persists even after manually deleting rows from locale_file, because the data is reintroduced from cached project metadata stored in key_value.


Steps to Reproduce

  1. Install a contrib module with translation metadata (e.g., Lockr)
  2. Ensure the Locale module is enabled
  3. Uninstall the module:
    drush pm:uninstall lockr -y
  4. Verify stale cache entry exists:
    SELECT * FROM key_value 
    WHERE collection = 'locale.project' 
    AND name = 'lockr';
        
  5. Visit:
    /admin/config/regional/translate
  6. Check database again:
    SELECT * FROM locale_file WHERE project = 'lockr';
        

Result: The lockr entry is recreated in locale_file, and warnings may appear.


Expected behavior

  • Locale-related cached project entries (locale.project) should be removed when a module is uninstalled
  • Translation system should not rebuild projects for uninstalled modules

Actual behavior

  • Cached project entries persist after module uninstall
  • Locale system treats them as valid projects
  • Translation records are recreated from stale cache

Proposed resolution

  • Invalidate or remove corresponding locale.project entries from key_value during module uninstall
  • Alternatively, filter translation projects to only include currently installed modules when rebuilding translation status

Workaround

Manually remove stale entries:

DELETE FROM key_value
WHERE collection = 'locale.project'
AND name = 'lockr';
DELETE FROM locale_file
WHERE project = 'lockr';

Then clear caches:

drush cr

Additional information

  • This issue appears to be a cache invalidation gap in the Locale subsystem rather than a general module uninstall failure
  • Occurs only for modules that register translation project metadata
  • Reproducible when translation status is rebuilt via UI or Drush

Environment

  • Drupal: 10.x (observed)
  • Database: MariaDB
  • Locale module: Enabled

``

Comments

maheshv created an issue. See original summary.

nicxvan’s picture

Locale does remove those values on uninstall:

https://git.drupalcode.org/project/drupal/-/blob/main/core/modules/local...

Which calls this:

/ Remove translation files.
        $this->localeFileManager->deleteTranslationFiles($extensions, []);

        // Remove translatable projects.
        $this->localeProjectRepository->deleteMultiple($extensions);

        // Clear the translation status.
        $this->localeSource->deleteSources($extensions)

Which key value is stale?

maheshv’s picture

key_value
collection = 'locale.project'
name = 'lockr'

nicxvan’s picture

$this->localeProjectRepository->deleteMultiple($extensions);

Is this, which specifically deletes the module keys.

  public function deleteMultiple(array $keys): void {
    $this->keyValueFactory->get('locale.project')->deleteMultiple($keys);
    $this->memoryCache->delete('locale_get_projects');
  }

I wonder if something else is repopulating it for you.

maheshv’s picture

I had to write post_update_N() with below code to remove this warnings

<?php

/**
* @file
* Post update functions for test_module.
*/

declare(strict_types=1);

use Drupal\Core\Database\Database;

/**
* Remove stale Lockr locale cache and data.
*/
function test_module_post_update_10001(): void {
$connection = Database::getConnection();
$schema = $connection->schema();

// Remove from locale_file.
if ($schema->tableExists('locale_file')) {
$connection->delete('locale_file')
->condition('project', 'lockr')
->execute();
}

// Remove from key_value cache (CRITICAL FIX).
if ($schema->tableExists('key_value')) {
$connection->delete('key_value')
->condition('collection', 'locale.project')
->condition('name', 'lockr')
->execute();
}

// Clear locale state cache.
\Drupal::state()->delete('locale.translation_status');

// Clear all caches.
drupal_flush_all_caches();

\Drupal::logger('test_module')->notice('Removed stale Lockr locale project and cache.');
}

nicxvan’s picture

Status: Active » Postponed (maintainer needs more info)