Source for file Numbers.php
Documentation is available at Numbers.php 
 * ----------------------------------------------------------------------  
 * Copyright (c) 2006-2016 Khaled Al-Sham'aa.  
 * ----------------------------------------------------------------------  
 * This program is open source product; you can redistribute it and/or  
 * modify it under the terms of the GNU Lesser General Public License (LGPL)  
 * as published by the Free Software Foundation; either version 3  
 * of the License, or (at your option) any later version.  
 * This program is distributed in the hope that it will be useful,  
 * but WITHOUT ANY WARRANTY; without even the implied warranty of  
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 * GNU Lesser General Public License for more details.  
 * You should have received a copy of the GNU Lesser General Public License  
 * along with this program.  If not, see <http://www.gnu.org/licenses/lgpl.txt>.  
 * ----------------------------------------------------------------------  
 * Class Name: Spell numbers in the Arabic idiom  
 * Original    Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>  
 * Purpose:    Spell numbers in the Arabic idiom  
 * ----------------------------------------------------------------------  
 * Spell numbers in the Arabic idiom  
 * PHP class to spell numbers in the Arabic idiom. This function is very  
 * useful for financial applications in Arabic for example.  
 * If you ever have to create an Arabic PHP application built around invoicing or  
 * accounting, you might find this class useful. Its sole reason for existence is  
 * to help you translate integers into their spoken-word equivalents in Arabic  
 * How is this useful? Well, consider the typical invoice: In addition to a  
 * description of the work done, the date, and the hourly or project cost, it always  
 * includes a total cost at the end, the amount that the customer is expected  
 * To avoid any misinterpretation of the total amount, many organizations (mine  
 * included) put the amount in both words and figures; for example, $1,200 becomes  
 * "one thousand and two hundred dollars." You probably do the same thing every time  
 * Now take this scenario to a Web-based invoicing system. The actual data used to  
 * generate the invoice will be stored in a database as integers, both to save space  
 * and to simplify calculations. So when a printable invoice is generated, your Web  
 * application will need to convert those integers into words, this is more clarity  
 * This class will accept almost any numeric value and convert it into an equivalent  
 * string of words in written Arabic language (using Windows-1256 character set).  
 * The value can be any positive number up to 999,999,999 (users should not use  
 * commas). It will take care of feminine and Arabic grammar rules.  
 *     include('./I18N/Arabic.php');  
 *     $obj = new I18N_Arabic('Numbers');  
 *     $text = $obj->int2str($integer);  
 *     echo "<p align=\"right\"><b class=hilight>$integer</b><br />$text</p>";  
 *     $text = $obj->int2str($integer);  
 *     echo "<p align=\"right\"><b class=hilight>$integer</b><br />$text</p>";  
 * @author    Khaled Al-Sham'aa <khaled@ar-php.org>  
 * @copyright 2006-2016 Khaled Al-Sham'aa  
 * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>  
 * @link      http://www.ar-php.org  
 * This PHP class spell numbers in the Arabic idiom  
 * @author    Khaled Al-Sham'aa <khaled@ar-php.org>  
 * @copyright 2006-2016 Khaled Al-Sham'aa  
 * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>  
 * @link      http://www.ar-php.org  
    private $_individual    =  array();  
    private $_complications =  array();  
    private $_arabicIndic   =  array();  
    private $_ordering      =  array();  
    private $_currency      =  array();  
    private $_spell         =  array();  
     * Loads initialize values  
    public function __construct()  
        foreach ($xml->xpath("//individual/number[@gender='male']") as $num) {  
            if (isset ($num['grammar'])) {  
                $grammar =  $num['grammar'];  
                $this->_individual["{ $num['value']}"][1]["$grammar"] = (string) $num;  
                $this->_individual["{ $num['value']}"][1] = (string) $num;  
        foreach ($xml->xpath("//individual/number[@gender='female']") as $num) {  
            if (isset ($num['grammar'])) {  
                $grammar =  $num['grammar'];  
                $this->_individual["{ $num['value']}"][2]["$grammar"] = (string) $num;  
                $this->_individual["{ $num['value']}"][2] = (string) $num;  
        foreach ($xml->xpath("//individual/number[@value>19]") as $num) {  
            if (isset ($num['grammar'])) {  
                $grammar =  $num['grammar'];  
                $this->_individual["{ $num['value']}"]["$grammar"] = (string) $num;  
                $this->_individual["{ $num['value']}"] = (string) $num;  
        foreach ($xml->complications->number as $num) {  
            $format =  $num['format'];  
            $this->_complications["$scale"]["$format"] = (string) $num;  
        foreach ($xml->arabicIndic->number as $html) {  
            $this->_arabicIndic["$value"] =  $html;  
        foreach ($xml->xpath("//order/number[@gender='male']") as $num) {  
            $this->_ordering["{ $num['value']}"][1] = (string) $num;  
        foreach ($xml->xpath("//order/number[@gender='female']") as $num) {  
            $this->_ordering["{ $num['value']}"][2] = (string) $num;  
        $expression =  "//individual/number[@value<11 or @value>19]";  
        foreach ($xml->xpath($expression) as $num) {  
            $str =  str_replace(array('أ','إ','آ'), 'ا', (string) $num);  
            $this->_spell[$str] = (integer) $num['value'];  
        foreach ($xml->xpath("//currency") as $info) {  
            $money_ar =  $info->money->arabic;  
            $money_en =  $info->money->english;  
            $this->_currency["{ $info->iso}"]['ar']['basic']    =  $money_ar->basic;  
            $this->_currency["{ $info->iso}"]['ar']['fraction'] =  $money_ar->fraction;  
            $this->_currency["{ $info->iso}"]['en']['basic']    =  $money_en->basic;  
            $this->_currency["{ $info->iso}"]['en']['fraction'] =  $money_en->fraction;  
            $this->_currency["{ $info->iso}"]['decimals'] =  $info->money->decimals;  
     * Set feminine flag of the counted object  
     * @param integer $value Counted object feminine  
     *                       (1 for masculine & 2 for feminine)  
     * @return object $this to build a fluent interface  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        if ($value ==  1 ||  $value ==  2) {  
            $this->_feminine =  $value;  
     * Set the grammar position flag of the counted object  
     * @param integer $value Grammar position of counted object  
     *                        (1 if Marfoua & 2 if Mansoub or Majrour)  
     * @return object $this to build a fluent interface  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        if ($value ==  1 ||  $value ==  2) {  
     * Set the ordering flag, is it normal number or ordering number  
     * @param integer $value Is it an ordering number? default is 1  
     *                        (use 1 if no and 2 if yes)  
     * @return object $this to build a fluent interface  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        if ($value ==  1 ||  $value ==  2) {  
     * Get the feminine flag of counted object  
     * @return integer return current setting of counted object feminine flag  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
     * Get the grammer position flag of counted object  
     * @return integer return current setting of counted object grammer  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
     * Get the ordering flag value  
     * @return integer return current setting of ordering flag value  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
     * Spell integer number in Arabic idiom  
     * @param integer $number The number you want to spell in Arabic idiom  
     * @return string The Arabic idiom that spells inserted number  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        if ($number ==  1 &&  $this->_order ==  2) {  
            if ($this->_feminine ==  1) {  
                $number = (string) - 1 *  $number;  
                $string .=  ' فاصلة ' .  $dec;   
     * Spell number in Arabic idiom as money  
     * @param integer $number The number you want to spell in Arabic idiom as money  
     * @param string  $iso    The three-letter Arabic country code defined in  
     * @param string  $lang   The two-letter language code in ISO 639-1 standard  
     * @return string The Arabic idiom that spells inserted number as money  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
    public function money2str($number, $iso= 'SYP', $lang= 'ar')  
        $number =  sprintf("%01.{$this->_currency[$iso]['decimals']}f ", $number);  
            $string .=  ' ' .  $this->_currency[$iso][$lang]['basic'];  
        if (!empty($temp[1]) &&  $temp[1] !=  0) {  
            $string .=  ' ' .  $this->_currency[$iso][$lang]['fraction'];  
     * Convert Arabic idiom number string into Integer  
     * @param string $str The Arabic idiom that spells input number  
     * @return integer The number you spell it in the Arabic idiom  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        $ptr =  array('ـ', 'َ','ً','ُ','ٌ','ِ','ٍ','ْ','ّ');  
        $ptr =  array('اثنا','اثني','اثنتا', 'اثنتي');  
        if (strpos($str, 'ناقص') ===  false  
            &&  strpos($str, 'سالب') ===  false 
        $max     =  count($this->_complications);  
        for ($scale= $max; $scale> 0; $scale-- ) {  
            $key =  pow(1000, $scale);  
            $pattern =  array('أ','إ','آ');  
            $format1 =  str_replace($pattern, 'ا', $this->_complications[$scale][1]);  
            $format2 =  str_replace($pattern, 'ا', $this->_complications[$scale][2]);  
            $format3 =  str_replace($pattern, 'ا', $this->_complications[$scale][3]);  
            $format4 =  str_replace($pattern, 'ا', $this->_complications[$scale][4]);  
            if (strpos($str, $format1) !==  false) {  
                list ($temp, $str) =  explode($format1, $str); 
                $segment[$key]    =  'اثنان';  
            } elseif (strpos($str, $format2) !==  false) {  
                list ($temp, $str) =  explode($format2, $str); 
                $segment[$key]    =  'اثنان';  
            } elseif (strpos($str, $format3) !==  false) {  
                list ($segment[$key], $str) =  explode($format3, $str); 
            } elseif (strpos($str, $format4) !==  false) {  
                list ($segment[$key], $str) =  explode($format4, $str); 
                if ($segment[$key] ==  '') {  
            if ($segment[$key] !=  '') {  
                $segment[$key] =  trim($segment[$key]);  
        $segment[1] =  trim($str);  
        foreach ($segment as $scale =>  $str) {  
            foreach ($this->_spell as $word =>  $value) {  
                if (strpos($str, "$word ") !==  false) {  
            $total   +=  $subTotal *  $scale;  
     * Spell integer number in Arabic idiom  
     * @param integer $number The number you want to spell in Arabic idiom  
     * @param logical $zero   Present leading zero if true [default is true]  
     * @return string The Arabic idiom that spells inserted number  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
    protected function subInt2str($number, $zero =  true)  
        $number =  ($zero !=  false) ?  trim($number) :  trim((float) $number);  
            //--- by Jnom: handle left zero  
                while (($fulnum[0]) ==  '0') {  
            $blocks_num =  count($blocks) -  1;  
            for ($i =  $blocks_num; $i >=  0; $i-- ) {  
                $number =  floor($blocks[$i]);  
                    if ($number ==  1 &&  $i !=  0) {  
                        $text =  $this->_complications[$i][4];  
                        if ($this->_order ==  2) {  
                    } elseif ($number ==  2 &&  $i !=  0) {  
                        $text =  $this->_complications[$i][$this->_format];  
                        if ($this->_order ==  2) {  
                    } elseif ($number >  2 &&  $number <  11 &&  $i !=  0) {  
                        $text .=  ' ' .  $this->_complications[$i][3];  
                        if ($this->_order ==  2) {  
                        $text .=  ' ' .  $this->_complications[$i][4];  
                        if ($this->_order ==  2) {  
                    //--- by Jnom: handle left zero  
                    if ($text !=  '' &&  $zeros !=  '' &&  $zero !=  false) {  
                        $text  =  $zeros. ' '. $text;  
     * Spell sub block number of three digits max in Arabic idiom  
     * @param integer $number Sub block number of three digits max you want to  
     * @return string The Arabic idiom that spells inserted sub block  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
            $hundred =  floor($number /  100) *  100;  
            if ($this->_order ==  2) {  
                    $pre. $this->_individual[$hundred][$this->_format]  
                array_push($items, $pre. $this->_individual[$hundred]);  
            if ($this->_order ==  2) {  
                    array_push($items, $this->_ordering[$number][$this->_feminine]);  
                } elseif ($number <  20) {  
                    $item    =  'ال' .  $this->_ordering[$number][$this->_feminine];  
                    if ($this->_feminine ==  1) {  
                    $tens =  floor($number /  10) *  10;  
                        'ال' .  $this->_ordering[$ones][$this->_feminine]  
                        'ال' .  $this->_individual[$tens][$this->_format]  
                if ($number ==  2 ||  $number ==  12) {  
                        $this->_individual[$number][$this->_feminine][$this->_format]  
                } elseif ($number <  20) {  
                        $this->_individual[$number][$this->_feminine]  
                    $tens =  floor($number /  10) *  10;  
                            $this->_individual[2][$this->_feminine][$this->_format]  
                            $this->_individual[$ones][$this->_feminine]  
                    array_push($items, $this->_individual[$tens][$this->_format]);  
     * Represent integer number in Arabic-Indic digits using HTML entities  
     * @param integer $number The number you want to present in Arabic-Indic digits  
     * @return string The Arabic-Indic digits represent inserted integer number  
     * @author Khaled Al-Sham'aa <khaled@ar-php.org>  
        $str =  strtr("$number", $this->_arabicIndic);  
 
 
        
       |