summaryrefslogtreecommitdiff
path: root/LedgerSMB/Num2text.pm
diff options
context:
space:
mode:
Diffstat (limited to 'LedgerSMB/Num2text.pm')
-rwxr-xr-xLedgerSMB/Num2text.pm766
1 files changed, 764 insertions, 2 deletions
diff --git a/LedgerSMB/Num2text.pm b/LedgerSMB/Num2text.pm
index 252f8f06..39930fc5 100755
--- a/LedgerSMB/Num2text.pm
+++ b/LedgerSMB/Num2text.pm
@@ -35,6 +35,12 @@
sub init {
my $self = shift;
my $locale = $self->{'locale'};
+ my $langtag = substr($locale->language_tag, 0, 2);
+ $self->{'numrules'} = 'en';
+ $self->{'numrules'} = $langtag if
+ grep {/$langtag/} (qw/ca de es et fr hu it nl ru/);
+ $self->{'numrules'} = 'es' if $self->{'numrules'} eq 'ca';
+ $self->{'numrules'} = 'de' if $self->{'numrules'} eq 'ru';
%{ $self->{numbername} } =
(0 => $locale->text('Zero'),
@@ -58,6 +64,15 @@ sub init {
18 => $locale->text('Eighteen'),
19 => $locale->text('Nineteen'),
20 => $locale->text('Twenty'),
+ 21 => $locale->text('Twenty One'),
+ 22 => $locale->text('Twenty Two'),
+ 23 => $locale->text('Twenty Three'),
+ 24 => $locale->text('Twenty Four'),
+ 25 => $locale->text('Twenty Five'),
+ 26 => $locale->text('Twenty Six'),
+ 27 => $locale->text('Twenty Seven'),
+ 28 => $locale->text('Twenty Eight'),
+ 29 => $locale->text('Twenty Nine'),
30 => $locale->text('Thirty'),
40 => $locale->text('Forty'),
50 => $locale->text('Fifty'),
@@ -66,6 +81,9 @@ sub init {
80 => $locale->text('Eighty'),
90 => $locale->text('Ninety'),
10**2 => $locale->text('Hundred'),
+ 500 => $locale->text('Five Hundred'),
+ 700 => $locale->text('Seven Hundred'),
+ 900 => $locale->text('Nine Hundred'),
10**3 => $locale->text('Thousand'),
10**6 => $locale->text('Million'),
10**9 => $locale->text('Billion'),
@@ -78,6 +96,20 @@ sub init {
sub num2text {
my ($self, $amount) = @_;
+ return $self->num2text_de($amount) if $self->{'numrules'} eq 'de';
+ return $self->num2text_es($amount) if $self->{'numrules'} eq 'es';
+ return $self->num2text_nl($amount) if $self->{'numrules'} eq 'nl';
+ return $self->num2text_hu($amount) if $self->{'numrules'} eq 'hu';
+ return $self->num2text_et($amount) if $self->{'numrules'} eq 'et';
+ return $self->num2text_fr($amount) if $self->{'numrules'} eq 'fr';
+ return $self->num2text_it($amount) if $self->{'numrules'} eq 'it';
+ return $self->num2text_en($amount);
+}
+
+
+sub num2text_en {
+ my ($self, $amount) = @_;
+
return $self->{numbername}{0} unless $amount;
my @textnumber = ();
@@ -122,7 +154,7 @@ sub num2text {
if ($numblock[$i] > 9) {
# tens
- push @textnumber, $self->format_ten($numblock[$i]);
+ push @textnumber, $self->format_ten_en($numblock[$i]);
} elsif ($numblock[$i] > 0) {
# ones
push @textnumber, $self->{numbername}{$numblock[$i]};
@@ -143,7 +175,7 @@ sub num2text {
}
-sub format_ten {
+sub format_ten_en {
my ($self, $amount) = @_;
my $textnumber = "";
@@ -164,5 +196,735 @@ sub format_ten {
}
+sub num2text_de {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my ($i, $appendn);
+ my @a = ();
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+ my $belowhundred = !$#numblock;
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+ $appendn = "";
+
+ $numblock[$i] *= 1;
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ # the one from hundreds
+ push @textnumber, $self->{numbername}{$num[0]};
+
+ # add hundred designation
+ push @textnumber, $self->{numbername}{10**2};
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+ }
+
+ $appendn = 'en' if ($i == 2);
+ $appendn = 'n' if ($i > 2);
+
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_de($numblock[$i], $belowhundred);
+ } elsif ($numblock[$i] > 1) {
+ # ones
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ } elsif ($numblock[$i] == 1) {
+ if ($i == 0) {
+ push @textnumber, $self->{numbername}{$numblock[$i]}.'s';
+ } else {
+ if ($i >= 2) {
+ push @textnumber, $self->{numbername}{$numblock[$i]}.'e';
+ } else {
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+ }
+ $appendn = "";
+ }
+
+ # add thousand, million
+ if ($i) {
+ $amount = 10**($i * 3);
+ push @textnumber, $self->{numbername}{$amount}.$appendn;
+ }
+
+ pop @numblock;
+
+ }
+
+ join '', @textnumber;
+
+}
+
+
+sub format_ten_de {
+ my ($self, $amount, $belowhundred) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+
+ if ($amount > 20) {
+ if ($num[1] == 0) {
+ $textnumber = $self->{numbername}{$amount};
+ } else {
+ if ($belowhundred) {
+ $amount = $num[0] * 10;
+ $textnumber = $self->{numbername}{$num[1]}.'und'.$self->{numbername}{$amount};
+ } else {
+ $amount = $num[0] * 10;
+ $textnumber = $self->{numbername}{$amount}.$self->{numbername}{$num[1]};
+ $textnumber .= 's' if ($num[1] == 1);
+ }
+ }
+ } else {
+ $textnumber = $self->{numbername}{$amount};
+ }
+
+ $textnumber;
+
+}
+
+
+sub num2text_et {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my ($i, $appendit);
+ my @a = ();
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ $numblock[$i] *= 1;
+ @num = split //, $numblock[$i];
+
+ $appendit = "it";
+ $hundred = 0;
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ # the one from hundreds
+ push @textnumber, "$self->{numbername}{$num[0]}$self->{numbername}{10**2}";
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+ @num = split //, $numblock[$i];
+ $hundred = 1;
+ }
+
+ if ($numblock[$i] > 19) {
+ # 20 - 99
+ push @textnumber, "$self->{numbername}{$num[0]}kümmend";
+ @num = split //, $numblock[$i];
+ push @textnumber, $self->{numbername}{$num[1]} if $num[1] > 0;
+
+ } elsif ($numblock[$i] > 10) {
+ # 11 - 19
+ if ($hundred) {
+ @num = split //, $numblock[$i];
+ }
+ $num = $num[1];
+
+ push @textnumber, "$self->{numbername}{$num}teist";
+
+ } elsif ($numblock[$i] > 1) {
+ # ones
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+
+ } elsif ($numblock[$i] == 1) {
+ push @textnumber, $self->{numbername}{$num[0]};
+ $appendit = "";
+
+ }
+
+ # add thousand, million
+ if ($i) {
+ $amount = 10**($i * 3);
+ $appendit = ($i == 1) ? "" : $appendit;
+ push @textnumber, "$self->{numbername}{$amount}$appendit";
+ }
+
+ pop @numblock;
+
+ }
+
+ join ' ', @textnumber;
+
+}
+
+
+sub num2text_es {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my $stripun = 0;
+ my @a = ();
+ my $i;
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+ # special case for 1000
+ if ($numblock[1] eq '1' && $numblock[0] gt '000') {
+ # remove first array element from textnumber
+ $stripun = 1;
+ }
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+
+ $numblock[$i] *= 1;
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ if ($num[0] == 1) {
+ push @textnumber, $self->{numbername}{10**2};
+ } else {
+ # special case for 500, 700, 900
+ if (grep /$num[0]/, (5,7,9)) {
+ push @textnumber, $self->{numbername}{"${num[0]}00"};
+
+ } else {
+
+ # the one from hundreds, append cientos
+ push @textnumber, $self->{numbername}{$num[0]}.$self->{numbername}{10**2}.'s';
+
+ }
+ }
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+ }
+
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_es($numblock[$i], $i);
+ } elsif ($numblock[$i] > 0) {
+ # ones
+ $num = $numblock[$i];
+ $num .= 'o' if ($num == 1 && $i == 0);
+ push @textnumber, $self->{numbername}{$num};
+ }
+
+ # add thousand, million
+ if ($i) {
+ $num = 10**($i * 3);
+ if ($numblock[$i] > 1) {
+ if ($i == 2 || $i == 4) {
+ $a = $self->{numbername}{$num}."es";
+ $a =~ s/ó/o/;
+ push @textnumber, $a;
+ } elsif ($i == 3) {
+ $num = 10**($i * 2);
+ $a = "$self->{10**3} $self->{numbername}{$num}"."es";
+ $a =~ s/ó/o/;
+ push @textnumber, $a;
+ } else {
+ if ($i == 1) {
+ push @textnumber, $self->{numbername}{$num};
+ } else {
+ push @textnumber, $self->{numbername}{$num}.'s';
+ }
+ }
+ } else {
+ push @textnumber, $self->{numbername}{$num};
+ }
+ }
+
+ pop @numblock;
+
+ }
+
+ shift @textnumber if $stripun;
+
+ join ' ', @textnumber;
+
+}
+
+
+sub format_ten_es {
+ my ($self, $amount, $i) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+
+ if ($amount > 30) {
+ $textnumber = $self->{numbername}{$num[0]*10};
+ $amount = $num[1];
+ } else {
+ $amount .= 'o' if ($num[1] == 1 && $i == 0);
+ $textnumber = $self->{numbername}{$amount};
+ $amount = 0;
+ }
+
+ $textnumber .= " y ".$self->{numbername}{$amount} if $amount;
+
+ $textnumber;
+
+}
+
+
+sub num2text_fr {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my @a;
+ my $i;
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+ my $cent=0;
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ $cent=1;
+
+ # the one from hundreds
+
+ if ($num[0] > 1) {
+ push @textnumber, $self->{numbername}{$num[0]};
+ }
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+
+ # add hundred designation
+ if ($num[0] > 1) {
+ if($numblock[$i] > 0) {
+ push @textnumber, $self->{numbername}{10**2};
+ } else {
+ push @textnumber, "$self->{numbername}{10**2}s";
+ }
+ } else {
+ push @textnumber, $self->{numbername}{10**2};
+ }
+
+ }
+
+ $numblock[$i] *= 1;
+
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_fr($numblock[$i]);
+ } elsif ($numblock[$i] > 0) {
+ # ones
+ if ($i == 1) {
+ if ($cent == 1) {
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+ $cent = 0;
+ } else {
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+ }
+
+ # add thousand, million
+ if ($i) {
+ $num = 10**($i * 3);
+ if ($i == 1) {
+ push @textnumber, $self->{numbername}{$num};
+ } elsif ($numblock[$i] > 1) {
+ push @textnumber, "$self->{numbername}{$num}s";
+ } else {
+ push @textnumber, "$self->{numbername}{$num}";
+ }
+ }
+
+ pop @numblock;
+
+ }
+
+ join ' ', @textnumber;
+
+}
+
+
+sub format_ten_fr {
+ my ($self, $amount) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+
+ if ($amount > 20) {
+ if ($num[0] == 8) {
+ if ($num[1] > 0) {
+ $textnumber = $self->{numbername}{$num[0]*10};
+ } else {
+ $textnumber = "$self->{numbername}{$num[0]*10}s";
+ }
+ $amount = $num[1];
+ } elsif ($num[0] == 7 || $num[0] == 9) {
+ if ($num[1] > 0) {
+ $textnumber = $self->{numbername}{($num[0]-1)*10};
+
+ $textnumber .= " et" if ($num[1] == 1 && $num[0] == 7);
+
+ $amount -= ($num[0]-1)*10;
+ } else {
+ $textnumber = $self->{numbername}{$num[0]*10};
+ $amount = $num[1];
+ }
+ } else {
+ $textnumber = $self->{numbername}{$num[0]*10};
+ $textnumber .= " et" if ($num[1] == 1);
+ $amount = $num[1];
+ }
+ } else {
+ $textnumber = "$self->{numbername}{$amount}";
+ $amount = 0;
+ }
+
+ $textnumber .= " ".$self->{numbername}{$amount} if $amount;
+
+ $textnumber;
+
+}
+
+
+sub num2text_hu {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my @a;
+ my $i;
+ my $res;
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+ while (@numblock) {
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+ if ($numblock[$i] > 99) {
+ push @textnumber, $self->{numbername}{$num[0]};
+
+ # add hundred designation
+ push @textnumber, $self->{numbername}{10**2};
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+
+ }
+
+ $numblock[$i] *= 1;
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_hu($numblock[$i]);
+ } elsif ($numblock[$i] > 0) {
+ # ones
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+
+ # add thousand, million
+ if ($i) {
+ if ($i==1 && $amount < 2000){
+
+ $num = 10**($i * 3);
+ push @textnumber, $self->{numbername}{$num};
+ } else {
+
+ $num = 10**($i * 3);
+ push @textnumber, $self->{numbername}{$num}."-";
+ }
+ }
+
+ pop @numblock;
+
+ }
+ $res=ucfirst join '', @textnumber;
+ $res=~s/(\-)$//;
+ return $res;
+}
+
+
+sub format_ten_hu {
+ my ($self, $amount) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+ if ($amount > 30) {
+ $textnumber = $self->{numbername}{$num[0]*10};
+ $amount = $num[1];
+ } else {
+ $textnumber = $self->{numbername}{$amount};
+ $amount = 0;
+ }
+
+ $textnumber .= "".$self->{numbername}{$amount} if $amount;
+
+ $textnumber;
+
+}
+
+
+sub num2text_nl {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ('**');
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my ($i, $appendn);
+ my @a = ();
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+
+ $numblock[$i] *= 1;
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ # the one from hundreds
+ push @textnumber, $self->{numbername}{$num[0]};
+
+ # add hundred designation
+ push @textnumber, $self->{numbername}{10**2};
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+ }
+
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_nl($numblock[$i]);
+ } else {
+ # ones
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+
+ # add thousand, million
+ if ($i) {
+ $amount = 10**($i * 3);
+ push @textnumber, $self->{numbername}{$amount};
+ }
+
+ pop @numblock;
+
+ }
+
+ push @textnumber, '**';
+ join '', @textnumber;
+
+}
+
+
+sub format_ten_nl {
+ my ($self, $amount) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+
+ if ($amount > 20) {
+ # reverse one and ten and glue together with 'en'
+ $amount = $num[0] * 10;
+ $textnumber = $self->{numbername}{$num[1]}.'en'.$self->{numbername}{$amount};
+ } else {
+ $textnumber = $self->{numbername}{$amount};
+ }
+
+ $textnumber;
+
+}
+
+
+sub num2text_it {
+ my ($self, $amount) = @_;
+
+ return $self->{numbername}{0} unless $amount;
+
+ my @textnumber = ();
+
+ # split amount into chunks of 3
+ my @num = reverse split //, abs($amount);
+ my @numblock = ();
+ my ($i, $appendn);
+ my @a = ();
+
+ while (@num) {
+ @a = ();
+ for (1 .. 3) {
+ push @a, shift @num;
+ }
+ push @numblock, join / /, reverse @a;
+ }
+
+ while (@numblock) {
+
+ $i = $#numblock;
+ @num = split //, $numblock[$i];
+
+ $numblock[$i] *= 1;
+
+ if ($numblock[$i] == 0) {
+ pop @numblock;
+ next;
+ }
+
+ if ($numblock[$i] > 99) {
+ # the one from hundreds
+ push @textnumber, $self->{numbername}{$num[0]};
+
+ # add hundred designation
+ push @textnumber, $self->{numbername}{10**2};
+
+ # reduce numblock
+ $numblock[$i] -= $num[0] * 100;
+ }
+
+ if ($numblock[$i] > 9) {
+ # tens
+ push @textnumber, $self->format_ten_it($numblock[$i]);
+ } elsif ($numblock[$i] > 1) {
+ # ones
+ push @textnumber, $self->{numbername}{$numblock[$i]};
+ }
+
+ # add thousand, million
+ if ($i) {
+ $amount = 10**($i * 3);
+ push @textnumber, $self->{numbername}{$amount};
+ }
+
+ pop @numblock;
+
+ }
+
+ join '', @textnumber;
+
+}
+
+
+sub format_ten_it {
+ my ($self, $amount) = @_;
+
+ my $textnumber = "";
+ my @num = split //, $amount;
+
+ if ($amount > 20) {
+ if ($num[1] == 0) {
+ $textnumber = $self->{numbername}{$amount};
+ } else {
+ $amount = $num[0] * 10;
+ $textnumber = $self->{numbername}{$amount}.$self->{numbername}{$num[1]};
+ }
+ } else {
+ $textnumber = $self->{numbername}{$amount};
+ }
+
+ $textnumber;
+
+}
+
+
1;