I recently ran into a problem with PHP's built-in number_format function. The function is actually quite handy: It allows you to format a number in a manner that is appropriate for the language your website is currently in.

Example: To write the number 4505 and 31 hundredths in English, you'd write "4,505.31". In German or Spanish however, the comma is the decimal separator, in turn using the point as the "digit group separator": "4.505,31". Swiss German, however, uses an apostrophe-like character as a digit group separator: "4'505,31". And so on, and so forth.

All of these are supposedly addressed by using the number_format() function, feeding it the number to be displayed and the regionally appropriate separator characters.

Sadly though, when you do this for Russian and other eastern European languages, your result looks like this:<!--more-->

The reason is that number_format can't handle UTF-8 multi-byte characters (which are commonly used to encode non-ASCII characters, like ü, ß, or the whole Cyrillic alphabet. In fact, this whole blog is served to you in UTF-8-encoded characters.) If you think that's ironic that a function meant to simplify localization cannot handle the characters needed for exactly that purpose, so do I.

Either way, in order not to make our international customers too sad, I wrote a little workaround for this problem, and it's actually quite simple: First it formats the number with placeholders (both "single-byte" characters, so numberformat can handle them), and then it uses strreplace() to replace these characters by the ones appropriate for your current locale.

Here you go, the whole code for your entertainment and use, if you want to. Just, if you use it, I'd appreciate you leaving a comment here. Have fun!

/** * multibyte-safe numberformat function. * Uses regular php numberformat with "safe" placeholders, then replaces * them by their actual (possibly multi-byte) counterparts. */ function mbnumberformat($number, $numdecimalplaces = 0) { $localeconv = localeconv(); $placeholders = array('@', '~'); $actual = array($localeconv['decimalpoint'], $localeconv['thousandssep']); // format number with placeholders $formatted = numberformat($number, $numdecimalplaces, $placeholders[0], $placeholders[1]); // replace by localized characters $formatted = strreplace($placeholders, $actual, $formatted); return $formatted; }

Read more…