PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

The Intl extension does not support Accounting Formats witho

Error message

The Intl extension does not support Accounting Formats without ICU 53

What it means

Thrown by the Accounting number-format Wizard when a locale-aware accounting mask is requested but the installed ICU library is older than version 53. Accounting formats rely on NumberFormatter::CURRENCY_ACCOUNTING, which ICU only supports from 53 onwards, so getLocaleFormat() refuses to run rather than emit a wrong mask. It fires only when the intl extension reports an ICU version below 53.0, which is rare on current PHP builds.

Source

Thrown at src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php:21

namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard;

use NumberFormatter;
use PhpOffice\PhpSpreadsheet\Exception;

class Accounting extends CurrencyBase
{
    protected ?bool $overrideSpacing = true;

    protected ?CurrencyNegative $overrideNegative = CurrencyNegative::parentheses;

    /**
     * @throws Exception if the Intl extension and ICU version don't support Accounting formats
     */
    protected function getLocaleFormat(): string
    {
        if (self::icuVersion() < 53.0) {
            // @codeCoverageIgnoreStart
            throw new Exception('The Intl extension does not support Accounting Formats without ICU 53');
            // @codeCoverageIgnoreEnd
        }

        // Scrutinizer does not recognize CURRENCY_ACCOUNTING
        $formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY_ACCOUNTING);
        $mask = $formatter->format($this->stripLeadingRLM);
        if ($this->decimals === 0) {
            $mask = (string) preg_replace('/\.0+/miu', '', $mask);
        }

        return str_replace('¤', $this->formatCurrencyCode(), $mask);
    }

    public static function icuVersion(): float
    {
        [$major, $minor] = explode('.', INTL_ICU_VERSION);

        return (float) "{$major}.{$minor}";

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Upgrade PHP/intl so it links ICU >= 53 (verify with `echo INTL_ICU_VERSION;`), usually via current distro or sury/ondrej-php packages
  2. Build the accounting format without a locale so the wizard uses its built-in mask (pass '' as the locale argument)
  3. Catch the exception and fall back to a hand-written format code such as '_-"€"* #,##0.00_-;-"€"* #,##0.00_-;_-"€"* "-"??_-;_-@_-'

Example fix

// before
$mask = (new Accounting(2, '€', 'de-DE'))->format();

// after (guard for old ICU)
if (defined('INTL_ICU_VERSION') && version_compare(INTL_ICU_VERSION, '53.0', '>=')) {
    $mask = (new Accounting(2, '€', 'de-DE'))->format();
} else {
    $mask = '_-"€"* #,##0.00_-;-"€"* #,##0.00_-;_-"€"* "-"??_-;_-@_-';
}
Defensive patterns

Strategy: validation

Validate before calling

$icuOk = extension_loaded('intl') && defined('INTL_ICU_VERSION') && version_compare(INTL_ICU_VERSION, '53.0', '>=');
if ($icuOk) {
    $mask = (new Accounting(2, '€', 'de-DE'))->format();
} else {
    $mask = '_-"€"* #,##0.00_-;-"€"* #,##0.00_-;_-"€"* "-"??_-;_-@_-';
}

Type guard

function icuSupportsAccountingFormats(): bool
{
    return extension_loaded('intl')
        && defined('INTL_ICU_VERSION')
        && version_compare(INTL_ICU_VERSION, '53.0', '>=');
}

Try / catch

try {
    $mask = $accountingWizard->format();
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    // ICU too old: fall back to a hardcoded accounting format code
    $mask = '_-"€"* #,##0.00_-;-"€"* #,##0.00_-;_-"€"* "-"??_-;_-@_-';
}

Prevention

When it happens

Trigger: Calling (new Accounting(2, '€', 'de-DE'))->format(), or any Accounting wizard with a non-empty locale, on a PHP build whose intl extension links ICU < 53 (checked via INTL_ICU_VERSION).

Common situations: Legacy hosting, old Ubuntu/Debian PHP packages, outdated XAMPP/WAMP bundles, or containers built from very old base images where PHP was upgraded but the ICU library was not.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/6465c5fb5b28fe7a. Report an issue: GitHub.