Number::spell
Spells a number out in words, with optional thresholds for where spelling starts or stops.
Number::spell(int|float $number, ?string $locale = null, ?int $after = null, ?int $until = null): string- Added in Laravel 10.33.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$number | int|float | The value to spell out. |
$$localeoptional | ?string= null | ICU locale supplying the spell-out rules. Falls back to the Number class locale. |
$$afteroptional | ?int= null | Only spell numbers strictly greater than this; anything at or below is returned as digits. |
$$untiloptional | ?int= null | Only spell numbers strictly below this; anything at or above is returned as digits. |
Return value
stringThe number written as words, or the formatted digits when a threshold excludes it.
Errors
Throws RuntimeException when the intl PHP extension is not loaded.
Changelog
- PHP 10.33.0Introduced together with the Illuminate\Support\Number class.
- PHP 10.41.0Added the $after and $until threshold parameters.
Number::spell() runs the value through ICU's spell-out rules: 102 becomes one hundred and two, and with locale: 'fr', 88 becomes quatre-vingt-huit. It is the right tool for cheque amounts, legal text, and the typographic convention that small numbers are written as words while large ones stay as digits.
The thresholds exclude their own boundary
This is where people get caught. $until returns digits when $number >= $until, and $after returns digits when $number <= $after. So spell(10, until: 10) gives 10, not ten, and spell(10, after: 10) also gives 10. Both boundaries are exclusive of the word form. For the common house style "spell out one through nine", pass until: 10.
Excluded values still get formatted
When a threshold rejects a value the method does not return it untouched — it returns Number::format($number, locale: $locale), so grouping separators are applied and a large float may be rounded to three decimals by ICU's default. Pass both after and until together only when you want a spelled band in the middle and digits at both ends.
Example
When to use it
- Writing a cheque or contract amount out in words
- Applying a style guide that spells numbers below ten but not above
- Rendering a quantity in words for an accessibility-focused summary
Frequently asked questions
Why does Number::spell(10, until: 10) return 10 instead of ten?
Because the threshold is exclusive: the method returns digits when the number is greater than or equal to until. To spell ten as a word, pass until: 11, and use until: 10 for the common 'spell one through nine' rule.
What is the difference between after and until?
until spells numbers below the threshold and prints digits at or above it; after does the opposite, printing digits at or below the threshold and spelling numbers above it. Pass both to spell only a band in the middle.
Can Number::spell write numbers in another language?
Yes, pass a locale — Number::spell(88, locale: 'fr') gives quatre-vingt-huit. Coverage depends on your ICU build, and locales without spell-out rules fall back to a less useful output rather than throwing.
More examples
A house style: words below ten
Prints one, five and nine as words, then 10, 11 and 1,500 as digits. Note the last line: the rejected value goes through Number::format(), so it gains a thousands separator rather than being echoed raw.
<?php
use Illuminate\Support\Number;
foreach ([1, 5, 9, 10, 11, 1500] as $count) {
printf("%s comment%s\n", Number::spell($count, until: 10), $count === 1 ? '' : 's');
}Both thresholds at once
Values at or below 10 and at or above 100 come back as digits; only the band strictly between them is spelled — eleven, twenty, twenty-one, ninety-nine. The after check runs first, so when the two ranges overlap, after wins.
<?php
use Illuminate\Support\Number;
foreach ([3, 10, 11, 20, 21, 99, 100] as $n) {
printf("%-5s => %s\n", $n, Number::spell($n, after: 10, until: 100));
}Cheque wording
Prints 'one thousand two hundred and forty-two dollars and five cents ($1,242.05)'. Splitting the amount in integer cents before spelling avoids handing a float to the formatter, which would spell the fractional part digit by digit.
<?php
use Illuminate\Support\Number;
$cents = 124205;
$dollars = intdiv($cents, 100);
$remainder = $cents % 100;
printf(
"%s dollars and %s cents (%s)\n",
Number::spell($dollars),
Number::spell($remainder),
Number::currency($cents / 100)
);
Discussion