symfony/translation · error · InvalidArgumentException

The expansion factor must be greater than or equal to 1.

Error message

The expansion factor must be greater than or equal to 1.

What it means

PseudoLocalizationTranslator validates the 'expansion_factor' option at construction: values below 1.0 would shrink or not expand pseudo-localized strings, defeating the purpose, so it throws InvalidArgumentException.

Solutions

  1. Set expansion_factor to a value >= 1.0 (e.g. 1.3)
  2. Validate the config value before constructing the translator
  3. Remove the option to use the default 1.0

Example fix

// before
$t = new PseudoLocalizationTranslator($t, ['expansion_factor' => 0.5]);
// after
$factor = max(1.0, (float) ($_ENV['PSEUDO_EXPANSION'] ?? 1.0));
$t = new PseudoLocalizationTranslator($t, ['expansion_factor' => $factor]);
Defensive patterns

Strategy: validation

Validate before calling

$factor = $options['expansion_factor'] ?? 1.0;
if (!is_numeric($factor) || (float) $factor < 1.0) {
    throw new \InvalidArgumentException('expansion_factor must be >= 1.0');
}

Type guard

function isValidExpansionFactor(mixed $v): bool {
    return is_numeric($v) && (float) $v >= 1.0;
}

Try / catch

try {
    $pseudo = new PseudoLocalizationTranslator($translator, $options);
} catch (\InvalidArgumentException $e) {
    $pseudo = new PseudoLocalizationTranslator($translator); // safe defaults
}

Prevention

When it happens

Trigger: new PseudoLocalizationTranslator($translator, ['expansion_factor' => 0.5]) or a config value read from YAML/env that is 0 or negative; a typo mapping e.g. 0.1 instead of 1.x.

Common situations: Loading the factor from an .env variable parsed as float 0 when unset; experimenting with exaggerated pseudo-localization configs in test environments.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15). Data as JSON: /api/errors/26f422469cce4a94. Report an issue: GitHub.

Appendix: source

Thrown at PseudoLocalizationTranslator.php:75

     *      default: false
     *      description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand or when it contains HTML
     *      warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo <div>bar" => "foo <div>bar</div>"
     *
     *  * localizable_html_attributes:
     *      type: string[]
     *      default: []
     *      description: the list of HTML attributes whose values can be altered - it is only useful when the "parse_html" option is set to true
     *      example: if ["title"], and with the "accents" option set to true, "<a href="#" title="Go to your profile">Profile</a>" => "<a href="#" title="Ĝö ţö ýöûŕ þŕöƒîļé">Þŕöƒîļé</a>" - if "title" was not in the "localizable_html_attributes" list, the title attribute data would be left unchanged.
     */
    public function __construct(
        private TranslatorInterface $translator,
        array $options = [],
    ) {
        $this->translator = $translator;
        $this->accents = $options['accents'] ?? true;

        if (1.0 > ($this->expansionFactor = $options['expansion_factor'] ?? 1.0)) {
            throw new \InvalidArgumentException('The expansion factor must be greater than or equal to 1.');
        }

        $this->brackets = $options['brackets'] ?? true;

        $this->parseHTML = $options['parse_html'] ?? false;
        if ($this->parseHTML && !$this->accents && 1.0 === $this->expansionFactor) {
            $this->parseHTML = false;
        }

        $this->localizableHTMLAttributes = $options['localizable_html_attributes'] ?? [];
    }

    public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        $trans = '';
        $visibleText = '';

        foreach ($this->getParts($this->translator->trans($id, $parameters, $domain, $locale)) as [$visible, $localizable, $text]) {

View on GitHub (pinned to ae9e8a51bc)