54

Let's start with simple piece of code to format money with NumberFormatter:

$formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $formatter->formatCurrency(123456789, 'JPY');

This prints: ¥123,456,789.

This is ok if you want to format money.

But what I want to do is to get currency symbol (e.g. ¥) for given currency ISO 4217 code (e.g. JPY).

My first guess was to try using:

$formatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL);

But that gives currency symbol for locale given in constructor (en_US), $ in my case.

Is there a way to get currency symbol by currency ISO 4217 code in PHP?

umpirsky
  • 9,902
  • 13
  • 71
  • 96
  • The problem is that the currency symbol can appear either before or after the number. What are you using the symbol for? – Tom B Dec 16 '12 at 00:44
  • 4
    Just do a regex for anything thats not a digit or a comma. Something like `/[^0-9,]*/`. – rmobis Dec 16 '12 at 00:45
  • Some of the symbols will be multi-byte so a simple string search won't work very well. – kittycat Dec 16 '12 at 01:06
  • I want to avoid regex. Actually, I wanted to fix https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php#L106 and get rid of this regex, I thought PHP supports this. Thanks anyway. – umpirsky Dec 16 '12 at 01:13
  • The most useful related resource I have found is [this](http://stackoverflow.com/questions/4483158/python-convert-currency-code-to-its-sign) (yes, it's python, but all those functions are available in PHP), which is a bit of a nasty "solution". The root of the problem is that this functionality is dependent on the host OS having the appropriate locale information available - but at the same time I don't see a reason for this not to be possible within those restrictions. – DaveRandom Dec 16 '12 at 01:19
  • @DaveRandom I tried and `currency_symbol` and most of other data is empty for some reason. Thanks. – umpirsky Dec 16 '12 at 09:42

9 Answers9

60

First of all, there is no international global currency symbol table, that anyone on the planet could read and understand.

In each region/country the currency symbols will differ, that`s why you must determine them based on who is reading, using the browser / user locale.

The correct way is as you guessed, using NumberFormatter::CURRENCY_SYMBOL, but you first have to set the appropriate locale like en-US@currency=JPY:

$locale='en-US'; //browser or user locale
$currency='JPY';
$fmt = new NumberFormatter( $locale."@currency=$currency", NumberFormatter::CURRENCY );
$symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
header("Content-Type: text/html; charset=UTF-8;");
echo $symbol;

This way the symbol will be understandable by the user.

For example, $symbol will be:

  • Canadian dollar (CAD) : CA$ in USA, CAD in Romania , $CA in Iran
  • Iran Rial (IRR): IRR in USA, while in Iran will be
idragosalex
  • 1,585
  • 1
  • 12
  • 8
  • Excellent!! +1. I just wish there was a way to retrieve `locale` based on currency `iso`. Something like `rlocaleconv(int_curr_symbol, 'JPY')` or so! – Fr0zenFyr Jan 27 '17 at 13:14
26

I achieved this using https://github.com/symfony/Intl:

Symfony\Component\Intl\Intl::getCurrencyBundle()->getCurrencySymbol('EUR')

returns

'€'.

Symfony version > 4.3

It's worth pointing out for SF4.3 and above this has been deprecated:

/**
 * Returns the bundle containing currency information.
 *
 * @return CurrencyBundleInterface The currency resource bundle
 *
 * @deprecated since Symfony 4.3, to be removed in 5.0. Use {@see Currencies} instead.
 */
public static function getCurrencyBundle(): CurrencyBundleInterface
{

So, instead you can do:

use Symfony\Component\Intl\Currencies;
echo Currencies::getSymbol('AUD'); 
flumingo
  • 513
  • 2
  • 7
  • 24
umpirsky
  • 9,902
  • 13
  • 71
  • 96
5

Since the symbols can be multi-byte I used mb_*() functions to correctly grab the all non-punctuation and non-digit chars which would just leaves the symbol.

function get_currency_symbol($string)
{
    $symbol = '';
    $length = mb_strlen($string, 'utf-8');
    for ($i = 0; $i < $length; $i++)
    {
        $char = mb_substr($string, $i, 1, 'utf-8');
        if (!ctype_digit($char) && !ctype_punct($char))
            $symbol .= $char;
    }
    return $symbol;
}

$format = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$string = $format->formatCurrency(123456789, 'JPY');
echo get_currency_symbol($string);
kittycat
  • 14,983
  • 9
  • 55
  • 80
  • Currency symbols may be more than one character, e.g., Estonia Kroon = "kr". – Niko Dec 16 '12 at 01:24
  • Currency symbol is not always one char http://en.wikipedia.org/wiki/Currency_sign. Thanks. – umpirsky Dec 16 '12 at 09:47
  • @umpirsky please see updated code which supports multi-char symbols. – kittycat Dec 16 '12 at 20:00
  • Yes, but it's hacky, similar to https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php#L106 I will accept it if I find no other solution. Thanks. – umpirsky Dec 17 '12 at 07:28
5

If you set the locale using this function setlocale("LC_ALL", "es_AR"); You can use localeconv()['currency_symbol'] or localeconv()['int_curr_symbol'] to get the locale currency symbol and the international variation of the currency symbol.

1

You can use Symfony Intl Component

Install it via composer using composer require symfony/intl

Then get the HTML symbol with the following

use Symfony\Component\Intl\Currencies;
\Locale::setDefault('en');
$symbol = Currencies::getSymbol('INR'); // => '₹'
echo $symbol;
aphoe
  • 2,586
  • 1
  • 27
  • 31
1

I used this code and this code in php

   /**
   <?php
      $CS = new NumberFormatter('en_PH', NumberFormatter::CURRENCY);
      $CS = $CS->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
   ?>
   */

I got a currency symbol of Philippine Peso ₱₱₱₱

I also tried HTML code '&#8369' for Philippine Peso ₱. But it does not working when using in php server php mail specially if you are using an email server.

Try this code.

Marvin
  • 39
  • 7
0

Cryptic has a good answer, but there is a simpler way to do it:

preg_replace('#[a-z0-9.]*#i', '', $formatter->formatCurrency('0', $currency))

This is a nice simple inline solution that doesn't require declaring another function, however it also doesn't properly handle all cases - i.e. currencies where letters are part of the output. But for distinguishing between e.g. $ and £, it works fine.

Benubird
  • 18,551
  • 27
  • 90
  • 141
0
Zend_Locale::getTranslationList('CurrencySymbol')

Will give you an associative array of 3 letter currency codes to their symbol.

Can then use like this:

$curArr = Zend_Locale::getTranslationList('CurrencySymbol');
echo $curArr['GBP'];
Mc User
  • 33
  • 4
-3

Try this variant:

$formatter->getSymbol(NumberFormatter::INTL_CURRENCY_SYMBOL);