summaryrefslogtreecommitdiff
path: root/LedgerSMB/Num2text.pm
blob: ff0ce1fa3da2d8663eaa71ff4ebb714c7aecaceb (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. #
  6. # Copyright (C) 2006
  7. # This work contains copyrighted information from a number of sources all used
  8. # with permission.
  9. #
  10. # This file contains source code included with or based on SQL-Ledger which
  11. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  12. # under the GNU General Public License version 2 or, at your option, any later
  13. # version. For a full list including contact information of contributors,
  14. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  15. #
  16. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  17. # Copyright (C) 2002
  18. #
  19. # Author: DWS Systems Inc.
  20. # Web: http://www.sql-ledger.org
  21. #
  22. # Contributors:
  23. #
  24. #======================================================================
  25. #
  26. # This file has undergone whitespace cleanup.
  27. #
  28. #======================================================================
  29. #
  30. # this is the default code for the Check package
  31. #
  32. #=====================================================================
  33. # The conversion routines can be tested with for example:
  34. # perl <<EOF
  35. # use LedgerSMB::CP;
  36. # my $c = CP->new('da');
  37. # $c->init;
  38. # for(0 .. 202, 999 .. 1002, 1999 .. 2002, 999999 .. 1000002, 999999999 .. 1000000002)
  39. # {print $_.":".$c->num2text($_)."\n";};'
  40. # EOF
  41. sub init {
  42. my $self = shift;
  43. my $locale = $self->{'locale'};
  44. my $langtag = substr( $locale->language_tag, 0, 2 );
  45. $self->{'numrules'} = 'en';
  46. $self->{'numrules'} = $langtag
  47. if grep { /$langtag/ } (qw/ca de es et fr hu it nl ru da/);
  48. $self->{'numrules'} = 'es' if $self->{'numrules'} eq 'ca';
  49. $self->{'numrules'} = 'de' if $self->{'numrules'} eq 'ru';
  50. %{ $self->{numbername} } = (
  51. 0 => $locale->text('Zero'),
  52. 1 => $locale->text('One'),
  53. '1o' => $locale->text('One-o'),
  54. 2 => $locale->text('Two'),
  55. 3 => $locale->text('Three'),
  56. 4 => $locale->text('Four'),
  57. 5 => $locale->text('Five'),
  58. 6 => $locale->text('Six'),
  59. 7 => $locale->text('Seven'),
  60. 8 => $locale->text('Eight'),
  61. 9 => $locale->text('Nine'),
  62. 10 => $locale->text('Ten'),
  63. 11 => $locale->text('Eleven'),
  64. '11o' => $locale->text('Eleven-o'),
  65. 12 => $locale->text('Twelve'),
  66. 13 => $locale->text('Thirteen'),
  67. 14 => $locale->text('Fourteen'),
  68. 15 => $locale->text('Fifteen'),
  69. 16 => $locale->text('Sixteen'),
  70. 17 => $locale->text('Seventeen'),
  71. 18 => $locale->text('Eighteen'),
  72. 19 => $locale->text('Nineteen'),
  73. 20 => $locale->text('Twenty'),
  74. 21 => $locale->text('Twenty One'),
  75. '21o' => $locale->text('Twenty One-o'),
  76. 22 => $locale->text('Twenty Two'),
  77. 23 => $locale->text('Twenty Three'),
  78. 24 => $locale->text('Twenty Four'),
  79. 25 => $locale->text('Twenty Five'),
  80. 26 => $locale->text('Twenty Six'),
  81. 27 => $locale->text('Twenty Seven'),
  82. 28 => $locale->text('Twenty Eight'),
  83. 29 => $locale->text('Twenty Nine'),
  84. 30 => $locale->text('Thirty'),
  85. 40 => $locale->text('Forty'),
  86. 50 => $locale->text('Fifty'),
  87. 60 => $locale->text('Sixty'),
  88. 70 => $locale->text('Seventy'),
  89. 80 => $locale->text('Eighty'),
  90. 90 => $locale->text('Ninety'),
  91. 10**2 => $locale->text('Hundred'),
  92. 500 => $locale->text('Five Hundred'),
  93. 700 => $locale->text('Seven Hundred'),
  94. 900 => $locale->text('Nine Hundred'),
  95. 10**3 => $locale->text('Thousand'),
  96. 10**6 => $locale->text('Million'),
  97. 10**9 => $locale->text('Billion'),
  98. 10**12 => $locale->text('Trillion'),
  99. );
  100. }
  101. sub num2text {
  102. my ( $self, $amount ) = @_;
  103. return $self->num2text_de($amount) if $self->{'numrules'} eq 'de';
  104. return $self->num2text_es($amount) if $self->{'numrules'} eq 'es';
  105. return $self->num2text_nl($amount) if $self->{'numrules'} eq 'nl';
  106. return $self->num2text_hu($amount) if $self->{'numrules'} eq 'hu';
  107. return $self->num2text_et($amount) if $self->{'numrules'} eq 'et';
  108. return $self->num2text_fr($amount) if $self->{'numrules'} eq 'fr';
  109. return $self->num2text_it($amount) if $self->{'numrules'} eq 'it';
  110. return $self->num2text_da($amount) if $self->{'numrules'} eq 'da';
  111. return $self->num2text_en($amount);
  112. }
  113. sub num2text_en {
  114. my ( $self, $amount ) = @_;
  115. return $self->{numbername}{0} unless $amount;
  116. my @textnumber = ();
  117. # split amount into chunks of 3
  118. my @num = reverse split //, abs($amount);
  119. my @numblock = ();
  120. my @a;
  121. my $i;
  122. while (@num) {
  123. @a = ();
  124. for ( 1 .. 3 ) {
  125. push @a, shift @num;
  126. }
  127. push @numblock, join / /, reverse @a;
  128. }
  129. while (@numblock) {
  130. $i = $#numblock;
  131. @num = split //, $numblock[$i];
  132. if ( $numblock[$i] == 0 ) {
  133. pop @numblock;
  134. next;
  135. }
  136. if ( $numblock[$i] > 99 ) {
  137. # the one from hundreds
  138. push @textnumber, $self->{numbername}{ $num[0] };
  139. # add hundred designation
  140. push @textnumber, $self->{numbername}{ 10**2 };
  141. # reduce numblock
  142. $numblock[$i] -= $num[0] * 100;
  143. }
  144. $numblock[$i] *= 1;
  145. if ( $numblock[$i] > 9 ) {
  146. # tens
  147. push @textnumber, $self->format_ten_en( $numblock[$i] );
  148. }
  149. elsif ( $numblock[$i] > 0 ) {
  150. # ones
  151. push @textnumber, $self->{numbername}{ $numblock[$i] };
  152. }
  153. # add thousand, million
  154. if ($i) {
  155. $num = 10**( $i * 3 );
  156. push @textnumber, $self->{numbername}{$num};
  157. }
  158. pop @numblock;
  159. }
  160. join ' ', @textnumber;
  161. }
  162. sub format_ten_en {
  163. my ( $self, $amount ) = @_;
  164. my $textnumber = "";
  165. my @num = split //, $amount;
  166. if ( $amount > 20 ) {
  167. $textnumber = $self->{numbername}{ $num[0] * 10 };
  168. $amount = $num[1];
  169. }
  170. else {
  171. $textnumber = $self->{numbername}{$amount};
  172. $amount = 0;
  173. }
  174. $textnumber .= " " . $self->{numbername}{$amount} if $amount;
  175. $textnumber;
  176. }
  177. sub num2text_de {
  178. my ( $self, $amount ) = @_;
  179. return $self->{numbername}{0} unless $amount;
  180. my @textnumber = ();
  181. # split amount into chunks of 3
  182. my @num = reverse split //, abs($amount);
  183. my @numblock = ();
  184. my ( $i, $appendn );
  185. my @a = ();
  186. while (@num) {
  187. @a = ();
  188. for ( 1 .. 3 ) {
  189. push @a, shift @num;
  190. }
  191. push @numblock, join / /, reverse @a;
  192. }
  193. my $belowhundred = !$#numblock;
  194. while (@numblock) {
  195. $i = $#numblock;
  196. @num = split //, $numblock[$i];
  197. $appendn = "";
  198. $numblock[$i] *= 1;
  199. if ( $numblock[$i] == 0 ) {
  200. pop @numblock;
  201. next;
  202. }
  203. if ( $numblock[$i] > 99 ) {
  204. # the one from hundreds
  205. push @textnumber, $self->{numbername}{ $num[0] };
  206. # add hundred designation
  207. push @textnumber, $self->{numbername}{ 10**2 };
  208. # reduce numblock
  209. $numblock[$i] -= $num[0] * 100;
  210. }
  211. $appendn = 'en' if ( $i == 2 );
  212. $appendn = 'n' if ( $i > 2 );
  213. if ( $numblock[$i] > 9 ) {
  214. # tens
  215. push @textnumber,
  216. $self->format_ten_de( $numblock[$i], $belowhundred );
  217. }
  218. elsif ( $numblock[$i] > 1 ) {
  219. # ones
  220. push @textnumber, $self->{numbername}{ $numblock[$i] };
  221. }
  222. elsif ( $numblock[$i] == 1 ) {
  223. if ( $i == 0 ) {
  224. push @textnumber, $self->{numbername}{ $numblock[$i] } . 's';
  225. }
  226. else {
  227. if ( $i >= 2 ) {
  228. push @textnumber,
  229. $self->{numbername}{ $numblock[$i] } . 'e';
  230. }
  231. else {
  232. push @textnumber, $self->{numbername}{ $numblock[$i] };
  233. }
  234. }
  235. $appendn = "";
  236. }
  237. # add thousand, million
  238. if ($i) {
  239. $amount = 10**( $i * 3 );
  240. push @textnumber, $self->{numbername}{$amount} . $appendn;
  241. }
  242. pop @numblock;
  243. }
  244. join '', @textnumber;
  245. }
  246. sub format_ten_de {
  247. my ( $self, $amount, $belowhundred ) = @_;
  248. my $textnumber = "";
  249. my @num = split //, $amount;
  250. if ( $amount > 20 ) {
  251. if ( $num[1] == 0 ) {
  252. $textnumber = $self->{numbername}{$amount};
  253. }
  254. else {
  255. if ($belowhundred) {
  256. $amount = $num[0] * 10;
  257. $textnumber =
  258. $self->{numbername}{ $num[1] } . 'und'
  259. . $self->{numbername}{$amount};
  260. }
  261. else {
  262. $amount = $num[0] * 10;
  263. $textnumber =
  264. $self->{numbername}{$amount} . $self->{numbername}{ $num[1] };
  265. $textnumber .= 's' if ( $num[1] == 1 );
  266. }
  267. }
  268. }
  269. else {
  270. $textnumber = $self->{numbername}{$amount};
  271. }
  272. $textnumber;
  273. }
  274. sub num2text_et {
  275. my ( $self, $amount ) = @_;
  276. return $self->{numbername}{0} unless $amount;
  277. my @textnumber = ();
  278. # split amount into chunks of 3
  279. my @num = reverse split //, abs($amount);
  280. my @numblock = ();
  281. my ( $i, $appendit );
  282. my @a = ();
  283. while (@num) {
  284. @a = ();
  285. for ( 1 .. 3 ) {
  286. push @a, shift @num;
  287. }
  288. push @numblock, join / /, reverse @a;
  289. }
  290. while (@numblock) {
  291. $i = $#numblock;
  292. $numblock[$i] *= 1;
  293. @num = split //, $numblock[$i];
  294. $appendit = "it";
  295. $hundred = 0;
  296. if ( $numblock[$i] == 0 ) {
  297. pop @numblock;
  298. next;
  299. }
  300. if ( $numblock[$i] > 99 ) {
  301. # the one from hundreds
  302. push @textnumber,
  303. "$self->{numbername}{$num[0]}$self->{numbername}{10**2}";
  304. # reduce numblock
  305. $numblock[$i] -= $num[0] * 100;
  306. @num = split //, $numblock[$i];
  307. $hundred = 1;
  308. }
  309. if ( $numblock[$i] > 19 ) {
  310. # 20 - 99
  311. push @textnumber, "$self->{numbername}{$num[0]}kümmend";
  312. @num = split //, $numblock[$i];
  313. push @textnumber, $self->{numbername}{ $num[1] } if $num[1] > 0;
  314. }
  315. elsif ( $numblock[$i] > 10 ) {
  316. # 11 - 19
  317. if ($hundred) {
  318. @num = split //, $numblock[$i];
  319. }
  320. $num = $num[1];
  321. push @textnumber, "$self->{numbername}{$num}teist";
  322. }
  323. elsif ( $numblock[$i] > 1 ) {
  324. # ones
  325. push @textnumber, $self->{numbername}{ $numblock[$i] };
  326. }
  327. elsif ( $numblock[$i] == 1 ) {
  328. push @textnumber, $self->{numbername}{ $num[0] };
  329. $appendit = "";
  330. }
  331. # add thousand, million
  332. if ($i) {
  333. $amount = 10**( $i * 3 );
  334. $appendit = ( $i == 1 ) ? "" : $appendit;
  335. push @textnumber, "$self->{numbername}{$amount}$appendit";
  336. }
  337. pop @numblock;
  338. }
  339. join ' ', @textnumber;
  340. }
  341. sub num2text_es {
  342. my ( $self, $amount ) = @_;
  343. return $self->{numbername}{0} unless $amount;
  344. my @textnumber = ();
  345. # split amount into chunks of 3
  346. my @num = reverse split //, abs($amount);
  347. my @numblock = ();
  348. my $stripun = 0;
  349. my @a = ();
  350. my $i;
  351. while (@num) {
  352. @a = ();
  353. for ( 1 .. 3 ) {
  354. push @a, shift @num;
  355. }
  356. push @numblock, join / /, reverse @a;
  357. }
  358. # special case for 1000
  359. if ( $numblock[1] eq '1' && $numblock[0] gt '000' ) {
  360. # remove first array element from textnumber
  361. $stripun = 1;
  362. }
  363. while (@numblock) {
  364. $i = $#numblock;
  365. @num = split //, $numblock[$i];
  366. $numblock[$i] *= 1;
  367. if ( $numblock[$i] == 0 ) {
  368. pop @numblock;
  369. next;
  370. }
  371. if ( $numblock[$i] > 99 ) {
  372. if ( $num[0] == 1 ) {
  373. push @textnumber, $self->{numbername}{ 10**2 };
  374. }
  375. else {
  376. # special case for 500, 700, 900
  377. if ( grep /$num[0]/, ( 5, 7, 9 ) ) {
  378. push @textnumber, $self->{numbername}{"${num[0]}00"};
  379. }
  380. else {
  381. # the one from hundreds, append cientos
  382. push @textnumber,
  383. $self->{numbername}{ $num[0] }
  384. . $self->{numbername}{ 10**2 } . 's';
  385. }
  386. }
  387. # reduce numblock
  388. $numblock[$i] -= $num[0] * 100;
  389. }
  390. if ( $numblock[$i] > 9 ) {
  391. # tens
  392. push @textnumber, $self->format_ten_es( $numblock[$i], $i );
  393. }
  394. elsif ( $numblock[$i] > 0 ) {
  395. # ones
  396. $num = $numblock[$i];
  397. $num .= 'o' if ( $num == 1 && $i == 0 );
  398. push @textnumber, $self->{numbername}{$num};
  399. }
  400. # add thousand, million
  401. if ($i) {
  402. $num = 10**( $i * 3 );
  403. if ( $numblock[$i] > 1 ) {
  404. if ( $i == 2 || $i == 4 ) {
  405. $a = $self->{numbername}{$num} . "es";
  406. $a =~ s/ó/o/;
  407. push @textnumber, $a;
  408. }
  409. elsif ( $i == 3 ) {
  410. $num = 10**( $i * 2 );
  411. $a = "$self->{10**3} $self->{numbername}{$num}" . "es";
  412. $a =~ s/ó/o/;
  413. push @textnumber, $a;
  414. }
  415. else {
  416. if ( $i == 1 ) {
  417. push @textnumber, $self->{numbername}{$num};
  418. }
  419. else {
  420. push @textnumber, $self->{numbername}{$num} . 's';
  421. }
  422. }
  423. }
  424. else {
  425. push @textnumber, $self->{numbername}{$num};
  426. }
  427. }
  428. pop @numblock;
  429. }
  430. shift @textnumber if $stripun;
  431. join ' ', @textnumber;
  432. }
  433. sub format_ten_es {
  434. my ( $self, $amount, $i ) = @_;
  435. my $textnumber = "";
  436. my @num = split //, $amount;
  437. if ( $amount > 30 ) {
  438. $textnumber = $self->{numbername}{ $num[0] * 10 };
  439. $amount = $num[1];
  440. }
  441. else {
  442. $amount .= 'o' if ( $num[1] == 1 && $i == 0 );
  443. $textnumber = $self->{numbername}{$amount};
  444. $amount = 0;
  445. }
  446. $textnumber .= " y " . $self->{numbername}{$amount} if $amount;
  447. $textnumber;
  448. }
  449. sub num2text_fr {
  450. my ( $self, $amount ) = @_;
  451. return $self->{numbername}{0} unless $amount;
  452. my @textnumber = ();
  453. # split amount into chunks of 3
  454. my @num = reverse split //, abs($amount);
  455. my @numblock = ();
  456. my @a;
  457. my $i;
  458. while (@num) {
  459. @a = ();
  460. for ( 1 .. 3 ) {
  461. push @a, shift @num;
  462. }
  463. push @numblock, join / /, reverse @a;
  464. }
  465. my $cent = 0;
  466. while (@numblock) {
  467. $i = $#numblock;
  468. @num = split //, $numblock[$i];
  469. if ( $numblock[$i] == 0 ) {
  470. pop @numblock;
  471. next;
  472. }
  473. if ( $numblock[$i] > 99 ) {
  474. $cent = 1;
  475. # the one from hundreds
  476. if ( $num[0] > 1 ) {
  477. push @textnumber, $self->{numbername}{ $num[0] };
  478. }
  479. # reduce numblock
  480. $numblock[$i] -= $num[0] * 100;
  481. # add hundred designation
  482. if ( $num[0] > 1 ) {
  483. if ( $numblock[$i] > 0 ) {
  484. push @textnumber, $self->{numbername}{ 10**2 };
  485. }
  486. else {
  487. push @textnumber, "$self->{numbername}{10**2}s";
  488. }
  489. }
  490. else {
  491. push @textnumber, $self->{numbername}{ 10**2 };
  492. }
  493. }
  494. $numblock[$i] *= 1;
  495. if ( $numblock[$i] > 9 ) {
  496. # tens
  497. push @textnumber, $self->format_ten_fr( $numblock[$i] );
  498. }
  499. elsif ( $numblock[$i] > 0 ) {
  500. # ones
  501. if ( $i == 1 ) {
  502. if ( $cent == 1 ) {
  503. push @textnumber, $self->{numbername}{ $numblock[$i] };
  504. }
  505. $cent = 0;
  506. }
  507. else {
  508. push @textnumber, $self->{numbername}{ $numblock[$i] };
  509. }
  510. }
  511. # add thousand, million
  512. if ($i) {
  513. $num = 10**( $i * 3 );
  514. if ( $i == 1 ) {
  515. push @textnumber, $self->{numbername}{$num};
  516. }
  517. elsif ( $numblock[$i] > 1 ) {
  518. push @textnumber, "$self->{numbername}{$num}s";
  519. }
  520. else {
  521. push @textnumber, "$self->{numbername}{$num}";
  522. }
  523. }
  524. pop @numblock;
  525. }
  526. join ' ', @textnumber;
  527. }
  528. sub format_ten_fr {
  529. my ( $self, $amount ) = @_;
  530. my $textnumber = "";
  531. my @num = split //, $amount;
  532. if ( $amount > 20 ) {
  533. if ( $num[0] == 8 ) {
  534. if ( $num[1] > 0 ) {
  535. $textnumber = $self->{numbername}{ $num[0] * 10 };
  536. }
  537. else {
  538. $textnumber = "$self->{numbername}{$num[0]*10}s";
  539. }
  540. $amount = $num[1];
  541. }
  542. elsif ( $num[0] == 7 || $num[0] == 9 ) {
  543. if ( $num[1] > 0 ) {
  544. $textnumber = $self->{numbername}{ ( $num[0] - 1 ) * 10 };
  545. $textnumber .= " et" if ( $num[1] == 1 && $num[0] == 7 );
  546. $amount -= ( $num[0] - 1 ) * 10;
  547. }
  548. else {
  549. $textnumber = $self->{numbername}{ $num[0] * 10 };
  550. $amount = $num[1];
  551. }
  552. }
  553. else {
  554. $textnumber = $self->{numbername}{ $num[0] * 10 };
  555. $textnumber .= " et" if ( $num[1] == 1 );
  556. $amount = $num[1];
  557. }
  558. }
  559. else {
  560. $textnumber = "$self->{numbername}{$amount}";
  561. $amount = 0;
  562. }
  563. $textnumber .= " " . $self->{numbername}{$amount} if $amount;
  564. $textnumber;
  565. }
  566. sub num2text_hu {
  567. my ( $self, $amount ) = @_;
  568. return $self->{numbername}{0} unless $amount;
  569. my @textnumber = ();
  570. # split amount into chunks of 3
  571. my @num = reverse split //, abs($amount);
  572. my @numblock = ();
  573. my @a;
  574. my $i;
  575. my $res;
  576. while (@num) {
  577. @a = ();
  578. for ( 1 .. 3 ) {
  579. push @a, shift @num;
  580. }
  581. push @numblock, join / /, reverse @a;
  582. }
  583. while (@numblock) {
  584. $i = $#numblock;
  585. @num = split //, $numblock[$i];
  586. if ( $numblock[$i] == 0 ) {
  587. pop @numblock;
  588. next;
  589. }
  590. if ( $numblock[$i] > 99 ) {
  591. push @textnumber, $self->{numbername}{ $num[0] };
  592. # add hundred designation
  593. push @textnumber, $self->{numbername}{ 10**2 };
  594. # reduce numblock
  595. $numblock[$i] -= $num[0] * 100;
  596. }
  597. $numblock[$i] *= 1;
  598. if ( $numblock[$i] > 9 ) {
  599. # tens
  600. push @textnumber, $self->format_ten_hu( $numblock[$i] );
  601. }
  602. elsif ( $numblock[$i] > 0 ) {
  603. # ones
  604. push @textnumber, $self->{numbername}{ $numblock[$i] };
  605. }
  606. # add thousand, million
  607. if ($i) {
  608. if ( $i == 1 && $amount < 2000 ) {
  609. $num = 10**( $i * 3 );
  610. push @textnumber, $self->{numbername}{$num};
  611. }
  612. else {
  613. $num = 10**( $i * 3 );
  614. push @textnumber, $self->{numbername}{$num} . "-";
  615. }
  616. }
  617. pop @numblock;
  618. }
  619. $res = ucfirst join '', @textnumber;
  620. $res =~ s/(\-)$//;
  621. return $res;
  622. }
  623. sub format_ten_hu {
  624. my ( $self, $amount ) = @_;
  625. my $textnumber = "";
  626. my @num = split //, $amount;
  627. if ( $amount > 30 ) {
  628. $textnumber = $self->{numbername}{ $num[0] * 10 };
  629. $amount = $num[1];
  630. }
  631. else {
  632. $textnumber = $self->{numbername}{$amount};
  633. $amount = 0;
  634. }
  635. $textnumber .= "" . $self->{numbername}{$amount} if $amount;
  636. $textnumber;
  637. }
  638. sub num2text_nl {
  639. my ( $self, $amount ) = @_;
  640. return $self->{numbername}{0} unless $amount;
  641. my @textnumber = ('**');
  642. # split amount into chunks of 3
  643. my @num = reverse split //, abs($amount);
  644. my @numblock = ();
  645. my ( $i, $appendn );
  646. my @a = ();
  647. while (@num) {
  648. @a = ();
  649. for ( 1 .. 3 ) {
  650. push @a, shift @num;
  651. }
  652. push @numblock, join / /, reverse @a;
  653. }
  654. while (@numblock) {
  655. $i = $#numblock;
  656. @num = split //, $numblock[$i];
  657. $numblock[$i] *= 1;
  658. if ( $numblock[$i] == 0 ) {
  659. pop @numblock;
  660. next;
  661. }
  662. if ( $numblock[$i] > 99 ) {
  663. # the one from hundreds
  664. push @textnumber, $self->{numbername}{ $num[0] };
  665. # add hundred designation
  666. push @textnumber, $self->{numbername}{ 10**2 };
  667. # reduce numblock
  668. $numblock[$i] -= $num[0] * 100;
  669. }
  670. if ( $numblock[$i] > 9 ) {
  671. # tens
  672. push @textnumber, $self->format_ten_nl( $numblock[$i] );
  673. }
  674. else {
  675. # ones
  676. push @textnumber, $self->{numbername}{ $numblock[$i] };
  677. }
  678. # add thousand, million
  679. if ($i) {
  680. $amount = 10**( $i * 3 );
  681. push @textnumber, $self->{numbername}{$amount};
  682. }
  683. pop @numblock;
  684. }
  685. push @textnumber, '**';
  686. join '', @textnumber;
  687. }
  688. sub format_ten_nl {
  689. my ( $self, $amount ) = @_;
  690. my $textnumber = "";
  691. my @num = split //, $amount;
  692. if ( $amount > 20 ) {
  693. # reverse one and ten and glue together with 'en'
  694. $amount = $num[0] * 10;
  695. $textnumber =
  696. $self->{numbername}{ $num[1] } . 'en' . $self->{numbername}{$amount};
  697. }
  698. else {
  699. $textnumber = $self->{numbername}{$amount};
  700. }
  701. $textnumber;
  702. }
  703. sub num2text_it {
  704. my ( $self, $amount ) = @_;
  705. return $self->{numbername}{0} unless $amount;
  706. my @textnumber = ();
  707. # split amount into chunks of 3
  708. my @num = reverse split //, abs($amount);
  709. my @numblock = ();
  710. my ( $i, $appendn );
  711. my @a = ();
  712. while (@num) {
  713. @a = ();
  714. for ( 1 .. 3 ) {
  715. push @a, shift @num;
  716. }
  717. push @numblock, join / /, reverse @a;
  718. }
  719. while (@numblock) {
  720. $i = $#numblock;
  721. @num = split //, $numblock[$i];
  722. $numblock[$i] *= 1;
  723. if ( $numblock[$i] == 0 ) {
  724. pop @numblock;
  725. next;
  726. }
  727. if ( $numblock[$i] > 99 ) {
  728. # the one from hundreds
  729. push @textnumber, $self->{numbername}{ $num[0] };
  730. # add hundred designation
  731. push @textnumber, $self->{numbername}{ 10**2 };
  732. # reduce numblock
  733. $numblock[$i] -= $num[0] * 100;
  734. }
  735. if ( $numblock[$i] > 9 ) {
  736. # tens
  737. push @textnumber, $self->format_ten_it( $numblock[$i] );
  738. }
  739. elsif ( $numblock[$i] > 1 ) {
  740. # ones
  741. push @textnumber, $self->{numbername}{ $numblock[$i] };
  742. }
  743. # add thousand, million
  744. if ($i) {
  745. $amount = 10**( $i * 3 );
  746. push @textnumber, $self->{numbername}{$amount};
  747. }
  748. pop @numblock;
  749. }
  750. join '', @textnumber;
  751. }
  752. sub format_ten_it {
  753. my ( $self, $amount ) = @_;
  754. my $textnumber = "";
  755. my @num = split //, $amount;
  756. if ( $amount > 20 ) {
  757. if ( $num[1] == 0 ) {
  758. $textnumber = $self->{numbername}{$amount};
  759. }
  760. else {
  761. $amount = $num[0] * 10;
  762. $textnumber =
  763. $self->{numbername}{$amount} . $self->{numbername}{ $num[1] };
  764. }
  765. }
  766. else {
  767. $textnumber = $self->{numbername}{$amount};
  768. }
  769. $textnumber;
  770. }
  771. # A special (swedish-like) spelling of danish check numbers
  772. sub num2text_da {
  773. my ( $self, $amount ) = @_;
  774. # Handle 0
  775. return $self->{numbername}{0} unless $amount;
  776. # List of collected digits
  777. my @textnumber = ();
  778. # split amount into chunks of 3
  779. my @num = reverse split //, abs($amount);
  780. my @numblock = ();
  781. my @a = ();
  782. while (@num) {
  783. @a = ();
  784. for ( 1 .. 3 ) {
  785. push @a, shift @num;
  786. }
  787. push @numblock, join / /, reverse @a;
  788. }
  789. my $i;
  790. my $bigplural;
  791. while (@numblock) {
  792. $i = $#numblock;
  793. $numblock[$i] *= 1;
  794. if ( $numblock[$i] == 0 ) {
  795. pop @numblock;
  796. next;
  797. }
  798. # Plural suffix "er" for million and up, not for tusinde
  799. $bigpluralsuffix = "";
  800. $bigpluralsuffix = "er" if ( $i > 1 && $numblock[$i] > 1 );
  801. if ( $numblock[$i] > 99 ) {
  802. @num = split //, $numblock[$i];
  803. # the one from hundreds
  804. push @textnumber, $self->{numbername}{ $num[0] };
  805. # add hundred designation
  806. push @textnumber, $self->{numbername}{100};
  807. # reduce numblock
  808. $numblock[$i] -= $num[0] * 100;
  809. }
  810. if ( $numblock[$i] > 9 ) {
  811. @num = split //, $numblock[$i];
  812. # the one from tens
  813. push @textnumber, $self->{numbername}{ $num[0] };
  814. # add ten designation
  815. push @textnumber, $self->{numbername}{10};
  816. # reduce numblock
  817. $numblock[$i] -= $num[0] * 10;
  818. }
  819. if ( $numblock[$i] > 0 ) {
  820. # the ones left in the block
  821. if ( $numblock[$i] == 1 && $i != 1 ) {
  822. push @textnumber,
  823. $self->{numbername}{'1o'}; # Special case for "Et" tusinde
  824. }
  825. else {
  826. push @textnumber, $self->{numbername}{ $numblock[$i] };
  827. }
  828. }
  829. # add thousand, million, etc
  830. if ($i) {
  831. $amount = 10**( $i * 3 );
  832. push @textnumber, $self->{numbername}{$amount} . $bigpluralsuffix;
  833. }
  834. pop @numblock;
  835. }
  836. join '', @textnumber;
  837. }
  838. sub num2text_sl {
  839. my ($self, $amount) = @_;
  840. return $self->{numbername}{0} unless $amount;
  841. my @textnumber = ();
  842. # split amount into chunks of 3
  843. my @num = reverse split //, abs($amount);
  844. my @numblock = ();
  845. my ($i, $appendn);
  846. my @a = ();
  847. my $skip1k = 0;
  848. my $skip1m = 0;
  849. my $skip1b = 0;
  850. my $checkvalue = abs($amount) % 10**6;
  851. $checkvalue /= 1000;
  852. if (1 <= $checkvalue && $checkvalue <= 2) {
  853. $skip1k = 1;
  854. }
  855. $checkvalue = abs($amount) % 10**9;
  856. $checkvalue /= 10**6;
  857. if (1 <= $checkvalue && $checkvalue <= 2) {
  858. $skip1m = 1;
  859. }
  860. $checkvalue = abs($amount) % 10**15;
  861. $checkvalue /= 10**12;
  862. if (1 <= $checkvalue && $checkvalue <= 2) {
  863. $skip1b = 1;
  864. }
  865. my $check1m = abs($amount) % 10**8;
  866. my $check1md = abs($amount) % 10**11;
  867. my $check1b = abs($amount) % 10**14;
  868. while (@num) {
  869. @a = ();
  870. for (1 .. 3) {
  871. push @a, shift @num;
  872. }
  873. push @numblock, join / /, reverse @a;
  874. }
  875. my $belowhundred = !$#numblock;
  876. while (@numblock) {
  877. $i = $#numblock;
  878. @num = split //, $numblock[$i];
  879. $appendn = "";
  880. $numblock[$i] *= 1;
  881. if ($numblock[$i] == 0) {
  882. pop @numblock;
  883. next;
  884. }
  885. if ($numblock[$i] > 99) {
  886. # the one from hundreds
  887. if ( $num[0] > 2 ) {
  888. push @textnumber, $self->{numbername}{$num[0]};
  889. } elsif ( $num[0] > 1 ) {
  890. push @textnumber, 'dve';
  891. }
  892. # add hundred designation
  893. push @textnumber, $self->{numbername}{10**2};
  894. # reduce numblock
  895. $numblock[$i] -= $num[0] * 100;
  896. }
  897. # Appends, where for 1 they shall be eliminated later below:
  898. if ($i == 2) {
  899. if (2*10**6 <= $check1m && $check1m < 3*10**6) {
  900. $appendn = 'a';
  901. } elsif (3*10**6 <= $check1m && $check1m < 5*10**6) {
  902. $appendn = 'e';
  903. } else {
  904. $appendn = 'ov';
  905. }
  906. }
  907. if ($i == 4) {
  908. if (2*10**12 <= $check1b && $check1b < 3*10**12) {
  909. $appendn = 'a';
  910. } elsif (3*10**12 <= $check1b && $check1b < 5*10**12) {
  911. $appendn = 'e';
  912. } else {
  913. $appendn = 'ov';
  914. }
  915. }
  916. if ($numblock[$i] > 9) {
  917. # tens
  918. push @textnumber, $self->format_ten($numblock[$i], $belowhundred);
  919. } elsif ($numblock[$i] > 1) {
  920. # ones
  921. if (2*10**9 <= $check1md && $check1md < 3*10**9) {
  922. push @textnumber, 'dve';
  923. } else {
  924. push @textnumber, $self->{numbername}{$numblock[$i]};
  925. }
  926. } elsif ($numblock[$i] == 1) {
  927. if ($i == 0) {
  928. push @textnumber, $self->{numbername}{$numblock[$i]};
  929. } else {
  930. if ($i >= 5) {
  931. push @textnumber, $self->{numbername}{$numblock[$i]}.'-!-too big number-!-?!';
  932. } elsif ($i == 4) {
  933. if ($skip1b == 0) {
  934. push @textnumber, $self->{numbername}{$numblock[$i]};
  935. }
  936. } elsif ($i == 3) {
  937. if (1*10**9 <= $check1md && $check1md < 2*10**9) {
  938. push @textnumber, 'ena';
  939. } else {
  940. push @textnumber, $self->{numbername}{$numblock[$i]};
  941. }
  942. } elsif ($i == 2) {
  943. if ($skip1m == 0) {
  944. push @textnumber, $self->{numbername}{$numblock[$i]};
  945. }
  946. } elsif ($i == 1) {
  947. if ($skip1k == 0) {
  948. push @textnumber, $self->{numbername}{$numblock[$i]};
  949. }
  950. } else {
  951. push @textnumber, $self->{numbername}{$numblock[$i]};
  952. }
  953. }
  954. $appendn = "";
  955. }
  956. # Appends, where also for 1 they shall be considered as below;
  957. # if specified above with the others, they would be eliminated
  958. # by a command just a few lines above...
  959. #
  960. if ($i == 3) {
  961. if (1*10**9 <= $check1md && $check1md < 2*10**9) {
  962. $appendn = 'a';
  963. } elsif (2*10**9 <= $check1md && $check1md < 3*10**9) {
  964. $appendn = 'i';
  965. } elsif (3*10**9 <= $check1md && $check1md < 5*10**9) {
  966. $appendn = 'e';
  967. }
  968. }
  969. # add thousand, million
  970. if ($i) {
  971. $amount = 10**($i * 3);
  972. push @textnumber, $self->{numbername}{$amount}.$appendn;
  973. }
  974. pop @numblock;
  975. @textnumber = 'NAPAKA! ¿TEVILKA JE PREVELIKA!' if ($i > 4);
  976. }
  977. join '', @textnumber;
  978. }
  979. sub format_ten_sl {
  980. my ($self, $amount, $belowhundred) = @_;
  981. my $textnumber = "";
  982. my @num = split //, $amount;
  983. if ($amount > 20) {
  984. if ($num[1] == 0) {
  985. $textnumber = $self->{numbername}{$amount};
  986. } elsif ($num[1] == 1) {
  987. $amount = $num[0] * 10;
  988. $textnumber = $self->{numbername}{$num[1]}.'ain'.$self->{numbername}{$amount};
  989. } else {
  990. $amount = $num[0] * 10;
  991. $textnumber = $self->{numbername}{$num[1]}.'in'.$self->{numbername}{$amount};
  992. }
  993. } else {
  994. $textnumber = $self->{numbername}{$amount};
  995. }
  996. $textnumber;
  997. }
  998. 1;
  999. 1;