Skip to content

fix(twig): readtime() returns "0" for texts shorter than 200 words - #2473

Merged
ArnaudLigny merged 1 commit into
masterfrom
fix/readtime-minimum
Sep 20, 2026
Merged

ArnaudLigny merged 1 commit into
masterfrom
fix/readtime-minimum

Conversation

@ArnaudLigny

Copy link
Copy Markdown
Member

Problem

readtime() is documented to return the estimated reading time in minutes, with a 1 minute minimum. For any text shorter than 200 words it returns "0" instead:

{{ readtime(page.content) }} min  {# → "0 min" on a short post #}

Cause

$min = floor($words / 200);
if ($min === 0) {
    return '1';
}

floor() returns a float, so the strict comparison 0.0 === 0 is always false and the minimum guard is dead code. (string) 0.0 then yields "0".

Fix

Cast to int and enforce the minimum with max(), so it holds whatever the word count:

$min = (int) floor($words / 200);

return (string) max($min, 1);

Tests

Adds tests/Unit/Renderer/Extension/ContentTest.php covering the 1 minute minimum (null, empty string, short text), the 200 words/minute rate, and that markup is ignored.

The full unit suite passes (243 tests), phpstan is clean, and php-cs-fixer reports no change on the touched files.

Note (out of scope)

While writing the tests I noticed two unrelated quirks of the current implementation, left untouched here:

  • strip_tags() concatenates words across tag boundaries (<p>a</p><p>b</p> → ab), so the count is slightly low on markup without whitespace between blocks;
  • str_word_count() is ASCII-oriented and undercounts accented words, so non-English content reads as shorter than it is.

Happy to open a follow-up if you want either addressed.

🤖 Generated with Claude Code

`floor()` returns a float, so the `$min === 0` guard meant to enforce a
1 minute minimum was never true: a text of less than 200 words returned
the string "0" instead of "1".

Cast the result to int and use `max()` so the minimum is enforced
whatever the word count.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ArnaudLigny
ArnaudLigny merged commit e803288 into master Sep 20, 2026
19 checks passed
@ArnaudLigny
ArnaudLigny deleted the fix/readtime-minimum branch September 20, 2026 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant