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