Number::spell

Spells a number out in words, with optional thresholds for where spelling starts or stops.

Signature
Number::spell(int|float $number, ?string $locale = null, ?int $after = null, ?int $until = null): string
  • Added in Laravel 10.33.0

Parameters

ParameterTypeDescription
$$numberint|floatThe value to spell out.
$$localeoptional?string= nullICU locale supplying the spell-out rules. Falls back to the Number class locale.
$$afteroptional?int= nullOnly spell numbers strictly greater than this; anything at or below is returned as digits.
$$untiloptional?int= nullOnly 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.