[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SF.net SVN: ledger-smb: [365] trunk/LedgerSMB/Num2text.pm



Revision: 365
          http://svn.sourceforge.net/ledger-smb/?rev=365&view=rev
Author:   tetragon
Date:     2006-10-28 19:03:13 -0700 (Sat, 28 Oct 2006)

Log Message:
-----------
Add the messiness of eight sets of numeral to text conversion rules

Modified Paths:
--------------
    trunk/LedgerSMB/Num2text.pm

Modified: trunk/LedgerSMB/Num2text.pm
===================================================================
--- trunk/LedgerSMB/Num2text.pm	2006-10-28 19:17:32 UTC (rev 364)
+++ trunk/LedgerSMB/Num2text.pm	2006-10-29 02:03:13 UTC (rev 365)
@@ -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 @@
 		   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 @@
 		   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 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 @@
     
 		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 format_ten {
+sub format_ten_en {
 	my ($self, $amount) = @_;
   
 	my $textnumber = "";
@@ -164,5 +196,735 @@
 }
 
 
+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/\xF3/o/;
+					push @textnumber, $a;
+				} elsif ($i == 3) {
+					$num = 10**($i * 2);
+					$a = "$self->{10**3} $self->{numbername}{$num}"."es";
+					$a =~ s/\xF3/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;
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.