public static function numberFormat(
        $value,
        $decimals = null,
        $locale = null,
        $show_thousands_separator = true
    ) {
        // look up decimal precision if none is provided
        if ($decimals === null) {
            $decimals = self::getDecimalPrecision($value);
        }

        // number_format can't handle UTF-8 separators, so insert placeholders
        $output = number_format(
            $value,
            $decimals,
            '.',
            $show_thousands_separator ? ',' : ''
        );

        if ($locale !== null) {
            $old_locale = setlocale(LC_ALL, 0);
            if (setlocale(LC_ALL, $locale) === false) {
                throw new SwatException(
                    sprintf(
                        'Locale %s passed to the ' .
                            'numberFormat() method is not valid for this operating ' .
                            'system.',
                        $locale
                    )
                );
            }
        }

        // get character set of the locale that is used
        $character_set = nl_langinfo(CODESET);

        // replace placeholder separators with locale-specific ones which
        // might contain non-ASCII
        $lc = localeconv();
        $output = str_replace('.', $lc['decimal_point'], $output);
        $output = str_replace(',', $lc['thousands_sep'], $output);

        // convert output to UTF-8
        if ($character_set !== 'UTF-8') {
            $output = iconv($character_set, 'UTF-8', $output);
            if ($output === false) {
                throw new SwatException(
                    sprintf(
                        'Could not convert %s output to UTF-8',
                        $character_set
                    )
                );
            }
        }

        if ($locale !== null) {
            setlocale(LC_ALL, $old_locale);
        }

        return $output;
    }