Code Monkey home page Code Monkey logo

number-to-words's Introduction

PHP Number to words converter

CircleCI Code Climate Test Coverage Latest Stable Version

Welcome to number-to-words, a PHP utility that seamlessly transforms numeric values into their corresponding words. Effortlessly convert numbers, such as 123, into expressive and readable formats like "one hundred and twenty-three" with just a few lines of code.

Installation

Add package to your composer.json by running:

$ composer require kwn/number-to-words

Usage

There are two types of number-to-words transformation: number and currency. In order to use a relevant transformer for specific language create an instance of NumberToWords class and call a method that creates a new instance of the desired transformer;

Number Transformer

Create a transformer for specific language using the getNumberTransformer('lang') method:

use NumberToWords\NumberToWords;

// create the number to words "manager" class
$numberToWords = new NumberToWords();

// build a new number transformer using the RFC 3066 language identifier
$numberTransformer = $numberToWords->getNumberTransformer('en');

Transformer can be used by passing in numeric values to the toWords() method:

$numberTransformer->toWords(5120); // outputs "five thousand one hundred twenty"

It can be also used with a static method:

NumberToWords::transformNumber('en', 5120); // outputs "five thousand one hundred twenty"

Currency Transformer

Creating a currency transformer works just like a number transformer.

use NumberToWords\NumberToWords;

// create the number to words "manager" class
$numberToWords = new NumberToWords();

// build a new currency transformer using the RFC 3066 language identifier
$currencyTransformer = $numberToWords->getCurrencyTransformer('en');

Then it can be used passing in numeric values for amount and ISO 4217 currency identifier to the toWords() method:

$currencyTransformer->toWords(5099, 'USD'); // outputs "fifty dollars ninety nine cents"

It can be also used with a static method:

NumberToWords::transformCurrency('en', 5099, 'USD'); // outputs "fifty dollars ninety nine cents"

Note: The Currency Transformer within this library processes integers; ensure your input amounts are in whole numbers by multiplying any float values by 100 before transformation. For instance, transform 45.67 by using 4567 as the input for accurate currency conversion.

Available locale

Language Identifier Number Currency
Albanian al + +
Arabic ar + +
Azerbaijani az + +
Belgian French fr_BE + -
Brazilian Portuguese pt_BR + +
Bulgarian bg + +
Czech cs + -
Danish dk + +
Dutch nl + -
English en + +
Estonian et + -
Georgian ka + +
German de + +
French fr + +
Hungarian hu + +
Indonesian id + +
Italian it + -
Kurdish ku + -
Lithuanian lt + +
Latvian lv + +
Macedonian mk + -
Malay ms + +
Persian fa + -
Polish pl + +
Romanian ro + +
Serbian sr + +
Slovak sk + +
Spanish es + +
Russian ru + +
Swedish sv + -
Turkish tr + +
Turkmen tk + +
Ukrainian ua + +
Uzbek uz + +
Yoruba yo + +

Contributors

Some transformers were ported from the pear/Numbers_Words library. Others were created by contributors. Thank you!

Version 2.x - BC and major changes

  • Dropped support for PHP <7.4.
  • Added typehints for NumberTransformer and CurrencyTransformer interfaces. Now both accept integer numbers only (Albanian language might be affected).
  • Added support for PSR12.

Questions and answers

Q: What should I do if I encounter a bug while using the library?

A: If you come across a bug, please open an issue on our GitHub repository. As I may not be proficient in all languages, we encourage users to submit fixes and collaborate to enhance the library's functionality.

Q: My language is missing. Could it be added?

A: There's a high chance I don't know your language. Feel free to implement the missing language and open a pull request. You can use the existing languages as a reference.

number-to-words's People

Contributors

andreybolonin avatar coupej avatar creeppork avatar cristiangomeze avatar develgold avatar djunehor avatar goodot avatar havryshkevych avatar iamdual avatar ickbinhier avatar igorzavaleev avatar janhartigan avatar kongulov avatar kwn avatar leonardjke avatar mahdimajidzadeh avatar maksa988 avatar miansaleem avatar olimovv avatar olivermbs avatar popovserhii avatar pudovmaxim avatar samnela avatar shahonseven avatar sorokinws avatar uguurozkan avatar veguss avatar wbrframe avatar xeux avatar zehir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

number-to-words's Issues

Error with cents (USD)

I am trying to convert money to words. But I don't know what happen with this number: 584.93 The library show me: Five Hundred Eighty-Four Dollars Ninety-Two Cents.

use NumberToWords\NumberToWords;
$numberToWords = new NumberToWords();
$currencyTransformer = $numberToWords->getCurrencyTransformer('en')->toWords(584.93*100, 'USD');
echo $currencyTransformer;

It is not ninety-two. It is ninety-three. Why does this happen?

BUG : Amount in currency conversion "fr" / JPY

We use this package in production and we found an issue with it.

Here the tested code :

(new NumberToWords())
                ->getCurrencyTransformer('fr')
                ->toWords(1000, 'JPY')
            ;

Here the raised error : "Array to string conversion"

Notice that it works with 100 => "un yen"

But not with 101 for instance => "Undefined offset: 1"

Can you fix it, please ?

As a complementary remark, it will be a great addition to have a method that return the supported combinaison between Currency and Langage.

Best regards.

New Addition

Also add currency 'INR' with Language 'hindi'

UAH not cent

'UAH' => [ [2, 'гривна', 'гривны', 'гривен'], [1, 'цент', 'цента', 'центов']
1 UAH = 100 копеек, is called as well as a Russian kopeyka
You should change [ 'цент', 'цента', 'центов'] to [ 'копейка', 'копейки', 'копеек']

Releases

Hey, could you create releses tags with major changes in the package?

FrenchCurrencyTransformer

First Of All Congrat and Thank you ForThe usefull Library ;

Just Notice That FrenchCurrencyTransformer is not Present in NumberToWords Class on the $currencyTransformers , wich lead to an error " Currency transformer for "fr" language is not implemented "

brazilian portuguese typo - word cinqüenta

Hi.

just a little issue. in brazilian portuguese the character ü in word cinqüenta is not used anymore. now it's just the character 'u'
please, change cinqüenta to cinquenta in file \src\Legacy\Numbers\Words\Locale\Pt\BR.php

Thanks!

Wrong decimal conversion

Using v1.9.2 or v1.12.0, numbers 64.74, 65.74, 66.74 etc. up to 81.74 are all given decimal words of 73 instead of 74, that is 'seventy-three' in English (or 'soixante treize' in French which I use) in whatever currency selected.

Typo in the romanian CurrencyTransformer

\Kwn\NumberToWords\Language\Romanian\Transformer\CurrencyTransformer.php at line 53
$ret .= ' ' . $this->toWords($fraction, $currNouns[1]); should actually be
$ret .= ' ' . $this->transformer->toWords($fraction, $currNouns[1]);

[ru] Incorrect sextillion tests

Number: 2342535345365393436:

Expected:

два секстиллиона триста сорок два квадриллиона пятьсот тридцать пять триллионов триста сорок пять миллиардов триста шестьдесят пять миллионов триста девяноста три тысячи четыреста тридцать шесть

Actual:

два секстиллиона триста сорок два квадриллиона пятьсот тридцать пять триллионов триста сорок пять миллиардов триста шестьдесят пять миллионов триста девяносто три тысячи четыреста восемь


Second number: 5342535345365393436:

Expected:

пять секстиллионов триста сорок два квадриллиона пятьсот тридцать пять триллионов триста сорок пять миллиардов триста шестьдесят пять миллионов триста девяноста три тысячи четыреста тридцать шесть

Actual:

пять секстиллионов триста сорок два квадриллиона пятьсот тридцать пять триллионов триста сорок пять миллиардов триста шестьдесят пять миллионов триста девяносто три тысячи четыреста восемь

throw exception when use unsupported currency

when use this package with project that have dynamic currencies, and user add new currency not supported by this package it will throw exception "Currency "%s" is not available for "%s" language",

I think if we return an empty array it will be better.

Error on installation

Hi I'm trying to install this library but I always get this error. How can I solve it?

An uncaught Exception was encountered

Type: ParseError

Message: syntax error, unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST)

Filename: /var/www/clients/client0/web14/web/application/vendor/kwn/number-to-words/src/Concerns/ManagesCurrencyTransformers.php

Adding localization of zh_ZH

Hi! I am very interested in your library, however - we also work with the Chinese language, and I would like to see the localization of zh_ZH. Can you tell me if it is planned to be added? Or, can I finalize this localization myself, and create a PR for you? Thanks!

Inconsistent fractional part

I have a use case where I convert 1.16 to words in es, I get "un peso con quince centavos" that is wrong, I expected "un peso con dieciseis centavos", then the result is 0.01 less than required, when I read the code I found in Numbers/Words.php file the follow method:

    public function transformToCurrency($amount, $locale, $currency)
    {
        $localeClassName = $this->resolveLocaleClassName($locale);
        $transformer = new $localeClassName($this->options);

        $decimalPart = (int) ($amount / 100);
        $fractionalPart = $amount % 100;

        if (0 === $fractionalPart) {
            return trim($transformer->toCurrencyWords($currency, $decimalPart));
        }

        return trim($transformer->toCurrencyWords($currency, $decimalPart, $fractionalPart));
    }

I found it right and checking in http://phptester.net/ it works right but when I run mi app I get 15 instead of 16 by the fractional part, when I replace with fmod() I get the right value, I don't know the risk of this, but, the fractional part could be calculate by some kind of:

    public function transformToCurrency($amount, $locale, $currency)
    {
        $localeClassName = $this->resolveLocaleClassName($locale);
        $transformer = new $localeClassName($this->options);

        $decimalPart = (int) ($amount / 100);
        $fractionalPart = $amount - ($decimalPart * 100); // <-- suggestion

        if (0 === $fractionalPart) {
            return trim($transformer->toCurrencyWords($currency, $decimalPart));
        }

        return trim($transformer->toCurrencyWords($currency, $decimalPart, $fractionalPart));
    }

I'm working with php7.2/7.3

edit:

The same is happening in Locale/Es.php in

        $d = $number % 10; // <- line 141      
        $t = (int) ($number / 10) % 10;
        $h = (int) ($number / 100) % 10;

exponentSeparator doesn't seem to be used

I've been trying to use the exponent separator, but it doesn't seem to be used anywhere in code (except for it's initialization in a function).
Is the purpose of exponentSeparator to separate triplets with a string?

Minus sign

Currencies below than zero does not display correctly. I propose add minus sign property to Number model or/and use abs function to convert currency correctly.

To words method missing

Hi, I looked into your package and realized the "toWords()" method was missing, Kindly assist!!

Request addition "Mauritian Rupee" (MUR)

Hello,
Please, is it possible to add, for the French language, the currency
"Mauritian Rupee" (MUR).

Fr.php, $currencyNames = [ ... , 'MUR' => [['roupie mauricienne'], ['cents']],]

Thanks :)

Optimal usage

So in #2 we briefly talked about how someone might use this library. Let's talk first about how to use it now. An example:

//build the registry of transformers we want to work with
$registry = new TransformerFactoriesRegistry([
    new EnglishTransformerFactory
]);

//create the number to words "manager" class
$numberToWords = new NumberToWords($registry);

//build a new currency transformer
$currencyTransformer = $numberToWords->getCurrencyTransformer('en', 'USD', SubunitFormat::Words);

//build an Amount that we can pass to the transformer
$amount = new Amount(new Number(50), new Currency('USD'), new SubunitFormat(SubunitFormat::Words));

//do the conversion
$currencyTransformer->toWords($amount); //outputs "fifty dollars and zero cents"

So as a first point, I think we should decide where the currency and subunit format information should live. In the above code, this line:

$numberToWords->getCurrencyTransformer('en', 'USD', SubunitFormat::Words);

Is a bit deceptive because it's not actually creating an English, US Dollar, subunit word transformer. It's creating an English transformer that can convert any Amount into words. The Amount has meta information about its currency and subunit format. I think what's obvious is that the subunit format shouldn't be a part of the Amount because it doesn't really describe the amount, but the transformation that needs to occur. A similar argument could be made for the currency...it's simple a facet of how you convert a particular number into words.

So if we split these concepts off into the transformer creation, we can simplify the data structures a bit:

//this now uses the second and third parameters to instruct the transformer creation
$currencyTransformer = $numberToWords->getCurrencyTransformer('en', 'USD', SubunitFormat::Words);

//do the conversion
$currencyTransformer->toWords(new Number(50)); //outputs "fifty dollars and zero cents"

The one downside of this is that it puts a bit more work up to the service registration layer (i.e. you need to explicitly create an English, USD, subunit word transformer instead of having a more flexible transformer that can be used in a bunch of different ways). However, I think a decently-architected system won't have to worry about this as the transformer dependency needs to be explicitly created anyway.

So then maybe we can do one better by eliminating the Number:

$currencyTransformer->toWords(50); //outputs "fifty dollars and zero cents"
$currencyTransformer->toWords(49.99); //outputs "forty nine dollars and ninety nine cents"

We could still convert that int/float to a Number in the transformer, of course.

Let me know what you think..

Using $digits masculine form

Hello.

I find this library amazing. I'm trying to convert currency to text, which for the language that i have chosen "bg" is not created, but thats ok - i can use the numbers convertor. I've checked the source code and there are 3 different forms .By default it is set to the neutral digit, but I need to use the masculine form. Is there some way to change it ?

 private static $digits = [
        0  => [1 => "едно", "две", "три", "четири", "пет", "шест", "седем", "осем", "девет"], // neuter
        1  => [1 => 'един', 'два'],                                                           // masculine
        -1 => [1 => 'една']                                                                   // feminine
    ];

The only code I use ( and this is an example ) is

$numberToWords =  new \NumberToWords\NumberToWords;
$trans = $numberToWords->getNumberTransformer('bg');
$trans->toWords(2011);

If there is no option to toggle this, is there a way for me to extend the library and do it on my own

tldr. i need to have "един" and "два" Instead of "едно" and "две".

Make NumberTransformerBuilder injectable

First, thank you for your work.

If you use one of the supplied transformers (for example, GermanCurrencyTransformer), there is no way to modify the NumberTransformerBuilder. In my case, I need to customize the "withWordsSeparatedBy()" method, but the rest should stay the same.

Perhaps the CurrencyTransformer interface could get a "getTransformerBuilder()" method so that I can override this method to provde a custom provider in a child class.

Here is a simple example:

class CustomizedGermanCurrencyTransformer extends GermanCurrencyTransformer {

    /**
     * Overrides the default transformer builder to modify builder options
     * 
     * @return \NumberToWords\NumberTransformer\NumberTransformer
     */
    public function getTransformerBuilder()
    {
        return $numberTransformer = (new NumberTransformerBuilder())
            ->withDictionary($dictionary)
            ->withWordsSeparatedBy('')
            ->transformNumbersBySplittingIntoPowerAwareTriplets($numberToTripletsConverter, $tripletTransformer)
            ->inflectExponentByNumbers($exponentInflector)
            ->build();
    }
    
}

Add Breton language

Hello,
How are you,
Will it be possible to add Breton language to this project?

Regards
Pierre

Currencies subunits/fraction

cast "(float) $value" from Number model cuts currency fraction for example:

->toWords(50.99) // works correctly

->toWords(50.90) //does not works correctly cuts currency to 50.9 and displays pięćdziesiąt złotych dziewięć groszy

Documentation - namespace

The documentation is slightly incorrect, you need to instciate it with the namespace:

$numberToWords = new NumberToWords();

It should be:

$numberToWords = new NumberToWords\NumberToWords();

Spanish conversion that ends with 1

When a number ends with 1 the conversion is "....uno pesos" => should be "...un pesos"
when the number is one, the conversion is "uno peso" => should be "un peso"

[cs] typo for number 90

Currently, number transformer generates string devádesát from number 90. However, correct wording is without punctutation above first letter a => devadesát

Persian Support

Hi folks.

I Like the idea of supporting multiple languages in single library. So just tried ti implement Persian based on English classes.

It turned out its not possible to do such using current GenericNumberTransformerBuilder and it needs some modifications ( Adding another property like $tripletSeparator and modifying some parts might solve this but seems overkill to me).

I spent last couple of hours and made a number to words translator from scratch for Persian language. It has same test suite as english test and it is passing.

So was wondering if you have any interests in me creating a NumberTransformer wrapper for this language-specific implementation and make a pull request.

Represent cents as NUMBERS Format

I need to have next output "pięćdziesiąt złotych 98 groszy".
I try use this library as describe in README and get next result "piecdziesiat zlotych 98/100"

$registry = new \Kwn\NumberToWords\Transformer\TransformerFactoriesRegistry([
    new \Kwn\NumberToWords\Language\Polish\TransformerFactory()
]);
$numberToWords = new \Kwn\NumberToWords\NumberToWords($registry);
$currencyTransformer = $numberToWords->getCurrencyTransformer('pl', 'PLN', \Kwn\NumberToWords\Model\SubunitFormat::NUMBERS);
var_dump($currencyTransformer->toWords(50.98)); 
// piecdziesiat zlotych 98/100

What does actually mean this "98/100"?

P.S. I has added support for Ukrainian and Russian languages but before to do PR I want understand how to implement this feature in correct way.

how to force writing zero fraction

how to force write zero fraction, so if i have 144.00 USD i get the fallowing

$currencyTransformer->toWords(14400, 'USD');
one hundred forty-four dollar.

i want to get
one hundred forty-four dollar and zero cent .

Implementing an autoloader for usage without docker

Hi everyone, thanks for the work that you all have put in this library. I am not using docker and when I start calling the method to get the transformer I get a cascade of error. I was wondering whether you could implement an autoloader or if there is a quick way to solve all these "Class not found" errors.

I tried implementing an autoloader but with poor results (I am not an expert in php).

Thank you for your time.

License

Could you please include a license?

Spelling of negative numbers in German: "Minussomething" vs "minus something"

Many thanks for this nice piece of code!

However: I am pretty sure that in German the minus is spelled out separated by a space and in lowercase. But of course: being a German I still may be wrong though the stock PHP NumberFormatter also handles it that way. So it probably should be:
minus fünfzehn instead of the Minusfünfzehn (i.e. spelled out -15 in German).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.