octobercms/october · warning · Exception

[!!] Missing key for english [{$key}] in [{$englishPath}]

Error message

[!!] Missing key for english [{$key}] in [{$englishPath}]

What it means

The october:util refit lang utility (OctoberUtilRefitLang::utilRefitLang) converts legacy nested PHP language files (lang/<locale>/<file>.php) into per-locale JSON files (lang/<locale>.json) keyed by the English source string. For each key found in a non-English locale it does array_get($englishArr, $key); when the English source file has no such key, the JSON key cannot be derived and an Exception '[!!] Missing key for english ...' aborts the run.

Source

Thrown at modules/system/console/OctoberUtilRefitLang.php:188

            $fileName = 'lang.php';
        }

        $englishPath = "{$basePath}/lang/en/{$fileName}";
        $englishArr = include($englishPath);

        $legacyPath = "{$basePath}/lang/{$lang}/{$fileName}";
        $legacyArr = include($legacyPath);

        $newPath = "{$basePath}/lang/{$lang}.json";
        $newArr = [];

        if (file_exists($newPath)) {
            $newArr = json_decode(file_get_contents($newPath), true);
        }

        $english = array_get($englishArr, $key);
        if (!$english) {
            throw new Exception("[!!] Missing key for english [{$key}] in [{$englishPath}]");
        }

        $translated = array_get($legacyArr, $key);
        if (!$translated) {
            $this->comment("[{$lang}] Missing key [{$key}] in [{$legacyPath}]");
            return;
        }

        $newArr[$english] = $translated;

        File::put($newPath, $this->refitLangJsonEncode($newArr));

        $this->comment("[{$lang}] → {$english}:{$translated}");

        if ($lang === 'en') {
            $this->comment(PHP_EOL);
            $this->refitFinalMessage = "<?= __(\"{$english}\") ?>";
        }

View on GitHub (pinned to b608633a7e)

Solutions

  1. Add the missing key(s) to the English file named in the message (lang/en/<file>.php) — the message includes the key and path
  2. Or delete the orphaned key(s) from the offending locale file if the string is obsolete
  3. Re-run php artisan october:util refit lang; each fixed file proceeds until the next missing key, so repeat until it completes

Example fix

// before: lang/fr/validation.php contains 'custom.name' but lang/en/validation.php does not

// after: add the English source so the JSON key can be derived
// lang/en/validation.php
return [
    // ...
    'custom' => ['name' => 'Name'],
];
Defensive patterns

Strategy: validation

Validate before calling

$en = include "$basePath/lang/en/{$fileName}.php";
$loc = include "$basePath/lang/{$lang}/{$fileName}.php";
$missing = array_diff(array_keys(array_dot($loc)), array_keys(array_dot($en)));
if ($missing) {
    // fix lang/en first: ' . print_r($missing, true)
}

Prevention

When it happens

Trigger: Running php artisan october:util refit lang when lang/<locale>/<file>.php contains keys that do not exist in lang/en/<file>.php (translator added keys only to their locale, or English keys were renamed), or the English file is missing entirely.

Common situations: Contributed translations drifting ahead of the English base; plugins merged from forks with divergent lang trees; refactoring that renamed English keys but not the translations.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/1122fb6e5c34b175. Report an issue: GitHub.