summaryrefslogtreecommitdiff
path: root/LedgerSMB/Num2text.pm
blob: 8382df5c7f3a92211533c3961df4d3d063cf0431 (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 if
  47. 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. } elsif ($numblock[$i] > 0) {
  149. # ones
  150. push @textnumber, $self->{numbername}{$numblock[$i]};
  151. }
  152. # add thousand, million
  153. if ($i) {
  154. $num = 10**($i * 3);
  155. push @textnumber, $self->{numbername}{$num};
  156. }
  157. pop @numblock;
  158. }
  159. join ' ', @textnumber;
  160. }
  161. sub format_ten_en {
  162. my ($self, $amount) = @_;
  163. my $textnumber = "";
  164. my @num = split //, $amount;
  165. if ($amount > 20) {
  166. $textnumber = $self->{numbername}{$num[0]*10};
  167. $amount = $num[1];
  168. } else {
  169. $textnumber = $self->{numbername}{$amount};
  170. $amount = 0;
  171. }
  172. $textnumber .= " ".$self->{numbername}{$amount} if $amount;
  173. $textnumber;
  174. }
  175. sub num2text_de {
  176. my ($self, $amount) = @_;
  177. return $self->{numbername}{0} unless $amount;
  178. my @textnumber = ();
  179. # split amount into chunks of 3
  180. my @num = reverse split //, abs($amount);
  181. my @numblock = ();
  182. my ($i, $appendn);
  183. my @a = ();
  184. while (@num) {
  185. @a = ();
  186. for (1 .. 3) {
  187. push @a, shift @num;
  188. }
  189. push @numblock, join / /, reverse @a;
  190. }
  191. my $belowhundred = !$#numblock;
  192. while (@numblock) {
  193. $i = $#numblock;
  194. @num = split //, $numblock[$i];
  195. $appendn = "";
  196. $numblock[$i] *= 1;
  197. if ($numblock[$i] == 0) {
  198. pop @numblock;
  199. next;
  200. }
  201. if ($numblock[$i] > 99) {
  202. # the one from hundreds
  203. push @textnumber, $self->{numbername}{$num[0]};
  204. # add hundred designation
  205. push @textnumber, $self->{numbername}{10**2};
  206. # reduce numblock
  207. $numblock[$i] -= $num[0] * 100;
  208. }
  209. $appendn = 'en' if ($i == 2);
  210. $appendn = 'n' if ($i > 2);
  211. if ($numblock[$i] > 9) {
  212. # tens
  213. push @textnumber, $self->format_ten_de($numblock[$i], $belowhundred);
  214. } elsif ($numblock[$i] > 1) {
  215. # ones
  216. push @textnumber, $self->{numbername}{$numblock[$i]};
  217. } elsif ($numblock[$i] == 1) {
  218. if ($i == 0) {
  219. push @textnumber, $self->{numbername}{$numblock[$i]}.'s';
  220. } else {
  221. if ($i >= 2) {
  222. push @textnumber, $self->{numbername}{$numblock[$i]}.'e';
  223. } else {
  224. push @textnumber, $self->{numbername}{$numblock[$i]};
  225. }
  226. }
  227. $appendn = "";
  228. }
  229. # add thousand, million
  230. if ($i) {
  231. $amount = 10**($i * 3);
  232. push @textnumber, $self->{numbername}{$amount}.$appendn;
  233. }
  234. pop @numblock;
  235. }
  236. join '', @textnumber;
  237. }
  238. sub format_ten_de {
  239. my ($self, $amount, $belowhundred) = @_;
  240. my $textnumber = "";
  241. my @num = split //, $amount;
  242. if ($amount > 20) {
  243. if ($num[1] == 0) {
  244. $textnumber = $self->{numbername}{$amount};
  245. } else {
  246. if ($belowhundred) {
  247. $amount = $num[0] * 10;
  248. $textnumber = $self->{numbername}{$num[1]}.'und'.$self->{numbername}{$amount};
  249. } else {
  250. $amount = $num[0] * 10;
  251. $textnumber = $self->{numbername}{$amount}.$self->{numbername}{$num[1]};
  252. $textnumber .= 's' if ($num[1] == 1);
  253. }
  254. }
  255. } else {
  256. $textnumber = $self->{numbername}{$amount};
  257. }
  258. $textnumber;
  259. }
  260. sub num2text_et {
  261. my ($self, $amount) = @_;
  262. return $self->{numbername}{0} unless $amount;
  263. my @textnumber = ();
  264. # split amount into chunks of 3
  265. my @num = reverse split //, abs($amount);
  266. my @numblock = ();
  267. my ($i, $appendit);
  268. my @a = ();
  269. while (@num) {
  270. @a = ();
  271. for (1 .. 3) {
  272. push @a, shift @num;
  273. }
  274. push @numblock, join / /, reverse @a;
  275. }
  276. while (@numblock) {
  277. $i = $#numblock;
  278. $numblock[$i] *= 1;
  279. @num = split //, $numblock[$i];
  280. $appendit = "it";
  281. $hundred = 0;
  282. if ($numblock[$i] == 0) {
  283. pop @numblock;
  284. next;
  285. }
  286. if ($numblock[$i] > 99) {
  287. # the one from hundreds
  288. push @textnumber, "$self->{numbername}{$num[0]}$self->{numbername}{10**2}";
  289. # reduce numblock
  290. $numblock[$i] -= $num[0] * 100;
  291. @num = split //, $numblock[$i];
  292. $hundred = 1;
  293. }
  294. if ($numblock[$i] > 19) {
  295. # 20 - 99
  296. push @textnumber, "$self->{numbername}{$num[0]}kümmend";
  297. @num = split //, $numblock[$i];
  298. push @textnumber, $self->{numbername}{$num[1]} if $num[1] > 0;
  299. } elsif ($numblock[$i] > 10) {
  300. # 11 - 19
  301. if ($hundred) {
  302. @num = split //, $numblock[$i];
  303. }
  304. $num = $num[1];
  305. push @textnumber, "$self->{numbername}{$num}teist";
  306. } elsif ($numblock[$i] > 1) {
  307. # ones
  308. push @textnumber, $self->{numbername}{$numblock[$i]};
  309. } elsif ($numblock[$i] == 1) {
  310. push @textnumber, $self->{numbername}{$num[0]};
  311. $appendit = "";
  312. }
  313. # add thousand, million
  314. if ($i) {
  315. $amount = 10**($i * 3);
  316. $appendit = ($i == 1) ? "" : $appendit;
  317. push @textnumber, "$self->{numbername}{$amount}$appendit";
  318. }
  319. pop @numblock;
  320. }
  321. join ' ', @textnumber;
  322. }
  323. sub num2text_es {
  324. my ($self, $amount) = @_;
  325. return $self->{numbername}{0} unless $amount;
  326. my @textnumber = ();
  327. # split amount into chunks of 3
  328. my @num = reverse split //, abs($amount);
  329. my @numblock = ();
  330. my $stripun = 0;
  331. my @a = ();
  332. my $i;
  333. while (@num) {
  334. @a = ();
  335. for (1 .. 3) {
  336. push @a, shift @num;
  337. }
  338. push @numblock, join / /, reverse @a;
  339. }
  340. # special case for 1000
  341. if ($numblock[1] eq '1' && $numblock[0] gt '000') {
  342. # remove first array element from textnumber
  343. $stripun = 1;
  344. }
  345. while (@numblock) {
  346. $i = $#numblock;
  347. @num = split //, $numblock[$i];
  348. $numblock[$i] *= 1;
  349. if ($numblock[$i] == 0) {
  350. pop @numblock;
  351. next;
  352. }
  353. if ($numblock[$i] > 99) {
  354. if ($num[0] == 1) {
  355. push @textnumber, $self->{numbername}{10**2};
  356. } else {
  357. # special case for 500, 700, 900
  358. if (grep /$num[0]/, (5,7,9)) {
  359. push @textnumber, $self->{numbername}{"${num[0]}00"};
  360. } else {
  361. # the one from hundreds, append cientos
  362. push @textnumber, $self->{numbername}{$num[0]}.$self->{numbername}{10**2}.'s';
  363. }
  364. }
  365. # reduce numblock
  366. $numblock[$i] -= $num[0] * 100;
  367. }
  368. if ($numblock[$i] > 9) {
  369. # tens
  370. push @textnumber, $self->format_ten_es($numblock[$i], $i);
  371. } elsif ($numblock[$i] > 0) {
  372. # ones
  373. $num = $numblock[$i];
  374. $num .= 'o' if ($num == 1 && $i == 0);
  375. push @textnumber, $self->{numbername}{$num};
  376. }
  377. # add thousand, million
  378. if ($i) {
  379. $num = 10**($i * 3);
  380. if ($numblock[$i] > 1) {
  381. if ($i == 2 || $i == 4) {
  382. $a = $self->{numbername}{$num}."es";
  383. $a =~ s/ó/o/;
  384. push @textnumber, $a;
  385. } elsif ($i == 3) {
  386. $num = 10**($i * 2);
  387. $a = "$self->{10**3} $self->{numbername}{$num}"."es";
  388. $a =~ s/ó/o/;
  389. push @textnumber, $a;
  390. } else {
  391. if ($i == 1) {
  392. push @textnumber, $self->{numbername}{$num};
  393. } else {
  394. push @textnumber, $self->{numbername}{$num}.'s';
  395. }
  396. }
  397. } else {
  398. push @textnumber, $self->{numbername}{$num};
  399. }
  400. }
  401. pop @numblock;
  402. }
  403. shift @textnumber if $stripun;
  404. join ' ', @textnumber;
  405. }
  406. sub format_ten_es {
  407. my ($self, $amount, $i) = @_;
  408. my $textnumber = "";
  409. my @num = split //, $amount;
  410. if ($amount > 30) {
  411. $textnumber = $self->{numbername}{$num[0]*10};
  412. $amount = $num[1];
  413. } else {
  414. $amount .= 'o' if ($num[1] == 1 && $i == 0);
  415. $textnumber = $self->{numbername}{$amount};
  416. $amount = 0;
  417. }
  418. $textnumber .= " y ".$self->{numbername}{$amount} if $amount;
  419. $textnumber;
  420. }
  421. sub num2text_fr {
  422. my ($self, $amount) = @_;
  423. return $self->{numbername}{0} unless $amount;
  424. my @textnumber = ();
  425. # split amount into chunks of 3
  426. my @num = reverse split //, abs($amount);
  427. my @numblock = ();
  428. my @a;
  429. my $i;
  430. while (@num) {
  431. @a = ();
  432. for (1 .. 3) {
  433. push @a, shift @num;
  434. }
  435. push @numblock, join / /, reverse @a;
  436. }
  437. my $cent=0;
  438. while (@numblock) {
  439. $i = $#numblock;
  440. @num = split //, $numblock[$i];
  441. if ($numblock[$i] == 0) {
  442. pop @numblock;
  443. next;
  444. }
  445. if ($numblock[$i] > 99) {
  446. $cent=1;
  447. # the one from hundreds
  448. if ($num[0] > 1) {
  449. push @textnumber, $self->{numbername}{$num[0]};
  450. }
  451. # reduce numblock
  452. $numblock[$i] -= $num[0] * 100;
  453. # add hundred designation
  454. if ($num[0] > 1) {
  455. if($numblock[$i] > 0) {
  456. push @textnumber, $self->{numbername}{10**2};
  457. } else {
  458. push @textnumber, "$self->{numbername}{10**2}s";
  459. }
  460. } else {
  461. push @textnumber, $self->{numbername}{10**2};
  462. }
  463. }
  464. $numblock[$i] *= 1;
  465. if ($numblock[$i] > 9) {
  466. # tens
  467. push @textnumber, $self->format_ten_fr($numblock[$i]);
  468. } elsif ($numblock[$i] > 0) {
  469. # ones
  470. if ($i == 1) {
  471. if ($cent == 1) {
  472. push @textnumber, $self->{numbername}{$numblock[$i]};
  473. }
  474. $cent = 0;
  475. } else {
  476. push @textnumber, $self->{numbername}{$numblock[$i]};
  477. }
  478. }
  479. # add thousand, million
  480. if ($i) {
  481. $num = 10**($i * 3);
  482. if ($i == 1) {
  483. push @textnumber, $self->{numbername}{$num};
  484. } elsif ($numblock[$i] > 1) {
  485. push @textnumber, "$self->{numbername}{$num}s";
  486. } else {
  487. push @textnumber, "$self->{numbername}{$num}";
  488. }
  489. }
  490. pop @numblock;
  491. }
  492. join ' ', @textnumber;
  493. }
  494. sub format_ten_fr {
  495. my ($self, $amount) = @_;
  496. my $textnumber = "";
  497. my @num = split //, $amount;
  498. if ($amount > 20) {
  499. if ($num[0] == 8) {
  500. if ($num[1] > 0) {
  501. $textnumber = $self->{numbername}{$num[0]*10};
  502. } else {
  503. $textnumber = "$self->{numbername}{$num[0]*10}s";
  504. }
  505. $amount = $num[1];
  506. } elsif ($num[0] == 7 || $num[0] == 9) {
  507. if ($num[1] > 0) {
  508. $textnumber = $self->{numbername}{($num[0]-1)*10};
  509. $textnumber .= " et" if ($num[1] == 1 && $num[0] == 7);
  510. $amount -= ($num[0]-1)*10;
  511. } else {
  512. $textnumber = $self->{numbername}{$num[0]*10};
  513. $amount = $num[1];
  514. }
  515. } else {
  516. $textnumber = $self->{numbername}{$num[0]*10};
  517. $textnumber .= " et" if ($num[1] == 1);
  518. $amount = $num[1];
  519. }
  520. } else {
  521. $textnumber = "$self->{numbername}{$amount}";
  522. $amount = 0;
  523. }
  524. $textnumber .= " ".$self->{numbername}{$amount} if $amount;
  525. $textnumber;
  526. }
  527. sub num2text_hu {
  528. my ($self, $amount) = @_;
  529. return $self->{numbername}{0} unless $amount;
  530. my @textnumber = ();
  531. # split amount into chunks of 3
  532. my @num = reverse split //, abs($amount);
  533. my @numblock = ();
  534. my @a;
  535. my $i;
  536. my $res;
  537. while (@num) {
  538. @a = ();
  539. for (1 .. 3) {
  540. push @a, shift @num;
  541. }
  542. push @numblock, join / /, reverse @a;
  543. }
  544. while (@numblock) {
  545. $i = $#numblock;
  546. @num = split //, $numblock[$i];
  547. if ($numblock[$i] == 0) {
  548. pop @numblock;
  549. next;
  550. }
  551. if ($numblock[$i] > 99) {
  552. push @textnumber, $self->{numbername}{$num[0]};
  553. # add hundred designation
  554. push @textnumber, $self->{numbername}{10**2};
  555. # reduce numblock
  556. $numblock[$i] -= $num[0] * 100;
  557. }
  558. $numblock[$i] *= 1;
  559. if ($numblock[$i] > 9) {
  560. # tens
  561. push @textnumber, $self->format_ten_hu($numblock[$i]);
  562. } elsif ($numblock[$i] > 0) {
  563. # ones
  564. push @textnumber, $self->{numbername}{$numblock[$i]};
  565. }
  566. # add thousand, million
  567. if ($i) {
  568. if ($i==1 && $amount < 2000){
  569. $num = 10**($i * 3);
  570. push @textnumber, $self->{numbername}{$num};
  571. } else {
  572. $num = 10**($i * 3);
  573. push @textnumber, $self->{numbername}{$num}."-";
  574. }
  575. }
  576. pop @numblock;
  577. }
  578. $res=ucfirst join '', @textnumber;
  579. $res=~s/(\-)$//;
  580. return $res;
  581. }
  582. sub format_ten_hu {
  583. my ($self, $amount) = @_;
  584. my $textnumber = "";
  585. my @num = split //, $amount;
  586. if ($amount > 30) {
  587. $textnumber = $self->{numbername}{$num[0]*10};
  588. $amount = $num[1];
  589. } else {
  590. $textnumber = $self->{numbername}{$amount};
  591. $amount = 0;
  592. }
  593. $textnumber .= "".$self->{numbername}{$amount} if $amount;
  594. $textnumber;
  595. }
  596. sub num2text_nl {
  597. my ($self, $amount) = @_;
  598. return $self->{numbername}{0} unless $amount;
  599. my @textnumber = ('**');
  600. # split amount into chunks of 3
  601. my @num = reverse split //, abs($amount);
  602. my @numblock = ();
  603. my ($i, $appendn);
  604. my @a = ();
  605. while (@num) {
  606. @a = ();
  607. for (1 .. 3) {
  608. push @a, shift @num;
  609. }
  610. push @numblock, join / /, reverse @a;
  611. }
  612. while (@numblock) {
  613. $i = $#numblock;
  614. @num = split //, $numblock[$i];
  615. $numblock[$i] *= 1;
  616. if ($numblock[$i] == 0) {
  617. pop @numblock;
  618. next;
  619. }
  620. if ($numblock[$i] > 99) {
  621. # the one from hundreds
  622. push @textnumber, $self->{numbername}{$num[0]};
  623. # add hundred designation
  624. push @textnumber, $self->{numbername}{10**2};
  625. # reduce numblock
  626. $numblock[$i] -= $num[0] * 100;
  627. }
  628. if ($numblock[$i] > 9) {
  629. # tens
  630. push @textnumber, $self->format_ten_nl($numblock[$i]);
  631. } else {
  632. # ones
  633. push @textnumber, $self->{numbername}{$numblock[$i]};
  634. }
  635. # add thousand, million
  636. if ($i) {
  637. $amount = 10**($i * 3);
  638. push @textnumber, $self->{numbername}{$amount};
  639. }
  640. pop @numblock;
  641. }
  642. push @textnumber, '**';
  643. join '', @textnumber;
  644. }
  645. sub format_ten_nl {
  646. my ($self, $amount) = @_;
  647. my $textnumber = "";
  648. my @num = split //, $amount;
  649. if ($amount > 20) {
  650. # reverse one and ten and glue together with 'en'
  651. $amount = $num[0] * 10;
  652. $textnumber = $self->{numbername}{$num[1]}.'en'.$self->{numbername}{$amount};
  653. } else {
  654. $textnumber = $self->{numbername}{$amount};
  655. }
  656. $textnumber;
  657. }
  658. sub num2text_it {
  659. my ($self, $amount) = @_;
  660. return $self->{numbername}{0} unless $amount;
  661. my @textnumber = ();
  662. # split amount into chunks of 3
  663. my @num = reverse split //, abs($amount);
  664. my @numblock = ();
  665. my ($i, $appendn);
  666. my @a = ();
  667. while (@num) {
  668. @a = ();
  669. for (1 .. 3) {
  670. push @a, shift @num;
  671. }
  672. push @numblock, join / /, reverse @a;
  673. }
  674. while (@numblock) {
  675. $i = $#numblock;
  676. @num = split //, $numblock[$i];
  677. $numblock[$i] *= 1;
  678. if ($numblock[$i] == 0) {
  679. pop @numblock;
  680. next;
  681. }
  682. if ($numblock[$i] > 99) {
  683. # the one from hundreds
  684. push @textnumber, $self->{numbername}{$num[0]};
  685. # add hundred designation
  686. push @textnumber, $self->{numbername}{10**2};
  687. # reduce numblock
  688. $numblock[$i] -= $num[0] * 100;
  689. }
  690. if ($numblock[$i] > 9) {
  691. # tens
  692. push @textnumber, $self->format_ten_it($numblock[$i]);
  693. } elsif ($numblock[$i] > 1) {
  694. # ones
  695. push @textnumber, $self->{numbername}{$numblock[$i]};
  696. }
  697. # add thousand, million
  698. if ($i) {
  699. $amount = 10**($i * 3);
  700. push @textnumber, $self->{numbername}{$amount};
  701. }
  702. pop @numblock;
  703. }
  704. join '', @textnumber;
  705. }
  706. sub format_ten_it {
  707. my ($self, $amount) = @_;
  708. my $textnumber = "";
  709. my @num = split //, $amount;
  710. if ($amount > 20) {
  711. if ($num[1] == 0) {
  712. $textnumber = $self->{numbername}{$amount};
  713. } else {
  714. $amount = $num[0] * 10;
  715. $textnumber = $self->{numbername}{$amount}.$self->{numbername}{$num[1]};
  716. }
  717. } else {
  718. $textnumber = $self->{numbername}{$amount};
  719. }
  720. $textnumber;
  721. }
  722. # A special (swedish-like) spelling of danish check numbers
  723. sub num2text_da {
  724. my ($self, $amount) = @_;
  725. # Handle 0
  726. return $self->{numbername}{0} unless $amount;
  727. # List of collected digits
  728. my @textnumber = ();
  729. # split amount into chunks of 3
  730. my @num = reverse split //, abs($amount);
  731. my @numblock = ();
  732. my @a = ();
  733. while (@num) {
  734. @a = ();
  735. for (1 .. 3) {
  736. push @a, shift @num;
  737. }
  738. push @numblock, join / /, reverse @a;
  739. }
  740. my $i;
  741. my $bigplural;
  742. while (@numblock) {
  743. $i = $#numblock;
  744. $numblock[$i] *= 1;
  745. if ($numblock[$i] == 0) {
  746. pop @numblock;
  747. next;
  748. }
  749. # Plural suffix "er" for million and up, not for tusinde
  750. $bigpluralsuffix = "";
  751. $bigpluralsuffix = "er" if ($i > 1 && $numblock[$i] > 1);
  752. if ($numblock[$i] > 99) {
  753. @num = split //, $numblock[$i];
  754. # the one from hundreds
  755. push @textnumber, $self->{numbername}{$num[0]};
  756. # add hundred designation
  757. push @textnumber, $self->{numbername}{100};
  758. # reduce numblock
  759. $numblock[$i] -= $num[0] * 100;
  760. }
  761. if ($numblock[$i] > 9) {
  762. @num = split //, $numblock[$i];
  763. # the one from tens
  764. push @textnumber, $self->{numbername}{$num[0]};
  765. # add ten designation
  766. push @textnumber, $self->{numbername}{10};
  767. # reduce numblock
  768. $numblock[$i] -= $num[0] * 10;
  769. }
  770. if ($numblock[$i] > 0) {
  771. # the ones left in the block
  772. if($numblock[$i] == 1 && $i != 1) {
  773. push @textnumber, $self->{numbername}{'1o'}; # Special case for "Et" tusinde
  774. } else {
  775. push @textnumber, $self->{numbername}{$numblock[$i]};
  776. }
  777. }
  778. # add thousand, million, etc
  779. if ($i) {
  780. $amount = 10**($i * 3);
  781. push @textnumber, $self->{numbername}{$amount}.$bigpluralsuffix;
  782. }
  783. pop @numblock;
  784. }
  785. join '', @textnumber;
  786. }
  787. 1;