wppaste
WordPress

number_format_i18n( float $number, int $decimals = 0 ): string

Since
2.3.0
Source
wp-includes/functions.php:424

Formats a numeric value using the current locale's decimal point and thousands separator instead of PHP's number_format() defaults. It rounds to the number of decimal places you pass in $decimals (0 by default) and always returns a string, not a float or int. If the global $wp_locale object isn't set yet, it silently falls back to plain number_format() output with a period and comma, so calling it too early in the request can produce unlocalized results.

Converts float number to format based on the locale.

Compatibility

WordPress
since 2.3.0
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$numberfloat
The number to convert based on locale.
$decimalsintoptional
Precision of the number of decimal places. Default 0.Default: 0

Return value

string
Converted number in string format.

Code examples

Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.

Display a price stored in post meta with locale-aware formatting

Post 2 has a price value stored in post meta that should be shown with the site's decimal separator.

$price = get_post_meta( 2, 'price', true );

if ( '' === $price ) {
	$price = 0;
}

$formatted_price = number_format_i18n( (float) $price, 2 );

echo esc_html( 'Price: ' . $formatted_price );

get_post_meta() always returns a string, so cast it to float before passing it in.

Format the average number of comments per post

Loop over posts 1 through 5, average their comment counts, and format the result to one decimal place.

$post_ids = array( 1, 2, 3, 4, 5 );
$total_comments = 0;

foreach ( $post_ids as $post_id ) {
	$total_comments += (int) get_comments_number( $post_id );
}

$average = $total_comments / count( $post_ids );

echo esc_html( 'Average comments per post: ' . number_format_i18n( $average, 1 ) );

Common problems and fixes · 4

Why does number_format_i18n give me a period and comma even though my site is in another language?

The function only uses locale-specific separators when the global $wp_locale object is set. If it runs before WordPress has finished bootstrapping locale data, it silently falls back to PHP's number_format() defaults.

Why did my decimal places disappear from the formatted number?

The $decimals parameter defaults to 0, so any value you pass in gets rounded to a whole number unless you explicitly ask for decimal places.

Can I get number_format_i18n to return a negative number of decimal places or skip rounding entirely?

No. The source passes $decimals through absint() before calling number_format(), so any negative value you supply is converted to its positive equivalent and the number is always rounded to that many places.

How do I change the formatted output site-wide without editing every call?

The function passes its result through the number_format_i18n filter, which also receives the original $number and $decimals arguments (added in 4.9.0), so you can hook it once instead of touching every call site.

Alternatives and related functions

number_format
When you don't need locale-aware separators and just want PHP's native rounding and formatting behavior.
size_format
When you're formatting a byte count (like a file or upload size) rather than an arbitrary number.
WP_Locale
When you need the raw decimal_point or thousands_sep strings for the current locale instead of a fully formatted number.

Performance profile

How much work a call to number_format_i18n() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Trivial

Touches nothing outside its own arguments.

Scaling
Constant

No loop in the body: the same number of instructions runs whatever you pass in.

Instructions
20–27

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 35.

Plugin surface
1 hook

Third-party callbacks on 'number_format_i18n' run inside this call, and their cost is not bounded by anything here.

Called by
50

50 places in core call this, so the cost is paid more often than your own code shows.

What it touches

  • hookthird-party callbacksapply_filters()called directly

What one call costs · 1 distinct outcome

One number would be a lie: the work depends on which branch runs. These are every distinct cost number_format_i18n() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
always20–27absint(), number_format(), apply_filters()

Across PHP versions

Compiles the same on PHP 7.4, 8.1, 8.2, 8.3, 8.4, 8.5 and 8.6-dev: 35 instructions, 20–27 executed per call, 1 branch. The work does not change between versions.

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Hooks and filters fired · 1

One hook fires while number_format_i18n() runs, in this order:

  1. apply_filters( number_format_i18n )filterline 443 (+19 into the body)

    Filters the number formatted based on the locale.

Uses · 2

  • absint()Converts a value to non-negative integer.
  • apply_filters()Calls the callback functions that have been added to a filter hook.

Used by · 50

Show all 50

Source code

function number_format_i18n( $number, $decimals = 0 ) {	global $wp_locale; 	if ( isset( $wp_locale ) ) {		$formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );	} else {		$formatted = number_format( $number, absint( $decimals ) );	} 	/**	 * Filters the number formatted based on the locale.	 *	 * @since 2.8.0	 * @since 4.9.0 The `$number` and `$decimals` parameters were added.	 *	 * @param string $formatted Converted number in string format.	 * @param float  $number    The number to convert based on locale.	 * @param int    $decimals  Precision of the number of decimal places.	 */	return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );}

Changelog

Introduced in 2.3.0. Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

About this page

Parsed data
Generated from the wordpress-develop 6.9.7 tag, from src/wp-includes/functions.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.