Source for file Numbers.php
Documentation is available at Numbers.php
* ----------------------------------------------------------------------
* Copyright (c) 2006-2012 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-2012 Khaled Al-Sham'aa
* @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
* @link http://www.ar-php.org
// New in PHP V5.3: Namespaces
// namespace I18N\Arabic;
// $obj = new I18N\Arabic\Numbers();
// $obj = new Arabic\Numbers();
// use I18N\Arabic\Numbers as Numbers;
* This PHP class spell numbers in the Arabic idiom
* @author Khaled Al-Sham'aa <khaled@ar-php.org>
* @copyright 2006-2012 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();
* 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;
* 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 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) {
array_push($items, $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;
array_push($items, 'ال' . $this->_ordering[$ones][$this->_feminine]);
array_push($items, 'ال' . $this->_individual[$tens][$this->_format]);
if ($number == 2 || $number == 12) {
} elseif ($number < 20) {
array_push($items, $this->_individual[$number][$this->_feminine]);
$tens = floor($number / 10) * 10;
array_push($items, $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 using
* @author Khaled Al-Sham'aa <khaled@ar-php.org>
$str = strtr("$number", $this->_arabicIndic);
|