diff options
-rwxr-xr-x | LedgerSMB/Num2text.pm | 766 |
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; |