--- loncom/interface/spreadsheet/Spreadsheet.pm	2003/09/05 01:06:45	1.22
+++ loncom/interface/spreadsheet/Spreadsheet.pm	2004/02/24 17:02:04	1.35
@@ -1,5 +1,5 @@
 #
-# $Id: Spreadsheet.pm,v 1.22 2003/09/05 01:06:45 matthew Exp $
+# $Id: Spreadsheet.pm,v 1.35 2004/02/24 17:02:04 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -48,8 +48,8 @@ Spreadsheet
 package Apache::Spreadsheet;
 
 use strict;
-use warnings FATAL=>'all';
-no warnings 'uninitialized';
+#use warnings FATAL=>'all';
+#no warnings 'uninitialized';
 use Apache::Constants qw(:common :http);
 use Apache::lonnet;
 use Safe;
@@ -59,6 +59,7 @@ use HTML::Entities();
 use HTML::TokeParser;
 use Spreadsheet::WriteExcel;
 use Time::HiRes;
+use Apache::lonlocal;
 
 ##
 ## Package Variables
@@ -159,7 +160,8 @@ sub filename {
         if ($newfilename !~ /\w/ || $newfilename =~ /^\W*$/) {
             $newfilename = 'default_'.$self->{'type'};
         }
-        if ($newfilename !~ /^default\.$self->{'type'}$/ ) {
+        if ($newfilename !~ /^default\.$self->{'type'}$/ &&
+            $newfilename !~ /^\/res\/(.*)spreadsheet$/) {
             if ($newfilename !~ /_$self->{'type'}$/) {
                 $newfilename =~ s/[\s_]*$//;
                 $newfilename .= '_'.$self->{'type'};
@@ -231,6 +233,16 @@ sub initialize {
     # the descendents of the spreadsheet class.
 }
 
+sub clear_package {
+    # This method is here to remind you that it will be overridden by
+    # the descendents of the spreadsheet class.
+}
+
+sub cleanup {
+    my $self = shift();
+    $self->clear_package();
+}
+
 sub initialize_spreadsheet_package {
     &load_spreadsheet_expirationdates();
     &clear_spreadsheet_definition_cache();
@@ -289,18 +301,23 @@ Returns the safe space required by a Spr
 =cut
 
 ######################################################
+{ 
+
+    my $safeeval;
+
 sub initialize_safe_space {
-    my $self = shift;
-    my $safeeval = new Safe(shift);
-    my $safehole = new Safe::Hole;
-    $safeeval->permit("entereval");
-    $safeeval->permit(":base_math");
-    $safeeval->permit("sort");
-    $safeeval->deny(":base_io");
-    $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
-    $safehole->wrap(\&mask,$safeeval,'&mask');
-    $safeeval->share('$@');
-    my $code=<<'ENDDEFS';
+  my $self = shift;
+  if (! defined($safeeval)) {
+      $safeeval = new Safe(shift);
+      my $safehole = new Safe::Hole;
+      $safeeval->permit("entereval");
+      $safeeval->permit(":base_math");
+      $safeeval->permit("sort");
+      $safeeval->deny(":base_io");
+      $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
+      $safehole->wrap(\&mask,$safeeval,'&mask');
+      $safeeval->share('$@');
+      my $code=<<'ENDDEFS';
 # ---------------------------------------------------- Inside of the safe space
 #
 # f: formulas
@@ -365,7 +382,7 @@ returns the number of items in the range
 #-------------------------------------------------------
 sub NUM {
     my $mask=&mask(@_);
-    my $num= $#{@{grep(/$mask/,keys(%sheet_values))}}+1;
+    my $num= $#{@{grep(eval("/$mask/"),keys(%sheet_values))}}+1;
     return $num;   
 }
 
@@ -382,7 +399,7 @@ sub BIN {
     my ($low,$high,$lower,$upper)=@_;
     my $mask=&mask($lower,$upper);
     my $num=0;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         if (($sheet_values{$_}>=$low) && ($sheet_values{$_}<=$high)) {
             $num++;
         }
@@ -404,7 +421,7 @@ returns the sum of items in the range.
 sub SUM {
     my $mask=&mask(@_);
     my $sum=0;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         $sum+=$sheet_values{$_};
     }
     return $sum;   
@@ -425,7 +442,7 @@ sub MEAN {
     my $mask=&mask(@_);
     my $sum=0; 
     my $num=0;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         $sum+=$sheet_values{$_};
         $num++;
     }
@@ -450,14 +467,14 @@ compute the standard deviation of the it
 sub STDDEV {
     my $mask=&mask(@_);
     my $sum=0; my $num=0;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         $sum+=$sheet_values{$_};
         $num++;
     }
     unless ($num>1) { return undef; }
     my $mean=$sum/$num;
     $sum=0;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         $sum+=($sheet_values{$_}-$mean)**2;
     }
     return sqrt($sum/($num-1));    
@@ -477,7 +494,7 @@ compute the product of the items in the
 sub PROD {
     my $mask=&mask(@_);
     my $prod=1;
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         $prod*=$sheet_values{$_};
     }
     return $prod;   
@@ -497,7 +514,7 @@ compute the maximum of the items in the
 sub MAX {
     my $mask=&mask(@_);
     my $max='-';
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         unless ($max) { $max=$sheet_values{$_}; }
         if (($sheet_values{$_}>$max) || ($max eq '-')) { 
             $max=$sheet_values{$_}; 
@@ -520,7 +537,7 @@ compute the minimum of the items in the
 sub MIN {
     my $mask=&mask(@_);
     my $min='-';
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
         unless ($max) { $max=$sheet_values{$_}; }
         if (($sheet_values{$_}<$min) || ($min eq '-')) { 
             $min=$sheet_values{$_}; 
@@ -545,7 +562,7 @@ sub SUMMAX {
     my ($num,$lower,$upper)=@_;
     my $mask=&mask($lower,$upper);
     my @inside=();
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
 	push (@inside,$sheet_values{$_});
     }
     @inside=sort(@inside);
@@ -572,7 +589,7 @@ sub SUMMIN {
     my ($num,$lower,$upper)=@_;
     my $mask=&mask($lower,$upper);
     my @inside=();
-    foreach (grep /$mask/,keys(%sheet_values)) {
+    foreach (grep eval("/$mask/"),keys(%sheet_values)) {
 	$inside[$#inside+1]=$sheet_values{$_};
     }
     @inside=sort(@inside);
@@ -598,7 +615,6 @@ parametername should be a string such as
 sub MINPARM {
     my ($expression) = @_;
     my $min = undef;
-    study($expression);
     foreach $parameter (keys(%c)) {
         next if ($parameter !~ /$expression/);
         if ((! defined($min)) || ($min > $c{$parameter})) {
@@ -623,7 +639,6 @@ parametername should be a string such as
 sub MAXPARM {
     my ($expression) = @_;
     my $max = undef;
-    study($expression);
     foreach $parameter (keys(%c)) {
         next if ($parameter !~ /$expression/);
         if ((! defined($min)) || ($max < $c{$parameter})) {
@@ -662,12 +677,13 @@ sub calc {
             return $lastcalc.': Maximum calculation depth exceeded';
         }
     }
-    return '';
+    return 'okay';
 }
 
 # ------------------------------------------- End of "Inside of the safe space"
 ENDDEFS
-    $safeeval->reval($code);
+        $safeeval->reval($code);
+    }
     $self->{'safe'} = $safeeval;
     $self->{'root'} = $self->{'safe'}->root();
     #
@@ -681,6 +697,9 @@ ENDDEFS
     $self->{'safe'}->reval($initstring);
     return $self;
 }
+
+}
+
 ######################################################
 
 =pod
@@ -694,6 +713,17 @@ ENDDEFS
 
 ######################################################
 
+=pod
+
+=item  &mask($lower,$upper)
+
+Inputs: $lower and $upper, cell names ("X12" or "a150") or globs ("X*").
+
+Returns:  Regular expression matching spreadsheet cells that are within
+the rectangle defined by $lower and $upper.  Due to the nature of the
+regular expression this result must be used inside an eval().
+
+=cut
 
 ######################################################
 {
@@ -708,78 +738,62 @@ sub mask {
     }
     $upper = $lower if (! defined($upper));
     #
-    my ($la,$ld) = ($lower=~/([A-Za-z]|\*)(\d+|\*)/);
-    my ($ua,$ud) = ($upper=~/([A-Za-z]|\*)(\d+|\*)/);
+    my ($la,$ld) = ($lower=~/([A-z]|\*)(\d+|\*)/);
+    my ($ua,$ud) = ($upper=~/([A-z]|\*)(\d+|\*)/);
     #
     my $alpha='';
     my $num='';
     #
+    # Do not put parenthases around $alpha.
+    # $num depends on the value in $1.
     if (($la eq '*') || ($ua eq '*')) {
-        $alpha='[A-Za-z]';
+        $alpha='[A-z]';
     } else {
-       if (($la=~/[A-Z]/) && ($ua=~/[A-Z]/) ||
-           ($la=~/[a-z]/) && ($ua=~/[a-z]/)) {
-          $alpha='['.$la.'-'.$ua.']';
-       } else {
-          $alpha='['.$la.'-Za-'.$ua.']';
-       }
-    }   
-    if (($ld eq '*') || ($ud eq '*')) {
-	$num='\d+';
+        if ($la gt $ua) {
+            my $tmp = $ua;
+            $ua = $la;
+            $la = $ua;
+        }
+        $alpha=qq/[$la-$ua]/;
+    }
+    if ($ld ne '*' && $ud ne '*') {
+        # Make sure $ld <= $ud
+        if ($ld > $ud) {
+            my $tmp = $ud;
+            $ud = $ld;
+            $ld = $tmp;
+        }
+        # Here we make a regular expression using some advanced regexp
+        # abilities.
+        # (\d+) will match the digits of the cell name and dump them in
+        #     to $1
+        # (?(?{ ... code ...} pattern_if_true | pattern_if_false)) will
+        #     choose pattern_if_true if { ... code ... } is true and
+        #     pattern_if_false if { ... code ... } is false.
+        # In this case, pattern_if_true is empty.  pattern_if_false is 
+        #     'donotmatch' and will not match our cells because none of 
+        #     them end with donotmatch.  
+        # Unfortunately, the use of this type of regular expression 
+        #     requires that each match be wrapped in an eval().  Search for
+        #     $mask in this module for examples
+        $num = '(\d+)(?(?{$1>= '.$ld.' && $1<='.$ud.'})|donotmatch)';
     } else {
-        if (length($ld)!=length($ud)) {
-           $num.='(';
-	   foreach ($ld=~m/\d/g) {
-              $num.='['.$_.'-9]';
-	   }
-           if (length($ud)-length($ld)>1) {
-              $num.='|\d{'.(length($ld)+1).','.(length($ud)-1).'}';
-	   }
-           $num.='|';
-           foreach ($ud=~m/\d/g) {
-               $num.='[0-'.$_.']';
-           }
-           $num.=')';
-       } else {
-           my @lda=($ld=~m/\d/g);
-           my @uda=($ud=~m/\d/g);
-           my $i; 
-           my $j=0; 
-           my $notdone=1;
-           for ($i=0;($i<=$#lda)&&($notdone);$i++) {
-               if ($lda[$i]==$uda[$i]) {
-		   $num.=$lda[$i];
-                   $j=$i;
-               } else {
-                   $notdone=0;
-               }
-           }
-           if ($j<$#lda-1) {
-	       $num.='('.$lda[$j+1];
-               for ($i=$j+2;$i<=$#lda;$i++) {
-                   $num.='['.$lda[$i].'-9]';
-               }
-               if ($uda[$j+1]-$lda[$j+1]>1) {
-		   $num.='|['.($lda[$j+1]+1).'-'.($uda[$j+1]-1).']\d{'.
-                   ($#lda-$j-1).'}';
-               }
-	       $num.='|'.$uda[$j+1];
-               for ($i=$j+2;$i<=$#uda;$i++) {
-                   $num.='[0-'.$uda[$i].']';
-               }
-               $num.=')';
-           } else {
-               if ($lda[-1]!=$uda[-1]) {
-                  $num.='['.$lda[-1].'-'.$uda[-1].']';
-	       }
-           }
-       }
+        $num = '(\d+)';
     }
-    my $expression ='^'.$alpha.$num."\$";
+    my $expression = '^'.$alpha.$num.'$';
     $memoizer{$key} = $expression;
     return $expression;
 }
 
+#
+# Debugging routine
+sub dump_memoized_values {
+    while (my ($key,$value) = each(%memoizer)) {
+        &Apache::lonnet::logthis('memoizer: '.$key.' = '.$value);
+    }
+    return;
+}
+
 }
 
 ##
@@ -830,7 +844,6 @@ sub expandnamed {
         my @matches = ();
         my @values = ();
         $#matches = -1;
-        study $expression;
         while (my($parameter,$value) = each(%{$self->{'constants'}})) {
             next if ($parameter !~ /$expression/);
             push(@matches,$parameter);
@@ -1124,9 +1137,49 @@ sub calcsheet {
 #    $self->logthis($self->get_errorlog());
     %{$self->{'values'}} = %{$self->{'safe'}->varglob('sheet_values')};
 #    $self->logthis($self->get_errorlog());
+    if ($result ne 'okay') {
+        $self->set_calcerror($result);
+    }
     return $result;
 }
 
+sub set_badcalc {
+    my $self = shift();
+    $self->{'badcalc'} =1;
+    return;
+}
+
+sub badcalc {
+    my $self = shift;
+    if (exists($self->{'badcalc'}) && $self->{'badcalc'}) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+sub set_calcerror {
+    my $self = shift;
+    if (@_) {
+        $self->set_badcalc();
+        if (exists($self->{'calcerror'})) {
+            $self->{'calcerror'}.="\n".$_[0];
+        } else {
+            $self->{'calcerror'}.=$_[0];
+        }
+    }
+}
+
+sub calcerror {
+    my $self = shift;
+    if ($self->badcalc()) {
+        if (exists($self->{'calcerror'})) {
+            return $self->{'calcerror'};
+        }
+    }
+    return;
+}
+
 ###########################################################
 ##
 ## Output Helpers
@@ -1135,17 +1188,28 @@ sub calcsheet {
 sub display {
     my $self = shift;
     my ($r) = @_;
-    $self->compute($r);
     my $outputmode = 'html';
-    if ($ENV{'form.output_format'} =~ /^(html|excel|csv)$/) {
-        $outputmode = $ENV{'form.output_format'};
+    foreach ($self->output_options()) {
+        if ($ENV{'form.output_format'} eq $_->{'value'}) {
+            $outputmode = $_->{'value'};
+            last;
+        }
     }
     if ($outputmode eq 'html') {
+        $self->compute($r);
         $self->outsheet_html($r);
+    } elsif ($outputmode eq 'htmlclasslist') {
+        # No computation neccessary...  This is kludgy
+        $self->outsheet_htmlclasslist($r);
     } elsif ($outputmode eq 'excel') {
+        $self->compute($r);
         $self->outsheet_excel($r);
     } elsif ($outputmode eq 'csv') {
+        $self->compute($r);
         $self->outsheet_csv($r);
+    } elsif ($outputmode eq 'xml') {
+#        $self->compute($r);
+        $self->outsheet_xml($r);
     }
     $self->cleanup();
     return;
@@ -1154,6 +1218,18 @@ sub display {
 ############################################
 ##         HTML output routines           ##
 ############################################
+sub html_report_error {
+    my $self = shift();
+    my $Str = '';
+    if ($self->badcalc()) {
+        $Str = '<h3 style="color:red">'.
+            &mt('An error occurred while calculating this spreadsheet').
+            "</h3>\n".
+            '<pre>'.$self->calcerror()."</pre>\n";
+    }
+    return $Str;
+}
+
 sub html_export_row {
     my $self = shift();
     my ($color) = @_;
@@ -1268,12 +1344,27 @@ sub html_header {
     my $self = shift;
     return '' if (! $ENV{'request.role.adv'});
     return "<table>\n".
-        '<tr><th align="center">Output Format</th><tr>'."\n".
-        '<tr><td>'.&output_selector()."</td></tr>\n".
+        '<tr><th align="center">'.&mt('Output Format').'</th></tr>'."\n".
+        '<tr><td>'.$self->output_selector()."</td></tr>\n".
         "</table>\n";
 }
 
+##
+## Default output types are HTML, Excel, and CSV
+sub output_options {
+    my $self = shift();
+    return  ({value       => 'html',
+              description => 'HTML'},
+             {value       => 'excel',
+              description => 'Excel'},
+#             {value       => 'xml',
+#              description => 'XML'},
+             {value       => 'csv',
+              description => 'Comma Separated Values'},);
+}
+
 sub output_selector {
+    my $self = shift();
     my $output_selector = '<select name="output_format" size="3">'."\n";
     my $default = 'html';
     if (exists($ENV{'form.output_format'})) {
@@ -1281,15 +1372,12 @@ sub output_selector {
     } else {
         $ENV{'form.output_format'} = $default;
     }
-    foreach (['html','HTML'],
-             ['excel','Excel'],
-             ['csv','Comma Seperated Values']) {
-        my ($name,$description) = @{$_};
-        $output_selector.=qq{<option value="$name"};
-        if ($name eq $default) {
+    foreach  ($self->output_options()) {
+        $output_selector.='<option value="'.$_->{'value'}.'"';
+        if ($_->{'value'} eq $default) {
             $output_selector .= ' selected';
         }
-        $output_selector .= ">$description</option>\n";
+        $output_selector .= ">".&mt($_->{'description'})."</option>\n";
     }
     $output_selector .= "</select>\n";
     return $output_selector;
@@ -1322,9 +1410,9 @@ sub create_excel_spreadsheet {
     my $workbook  = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
     if (! defined($workbook)) {
         $r->log_error("Error creating excel spreadsheet $filename: $!");
-        $r->print("Problems creating new Excel file.  ".
+        $r->print(&mt("Problems creating new Excel file.  ".
                   "This error has been logged.  ".
-                  "Please alert your LON-CAPA administrator");
+                  "Please alert your LON-CAPA administrator"));
         return undef;
     }
     #
@@ -1338,10 +1426,25 @@ sub create_excel_spreadsheet {
     return ($workbook,$filename);
 }
 
+#
+# This routine is just a stub 
+sub outsheet_htmlclasslist {
+    my $self = shift;
+    my ($r) = @_;
+    $r->print('<h2>'.&mt("This output is not supported").'</h2>');
+    $r->rflush();
+    return;
+}
+
 sub outsheet_excel {
     my $self = shift;
     my ($r) = @_;
-    $r->print("<h2>Preparing Excel Spreadsheet</h2>");
+    my $connection = $r->connection();
+    #
+    $r->print($self->html_report_error());
+    $r->rflush();
+    #
+    $r->print("<h2>".&mt('Preparing Excel Spreadsheet')."</h2>");
     #
     # Create excel worksheet
     my ($workbook,$filename) = $self->create_excel_spreadsheet($r);
@@ -1364,7 +1467,7 @@ sub outsheet_excel {
     $self->excel_output_row($worksheet,0,$rows_output++,'Summary');
     $rows_output++;    # skip a line
     #
-    $self->excel_rows($worksheet,$cols_output,$rows_output);
+    $self->excel_rows($connection,$worksheet,$cols_output,$rows_output);
     #
     #
     # Close the excel file
@@ -1382,6 +1485,11 @@ sub outsheet_excel {
 sub outsheet_csv   {
     my $self = shift;
     my ($r) = @_;
+    my $connection = $r->connection();
+    #
+    $r->print($self->html_report_error());
+    $r->rflush();
+    #
     my $csvdata = '';
     my @Values;
     #
@@ -1392,9 +1500,9 @@ sub outsheet_csv   {
     my $file;
     unless ($file = Apache::File->new('>'.'/home/httpd'.$filename)) {
         $r->log_error("Couldn't open $filename for output $!");
-        $r->print("Problems occured in writing the csv file.  ".
+        $r->print(&mt("Problems occured in writing the csv file.  ".
                   "This error has been logged.  ".
-                  "Please alert your LON-CAPA administrator.");
+                  "Please alert your LON-CAPA administrator."));
         $r->print("<pre>\n".$csvdata."</pre>\n");
         return 0;
     }
@@ -1405,12 +1513,12 @@ sub outsheet_csv   {
     }
     #
     # Output the body of the spreadsheet
-    $self->csv_rows($file);
+    $self->csv_rows($connection,$file);
     #
     # Close the csv file
     close($file);
     $r->print('<br /><br />'.
-              '<a href="'.$filename.'">Your CSV spreadsheet.</a>'."\n");
+              '<a href="'.$filename.'">'.&mt('Your CSV spreadsheet.').'</a>'."\n");
     #
     return 1;
 }
@@ -1446,17 +1554,20 @@ sub outsheet_xml   {
     ## But not on this day
     my $Str = '<spreadsheet type="'.$self->{'type'}.'">'."\n";
     while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {
-        if ($cell =~ /^template_(\d+)/) {
+        if ($cell =~ /^template_(\w+)/) {
             my $col = $1;
             $Str .= '<template col="'.$col.'">'.$formula.'</template>'."\n";
         } else {
-            my ($row,$col) = ($cell =~ /^([A-z])(\d+)/);
+            my ($col,$row) = ($cell =~ /^([A-z])(\d+)/);
             next if (! defined($row) || ! defined($col));
-            $Str .= '<field row="'.$row.'" col="'.$col.'" >'.$formula.'</cell>'
+            next if ($row != 0);
+            $Str .= 
+                '<field row="'.$row.'" col="'.$col.'" >'.$formula.'</field>'
                 ."\n";
         }
     }
     $Str.="</spreadsheet>";
+    $r->print("<pre>\n\n\n".$Str."\n\n\n</pre>");
     return $Str;
 }
 
@@ -1483,8 +1594,7 @@ sub parse_sheet {
                 $formulas{$cell} = $formula;
                 $sources{$cell}  = $source if (defined($source));
                 $parser->get_text('/field');
-            }
-            if ($token->[1] eq 'template') {
+            } elsif ($token->[1] eq 'template') {
                 $formulas{'template_'.$token->[2]->{'col'}}=
                     $parser->get_text('/template');
             }
@@ -1538,7 +1648,7 @@ sub load {
         # Not cached, need to read
         if (! defined($filename)) {
             $formulas = $self->load_system_default_sheet();
-        } elsif($self->filename() =~ /^\/res\/.*\.spreadsheet$/) {
+        } elsif($filename =~ /^\/res\/.*\.spreadsheet$/) {
             # Load a spreadsheet definition file
             my $sheetxml=&Apache::lonnet::getfile
                 (&Apache::lonnet::filelocation('',$filename));
@@ -1601,6 +1711,9 @@ sub set_row_numbers {
 ##
 sub exportrow {
     my $self = shift;
+    if (exists($self->{'badcalc'}) && $self->{'badcalc'}) {
+        return ();
+    }
     my @exportarray;
     foreach my $column (@UC_Columns) {
         push(@exportarray,$self->value($column.'0'));
@@ -1736,9 +1849,9 @@ sub othersheets {
                                       $self->{'cdom'}, $self->{'cnum'});
     my ($tmp) = keys(%results);
     if ($tmp =~ /^(con_lost|error|no_such_host)/i ) {
-        @alternatives = ('Default');
+        @alternatives = (&mt('Default'));
     } else {
-        @alternatives = ('Default', sort (keys(%results)));
+        @alternatives = (&mt('Default'), sort (keys(%results)));
     }
     return @alternatives; 
 }