symfony/translation · error · LogicException
Cannot parse message translation: please install the "intl"…
Error message
Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.
What it means
Thrown by IntlFormatter::formatIntl when the message uses ICU MessageFormat syntax but neither the intl PHP extension (MessageFormatter class) nor symfony/polyfill-intl-messageformatter is available. Without a MessageFormatter implementation, ICU-formatted messages cannot be parsed.
Solutions
- Install the intl PHP extension (`apk add php-intl` / `apt install php-intl` / enable extension=intl in php.ini)
- Or run `composer require symfony/polyfill-intl-messageformatter` as a pure-PHP fallback
- Align PHP extensions between dev and production images
Example fix
// before (Dockerfile) FROM php:8.2-fpm // after FROM php:8.2-fpm RUN docker-php-ext-install intl
Defensive patterns
Strategy: fallback
Validate before calling
if (!class_exists(\MessageFormatter::class) && !extension_loaded('intl')) { // install ext-intl or symfony/polyfill-intl-messageformatter before serving ICU messages } Type guard
function intlMessageFormattingAvailable(): bool { return class_exists(\MessageFormatter::class); } Try / catch
try { $msg = $translator->trans($id, $params, $domain, $locale); } catch (LogicException $e) { if (str_contains($e->getMessage(), 'intl')) { $msg = $this->fallbackSimpleTrans($id, $params); } else { throw $e; } } Prevention
- Pin ext-intl in composer.json (`require ext-intl`) so composer install fails early
- Use identical PHP base images for dev and production
- Prefer the symfony/polyfill-intl-messageformatter package for portability
When it happens
Trigger: Calling $translator->trans() (via MessageFormatter/IntlFormatter) on a message containing ICU syntax (e.g. '{count, plural, ...}') in a PHP build compiled without intl and without the polyfill installed.
Common situations: Deploying to a PHP environment (alpine/minimal Docker, some shared hosts) without ext-intl while local dev had it; production staging with different PHP images; translation files containing ICU plural/select messages.
Understand the failure class
Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.
Related errors
- Dumping translations in the YAML format requires the…
- Invalid message format
- Unable to format message
- Cannot load resource
- $rb->getErrorMessage()
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/c8238ebb892665f8.
Report an issue: GitHub.
Appendix: source
Thrown at Formatter/IntlFormatter.php:35
/**
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
*/
class IntlFormatter implements IntlFormatterInterface
{
private bool $hasMessageFormatter;
private array $cache = [];
public function formatIntl(string $message, string $locale, array $parameters = []): string
{
// MessageFormatter constructor throws an exception if the message is empty
if ('' === $message) {
return '';
}
if (!$formatter = $this->cache[$locale][$message] ?? null) {
if (!$this->hasMessageFormatter ??= class_exists(\MessageFormatter::class)) {
throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.');
}
try {
$this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
} catch (\IntlException $e) {
throw new InvalidArgumentException(\sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
}
}
foreach ($parameters as $key => $value) {
if (\in_array($key[0] ?? null, ['%', '{'], true)) {
unset($parameters[$key]);
$parameters[trim($key, '%{ }')] = $value;
}
}
if (false === $message = $formatter->format($parameters)) {
throw new InvalidArgumentException(\sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
}View on GitHub (pinned to ae9e8a51bc)