phalcon/cphalcon · error · Phalcon\Translate\Exceptions\KeyNotFound

Cannot find translation key: {key}

Error message

Cannot find translation key: {key}

What it means

Every Phalcon translate adapter funnels missing keys through AbstractAdapter::notFound(). By default it returns the key string itself; if the adapter was constructed with the option ['triggerError' => true], notFound() instead throws Phalcon\Translate\Exceptions\KeyNotFound with the missing key (phalcon/Translate/Adapter/AbstractAdapter.zep:75). This turns absent dictionary entries into hard failures on query()/t()/_()/offsetGet().

Source

Thrown at phalcon/Translate/Adapter/AbstractAdapter.zep:75

    /**
     * Returns the translation string of the given key (alias of method 't')
     *
     * @phpstan-param translate_placeholders $placeholders
     */
    public function _(string translateKey, array placeholders = []) -> string
    {
        return this->query(translateKey, placeholders);
    }

    /**
     * Whenever a key is not found this method will be called
     *
     * @throws KeyNotFound
     */
    public function notFound( string index) -> string
    {
        if unlikely (true === this->triggerError) {
            throw new KeyNotFound(index);
        }

        return index;
    }

    /**
     * Check whether a translation key exists
     */
    public function offsetExists(var offset) -> bool
    {
        return this->has(offset);
    }

    /**
     * Returns the translation related to the given key
     *
     * @param string $offset
     *

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Check existence first: if ($t->has('key')) ... or isset($t['key']) before querying.
  2. Add the missing key to the dictionary (NativeArray content, CSV file, or gettext catalog) and keep all locales in sync.
  3. Catch Phalcon\Translate\Exceptions\KeyNotFound at render boundaries when unknown keys are acceptable.
  4. Remove 'triggerError' => true from the adapter options to get the default fallback (key echoed back).

Example fix

// before
echo $t->_('welcome.back'); // adapter built with triggerError => true

// after
echo $t->has('welcome.back') ? $t->_('welcome.back') : 'Welcome back';
Defensive patterns

Strategy: validation

Validate before calling

$key = 'welcome.back';
if (!$t->has($key)) {
    $logger->notice("Missing translation key: {$key} for {$locale}");
}
echo $t->has($key) ? $t->_($key) : $fallbackText;

Try / catch

use Phalcon\Translate\Exceptions\KeyNotFound;

try {
    echo $t->_($key);
} catch (KeyNotFound $e) {
    echo $fallbackText; // degrade instead of a 500 when triggerError is on
}

Prevention

When it happens

Trigger: $t->_('missing.key'), $t->t('missing.key'), or $t['missing.key'] on any adapter built with 'triggerError' => true whose dictionary lacks that key.

Common situations: Enabling triggerError in production for strictness while a template still references a typo'd or undeclared key; locale files out of sync (key present in en.csv, missing in de.csv); CSV comment rows or wrong delimiter silently dropping keys so lookups miss.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/a6b4608a3c4e01e5. Report an issue: GitHub.