afuna: Cat under a blanket. Text: "Cats are just little people with Fur and Fangs" (Default)
afuna ([personal profile] afuna) wrote in [site community profile] changelog2010-02-16 03:27 pm

[dw-free] move /translate to /admin/translate

[commit: http://hg.dwscoalition.org/dw-free/rev/8428f0b6ae2d]

http://bugs.dwscoalition.org/show_bug.cgi?id=2323

Move all pages under /translate to /admin/translate.

Patch by [staff profile] denise.

Files modified:
  • cgi-bin/redirect.dat
  • htdocs/admin/index.bml
  • htdocs/admin/index.bml.text
  • htdocs/admin/translate/diff.bml
  • htdocs/admin/translate/edit.bml
  • htdocs/admin/translate/editpage.bml
  • htdocs/admin/translate/help-severity.bml
  • htdocs/admin/translate/index.bml
  • htdocs/admin/translate/index.bml.text
  • htdocs/admin/translate/search.bml
  • htdocs/admin/translate/searchform.bml
  • htdocs/admin/translate/teams.bml
  • htdocs/admin/translate/teams.bml.text
  • htdocs/admin/translate/welcome.bml
  • htdocs/translate/diff.bml
  • htdocs/translate/edit.bml
  • htdocs/translate/editpage.bml
  • htdocs/translate/help-severity.bml
  • htdocs/translate/index.bml
  • htdocs/translate/index.bml.text
  • htdocs/translate/search.bml
  • htdocs/translate/searchform.bml
  • htdocs/translate/teams.bml
  • htdocs/translate/teams.bml.text
  • htdocs/translate/welcome.bml
--------------------------------------------------------------------------------
diff -r 9323f181bcb6 -r 8428f0b6ae2d cgi-bin/redirect.dat
--- a/cgi-bin/redirect.dat	Tue Feb 16 15:09:47 2010 +0000
+++ b/cgi-bin/redirect.dat	Tue Feb 16 15:26:10 2010 +0000
@@ -45,3 +45,13 @@
 /mobile/friends.bml                 /mobile/read
 /misc/import                        /tools/importer
 /misc/import.bml                    /tools/importer
+/translate                          /admin/translate
+/translate/                         /admin/translate
+/translate/diff.bml                 /admin/translate/diff
+/translate/edit.bml                 /admin/translate/edit
+/translate/editpage.bml             /admin/translate/editpage
+/translate/help-severity.bml        /admin/translate/help-severity
+/translate/search.bml               /admin/translate/search
+/translate/searchform.bml           /admin/translate/searchform
+/translate/teams.bml                /admin/translate/teams
+/translate/welcome.bml              /admin/translate/welcome
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/index.bml
--- a/htdocs/admin/index.bml	Tue Feb 16 15:09:47 2010 +0000
+++ b/htdocs/admin/index.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -100,6 +100,8 @@ body<=
             '<?_ml .admin.sysban.link _ml?>', '<?_ml .admin.sysban.text _ml?>', [ 'sysban' ] ],
         [ 'theschwartz',
             '<?_ml .admin.theschwartz.link _ml?>', '<?_ml .admin.theschwartz.text _ml?>', [ 'siteadmin:theschwartz' ] ],
+        [ 'translate/',
+            '<?_ml .admin.translate.link _ml?>', '<?_ml .admin.translate.text _ml?>' ],
         [ 'userlog',
             '<?_ml .admin.userlog.link _ml?>', '<?_ml .admin.userlog.text _ml?>', [ 'canview:userlog', 'canview:*' ] ],
     );
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/index.bml.text
--- a/htdocs/admin/index.bml.text	Tue Feb 16 15:09:47 2010 +0000
+++ b/htdocs/admin/index.bml.text	Tue Feb 16 15:26:10 2010 +0000
@@ -80,6 +80,9 @@
 .admin.theschwartz.link=TheSchwartz Queue/Error Viewer
 .admin.theschwartz.text=View the status of jobs in the TheSchwartz queue.
 
+.admin.translate.link=Translation & Site Copy
+.admin.translate.text=View and edit the site copy and translations.
+
 .admin.userlog.link=Userlog Viewer
 .admin.userlog.text=Shows you a user's logged actions.
 
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/diff.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/diff.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,156 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<style type="text/css">
+del {
+    text-decoration: none;
+    color: #ff0000;
+    background-color: #ffd0d0;
+}
+ins {
+    text-decoration: none;
+    color: #002000;
+    background-color: #20ff20;
+}
+</style>
+</head>
+<body>
+<?_code
+{
+    use strict;
+    use vars qw(%GET);
+    use File::Temp qw/tempfile/;
+    
+    BML::set_content_type("text/html; charset=utf-8");
+    
+    my $lang = $GET{'lang'};
+    my $l = LJ::Lang::get_lang($lang);
+    return "<b>Invalid language</b>" unless $l;
+
+    return "<b>Invalid item</b>" unless $GET{'it'} =~ /^(\d+):(\d+)$/;
+    my ($dmid, $itid) = ($1, $2);
+    
+    my @lnids = $l->{'lnid'};
+    {
+        my $il = $l;
+        while ($il && $il->{'parentlnid'}) {
+            push @lnids, $il->{'parentlnid'};
+            $il = LJ::Lang::get_lang_id($il->{'parentlnid'});
+        }
+    }
+    my $lnids = join(",", @lnids);
+
+    my $dbr = LJ::get_db_reader();
+    my ($sth, $ret);
+
+    my $sth = $dbr->prepare("select * from ml_text where dmid=$dmid and itid=$itid and lnid in ($lnids) ORDER BY txtid");
+    $sth->execute;
+    my @tlist;
+    while (my $t = $sth->fetchrow_hashref) { 
+        next if @tlist && $t->{'text'} eq $tlist[-1]->{'text'};
+        push @tlist, $t; 
+    }
+
+    my $changes = scalar @tlist - 1;
+    return "<b>No changes</b>" unless $changes;
+
+    my $view_change = $GET{'change'} || $changes;
+    return "bogus change" if $view_change < 1 || $view_change > $changes;
+    for (1..$changes) {
+        if ($_ eq $view_change) {
+            $ret .= "<b>[Change $_]</b>\n";
+        } else {
+            $ret .= "<a href='diff?lang=$lang&it=$GET{'it'}&change=$_'>[Change $_]</a>\n";
+        }
+    }
+    $ret .= "<hr>";
+    my $was = $tlist[$view_change-1]->{'text'};
+    my $then = $tlist[$view_change]->{'text'};
+
+    my ($was_alt, $then_alt) = ($was, $then);
+    foreach (\$was_alt, \$then_alt) {
+        $$_ =~ s/\n/*NEWLINE*/g;
+        $$_ =~ s/\s+/\1\n/g;
+        $$_ .= "\n";
+    }
+
+    my ($was_file, $then_file, $fh);
+    my $tries = 0;
+
+    ($fh, $was_file) = tempfile();
+    print $fh $was_alt; close $fh;
+    ($fh, $then_file) = tempfile();
+    print $fh $then_alt; close $fh;
+
+    my @words = split(/\n/, $was_alt);
+    my $diff = `diff -u $was_file $then_file`;
+
+    my $pos = 0;
+    my $mode;
+    my $setmode = sub {
+        my $newmode = shift;
+        return " " if $newmode eq $mode;
+        my $ret;
+        $ret .= "</$mode>" if $mode;
+        $ret .= " ";
+        $ret .= "<$newmode>" if $newmode;
+        $mode = $newmode;
+        return $ret;
+    };
+
+    foreach my $dl (split(/\n/, $diff)) {
+        next if $dl =~ /^(\+\+\+|\-\-\-)/;
+        if ($dl =~ /^\@\@ \-(\d+),(\d+)/) {
+            my $newpos = $1;
+            $ret .= $setmode->("");
+            for (my $i=$pos+1; $i<$newpos; $i++) {
+                my $word = LJ::ehtml($words[$i-1]);
+                $word =~ s/\*NEWLINE\*/<br>\n/g;
+                $ret .= "$word ";
+                $pos++;
+            }
+            next;
+        }
+        if ($dl =~ /^ /) {
+            $pos++;
+            my $word = LJ::ehtml($words[$pos-1]);
+            $word =~ s/\*NEWLINE\*/<br>\n/g;
+            $ret .= $setmode->("") . $word;
+        }
+        if ($dl =~ /^\-/) {
+            $pos++;
+            my $word = LJ::ehtml($words[$pos-1]);
+            $word =~ s/\*NEWLINE\*/<br>\n/g;  
+            $ret .= $setmode->("del") . $word;
+        }
+        if ($dl =~ /^\+(.*)/) {
+            my $word = LJ::ehtml($1);
+            $word =~ s/\*NEWLINE\*/<br>\n/g;
+            $ret .= $setmode->("ins") . $word;
+        }
+    }
+
+    $ret .= $setmode->("");
+    while ($pos < @words) {
+        my $word = LJ::ehtml($words[$pos]);
+        $word =~ s/\*NEWLINE\*/<br>\n/g;
+        $ret .= "$word ";
+        $pos++;
+    }
+
+    $was = LJ::eall($was);
+    $was =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
+    $then = LJ::eall($then);
+    $then =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
+    
+    $ret .= "<p><table width='100%' border='1'><tr valign='top'><td width='50%'><b>Before:</b><br>$was</td>";
+    $ret .= "<td width='50%'><b>After:</b><br>$then</td></tr></table>";
+
+    unlink($was_file, $then_file);
+
+    return $ret;
+
+}
+_code?>
+</body>
+</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/edit.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/edit.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,14 @@
+<html>
+<head>
+ <title>Language Editor</title>
+</head>
+
+<frameset cols="200,*">
+  <frameset rows="230,*">
+    <frame name="search" src="searchform?lang=<?_code return $FORM{'lang'}; _code?>">
+    <frame name="res" src="search?lang=<?_code return $FORM{'lang'}; _code?>&amp;stale=1%2B&amp;search=sev">
+  </frameset>
+  <frame name="main" src="welcome">
+</frameset>
+
+</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/editpage.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/editpage.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,363 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<?_code
+{
+    LJ::Hooks::run_hook('trans_editpage_bml_postsave_begin');
+    return LJ::res_includes();
+}
+ _code?>
+</head>
+<body>
+<?_code
+ use strict;
+ use vars qw(%FORM);
+
+ BML::set_content_type("text/html; charset=utf-8");
+
+ my $lang = $FORM{'lang'};
+ my $l = LJ::Lang::get_lang($lang);
+ return "<b>Invalid language</b>" unless $l;
+ my $lp = $l->{'parentlnid'} ? LJ::Lang::get_lang_id($l->{'parentlnid'}) : undef;
+
+ my $dbr = LJ::get_db_reader();
+ my $dbh;
+ my ($sth, $ret);
+
+ my $remote = LJ::get_remote();
+ my $can_edit   = $remote && $remote->has_priv( "translate", $l->{'lncode'} );
+ my $can_delete = $remote && $remote->has_priv( "translate", "[itemdelete]" );
+ my $can_rename = $remote && $remote->has_priv( "translate", "[itemrename]" );
+
+ # Extra checkboxes for default language and root language (DW: en_DW and en)
+ my $extra_checkboxes = $l->{'lncode'} eq $LJ::DEFAULT_LANG || !defined $lp;
+
+ my $mode = {
+     '' => 'view',
+     'save' => 'save',
+ }->{$FORM{'mode'}};
+ return "bogus mode" unless $mode;
+
+ my $MAX_EDIT = 100;
+
+ if ($mode eq "view")
+ {
+     my @load;
+     foreach (split /,/, $FORM{'items'})
+     {
+         next unless /^(\d+):(\d+)$/;
+         last if @load >= $MAX_EDIT;
+         push @load, { 'dmid' => $1, 'itid'=> $2 };
+     }
+
+     return "Nothing to show." unless @load;
+
+     $ret .= "<form method='post' action='editpage'>";
+     $ret .= LJ::html_hidden('lang', $lang,
+                             'mode', 'save');
+
+     # load item info
+     my %ml_items;
+     my $itwhere = join(" OR ", map { "(dmid=$_->{'dmid'} AND itid=$_->{'itid'})" } @load);
+     $sth = $dbr->prepare("SELECT dmid, itid, itcode, proofed, updated, notes FROM ml_items WHERE $itwhere");
+     $sth->execute;
+     while (my ($dmid, $itid, $itcode, $proofed, $updated, $notes) = $sth->fetchrow_array) {
+         $ml_items{"$dmid-$itid"} = { 'itcode' => $itcode, 'proofed' => $proofed, 'updated' => $updated, 'notes' => $notes };
+     }
+
+     # getting latest mappings for this lang and parent
+     my %ml_text;
+     my %ml_latest;
+     $sth = $dbr->prepare("SELECT lnid, dmid, itid, txtid, chgtime, staleness FROM ml_latest ".
+                          "WHERE ($itwhere) AND lnid IN ($l->{'lnid'}, $l->{'parentlnid'})");
+     $sth->execute;
+     return $dbr->errstr if $dbr->err;
+     while ($_ = $sth->fetchrow_hashref) {
+         $ml_latest{"$_->{'dmid'}-$_->{'itid'}"}->{$_->{'lnid'}} = $_;
+         $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = undef;  # mark to load later
+     }
+
+     # load text
+     $sth = $dbr->prepare("SELECT dmid, txtid, lnid, itid, text FROM ml_text ".
+                          "WHERE " . join(" OR ",
+                                          map { "(dmid=$_->[0] AND txtid=$_->[1])" }
+                                          map { [ split(/-/, $_) ] } keys %ml_text));
+     $sth->execute;
+     while ($_ = $sth->fetchrow_hashref) {
+         $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = $_;
+     }
+
+     if ($can_delete) {
+         $ret .= "<p style='font-size:9pt'><b>To delete an item:</b> edit text to be \"XXDELXX\"</p>";
+     }
+
+     # show all editing items
+     my $ict = 0;
+     foreach my $i (@load)
+     {
+         my ($dmid, $itid) = ($i->{'dmid'}, $i->{'itid'});
+         my $ituq = "$dmid-$itid";
+         my $it = $ml_items{$ituq};
+         my $lat = $ml_latest{$ituq}->{$l->{'lnid'}};
+         next unless $it and $lat;
+         $ict++;
+
+         my $plat;
+         if ($lp && defined $ml_latest{$ituq}->{$lp->{'lnid'}}) {
+             $plat = $ml_latest{$ituq}->{$lp->{'lnid'}};
+         }
+
+         $ret .= LJ::html_hidden("dom_$ict", $dmid,
+                                 "itid_$ict", $itid,
+                                 "oldtxtid_$ict", $lat->{'txtid'},
+                                 "oldptxtid_$ict", $plat ? $plat->{'txtid'} : 0,
+                                 );
+
+         # top bar
+         $ret .= "<table bgcolor='#c0c0c0' width='100%'><tr><td><b>Code:</b> ";
+         if ($dmid != 1) {
+             my $d = LJ::Lang::get_dom_id($dmid);
+             $ret .= "[$d->{'uniq'}] ";
+         }
+
+         my $difflink;
+         if ($lat->{'staleness'}) {
+             $difflink = "($plat->{'chgtime'}, <a target='_new' href='diff?it=$i->{'dmid'}:$i->{'itid'}&lang=$lp->{'lncode'}'>diff</a>)";
+         }
+
+         $ret .= "$it->{'itcode'} $difflink</td>";
+         $ret .= "<td align='right'><b><a target='_new' href='help-severity'>Sev</a>:</b> $lat->{'staleness'}</td>";
+         $ret .= "</tr></table>";
+
+         $ret .= "<dl>";
+         if ($it->{'notes'}) {
+             my $notes = $it->{'notes'};
+             $notes =~ s!\n!<br />!g;
+             $ret .= "<dt><b>Notes:</b></dt><dd>$notes</dd>";
+         }
+
+         my $show_edit = 0;
+         my $use_textarea = 0;
+
+         if ($plat) {
+             $ret .= "<dt><b>$lp->{'lnname'}:</b></dt>";
+             my $t = $ml_text{"$plat->{'dmid'}-$plat->{'txtid'}"}->{'text'};
+             if ($t =~ /\n/) { $use_textarea = 1; }
+             if (length($t) > 255) { $use_textarea = 1; }
+             $t = LJ::eall($t);
+             $t =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
+             $ret .= "<dd>$t</dd>";
+         }
+
+         my $curtext = LJ::eall($ml_text{"$lat->{'dmid'}-$lat->{'txtid'}"}->{'text'});
+         if ($curtext =~ /\n/) { $use_textarea = 1; }
+         if (length($curtext) > 255) { $use_textarea = 1; }
+         if ($lat->{'staleness'} >= 3) {
+             # if wrong language, why populate it with stuff they'll just have to delete?
+             $curtext = "";
+         }
+
+         $ret .= "<dt><b>$l->{'lnname'}</b>:</b></dt><dd>";
+         my $disabled = "disabled='disabled'";
+         if ($lat->{'staleness'} >= 3) {
+             $disabled = "";
+             # when something's this stale, assume both it's being
+             # edited and that the severity is major (going from wrong
+             # language to right language is a major change, afterall)
+             $ret .= LJ::html_hidden("ed_$ict", "1",
+                                     "sev_$ict", "2",
+                                     );
+         } else {
+             my $js = "a=document.getElementById(\"newtext_$ict\"); a.disabled=!this.checked; if (this.checked) a.focus();";
+             $js .= "a=document.getElementById(\"pr_$ict\"); a.disabled=!this.checked; a=document.getElementById(\"up_$ict\"); a.disabled=!this.checked;"
+                 if $extra_checkboxes;
+             $ret .= "<input name='ed_$ict' type='checkbox' value='1' id='ed_$ict' onClick='$js' /><label for='ed_$ict'>Edit Text</label>";
+             if ($l->{'children'} && @{$l->{'children'}}) {
+                 $ret .= " Severity: ";
+                 $ret .= LJ::html_select({ 'name' => "sev_$ict", "selected" => 1 },
+                                         0 => "Typo/etc (no notify)",
+                                         1 => "Minor (notify translators)",
+                                         2 => "Major (require translation updates)");
+             }
+             $ret .= "<br />" unless $extra_checkboxes;
+         }
+
+         if ( $extra_checkboxes ) {
+             $ret .= " ";
+             $ret .= LJ::html_check( { type => 'checkbox', label => 'Proofed',
+                                       selected => $it->{proofed}, value => 1,
+                                       name => "pr_$ict", id => "pr_$ict",
+                                       disabled => $disabled eq '' ? 0 : 1 } );
+             $ret .= " ";
+             $ret .= LJ::html_check( { type => 'checkbox', label => 'Updated',
+                                       selected => $it->{updated}, value => 1,
+                                       name => "up_$ict", id => "up_$ict",
+                                       disabled => $disabled eq '' ? 0 : 1 } );
+             $ret .= "<br />";
+         }
+
+         if ($use_textarea) {
+             $ret .= "<textarea name='newtext_$ict' id='newtext_$ict' $disabled wrap='soft' rows='10' cols='60'>$curtext</textarea>";
+         } else {
+             $ret .= "<input name='newtext_$ict' id='newtext_$ict' $disabled size='60' value=\"$curtext\"/>";
+         }
+         $ret .= "</dd>\n";
+         $ret .= "</dl>";
+     }
+
+     if ($ict) {
+         $ret .= LJ::html_hidden("ict", $ict);
+         my $disabled = $can_edit ? "" : "disabled='disabled'";
+         $ret .= "<table width='100%' bgcolor='#e0e0e0'><tr><td align='center'><input type='submit' $disabled value='Save' /></td></tr></table>";
+     } else {
+         $ret .= "No items to show.  (since been deleted, perhaps?)";
+     }
+     $ret .= "</form>";
+
+     return $ret;
+ }
+
+ if ($mode eq "save")
+ {
+     my $num = $FORM{'ict'}+0;
+     $num = $MAX_EDIT if $num > $MAX_EDIT;
+
+     my (@errors, @info);
+     unless ($can_edit) {
+         push @errors, "You don't have access to edit text for this language.";
+         $num = 0;
+     }
+
+     unless (LJ::text_in(\%FORM)) {
+         push @errors, "You seem to have changed your browser's encoding to something other than UTF-8.  It needs to be in UTF-8.";
+         push @errors, "Nothing saved.";
+         $num = 0;
+     }
+
+     my $saved = 0;  # do any saves?
+
+     for (my $i=1; $i<=$num; $i++)
+     {
+         next unless $FORM{"ed_$i"};
+         my ($dom, $itid, $oldtxtid, $oldptxtid, $sev, $proofed, $updated) =
+             map { int($FORM{"${_}_$i"}+0) }
+                 qw(dom itid oldtxtid oldptxtid sev pr up);
+
+         my $itcode = $dbr->selectrow_array("SELECT itcode FROM ml_items WHERE dmid=$dom AND itid=$itid");
+         unless (defined $itcode) {
+             push @errors, "Bogus dmid/itid: $dom/$itid";
+             next;
+         }
+
+         $dbh ||= LJ::get_db_writer();
+         my $lat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$l->{'lnid'} AND dmid=$dom AND itid=$itid");
+         unless ($lat) {
+             push @errors, "No existing mapping for $itcode";
+             next;
+         }
+         unless ($lat->{'txtid'} == $oldtxtid) {
+             push @errors, "Another translator updated '$itcode' before you saved, so your edit has been ignored.";
+             next;
+         }
+
+         my $plat;
+         if ($lp) {
+             $plat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$lp->{'lnid'} ".
+                                             "AND dmid=$dom AND itid=$itid");
+             my $ptid = $plat ? $plat->{'txtid'} : 0;
+             unless ($ptid == $oldptxtid) {
+                 push @errors, "The source text of item '$itcode' changed while you were editing, so your edit has been ignored.";
+                 next;
+             }
+         }
+
+         # did they type anything?
+         my $text = $FORM{"newtext_$i"};
+         next unless $text =~ /\S/;
+
+         # delete
+         if ($text eq "XXDELXX") {
+             if ($can_delete) {
+                 $dbh->do("DELETE FROM ml_latest WHERE dmid=$dom AND itid=$itid");
+                 push @info, "Deleted: '$itcode'";
+             } else {
+                 push @errors, "You don't have access to delete items.";
+             }
+             next;
+         }
+
+         # did anything even change, though?
+         my $oldtext = $dbr->selectrow_array("SELECT text FROM ml_text WHERE dmid=$dom AND txtid=$lat->{'txtid'}");
+         if ($oldtext eq $text && $lat->{'staleness'} == 2) {
+             push @errors, "Severity of source language change requires change in text for item '$itcode'";
+             next;
+         }
+
+         # keep old txtid if text didn't change.
+         my $opts = {};
+         if ($oldtext eq $text) {
+             $opts->{'txtid'} = $lat->{'txtid'};
+             $text = undef;
+             $sev = 0;
+         }
+
+         # if setting text for first time, push down to children langs
+         if ($lat->{'staleness'} == 4) {
+             $opts->{'childrenlatest'} = 1;
+         }
+
+         # severity of change:
+         $opts->{'changeseverity'} = $sev;
+
+         # set userid of writer
+         $opts->{'userid'} = $remote->{'userid'};
+
+         my ($res, $msg) = LJ::Lang::web_set_text($dom, $l->{'lncode'}, $itcode, $text, $opts);
+         if ($res) {
+             push @info, "OK: $itcode";
+             $saved = 1;
+
+             if ( $extra_checkboxes ) {
+                 # Not gonna bother to refactor to LJ::Lang as the whole
+                 # translation system will get thrown away and redone later.
+                 # FIXME: make sure my words don't come back to haunt me.
+                 $dbh->do( "UPDATE ml_items SET proofed = ?, updated = ? " .
+                           "WHERE dmid = ? AND itid = ?", undef, $proofed ? 1 : 0,
+                           $updated ? 1 : 0, $dom, $itid );
+
+                 if ( $dbh->err ) {
+                     push @errors, $dbh->errstr;
+                 } else {
+                     push @info, "OK: $itcode (flags)";
+                 }
+             }
+         } else {
+             push @errors, $msg;
+         }
+
+         push @info, LJ::Hooks::run_hook('trans_editpage_bml_postsave', $opts)
+             if LJ::Hooks::are_hooks('trans_editpage_bml_postsave');
+     }
+
+     $dbh ||= LJ::get_db_writer();
+     $dbh->do("UPDATE ml_langs SET lastupdate=NOW() WHERE lnid=$l->{'lnid'}") if $saved;
+
+     if (@errors) {
+         $ret .= "<b>ERRORS:</b><ul>";
+         foreach (@errors) { $ret .= "<li>$_</li>"; }
+         $ret .= "</ul>";
+     }
+     if (@info) {
+         $ret .= "<b>Results:</b><ul>";
+         foreach (@info) { $ret .= "<li>$_</li>"; }
+         $ret .= "</ul>";
+     }
+     if (! @errors && ! @info) {
+         $ret .= "<i>No errors & nothing saved.</i>";
+     }
+     return $ret;
+ }
+
+_code?>
+</body>
+</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/help-severity.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/help-severity.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,12 @@
+<h1>Description of severity levels:</h1>
+
+<table cellpadding='3'>
+<tr valign='top'><td><b>0</b></td><td>Translate is up-to-date</td></tr>
+<tr valign='top'><td><b>1</b></td><td>Parent language has changed a little.  Your translation might need updating.</td></tr>
+<tr valign='top'><td><b>2</b></td><td>Parent language has changed.  Your translation probably needs updating.</td></tr>
+<tr valign='top'><td><b>3</b></td><td>New text was added in parent language which you haven't yet translated.</td></tr>
+<tr valign='top'><td><b>4</b></td><td>Item code in use but no text exists yet for any language.</td></tr>
+</table>
+
+<h2>Searching</h2>
+When searching, you can search for a certain severity level (0, 1, 2, 3, 4) or search for everything at or above a certain severity level (0+, 1+, 2+, 3+).
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/index.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/index.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,78 @@
+<?page
+title=><?_ml .title _ml?>
+body<=
+
+<?_code
+{
+    use strict;
+    
+    my $dbr = LJ::get_db_reader();
+    my $sth;
+
+    LJ::set_active_crumb('translate');
+    
+    $sth = $dbr->prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs");
+    $sth->execute;
+    my %lang;
+    $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref;
+ 
+    $sth = $dbr->prepare("SELECT lnid, staleness > 1, COUNT(*) FROM ml_latest GROUP by 1, 2");
+    $sth->execute;
+    while (my ($lnid, $stale, $ct) = $sth->fetchrow_array) {
+        next unless exists $lang{$lnid};
+        $lang{$lnid}->{'_total'} += $ct;
+        $lang{$lnid}->{'_good'} += (1-$stale) * $ct;
+        $lang{$lnid}->{'percent'} = 100 * $lang{$lnid}->{'_good'} / ($lang{$lnid}->{'_total'}||1);
+    }
+
+    my $sortcol = exists $lang{'1'}->{$FORM{'s'}} ? $FORM{'s'} : "lnname";
+    my @cols = (['lncode', $ML{'.table.code'}],
+                ['lnname', $ML{'.table.langname'}, sub {
+                    my $r = shift;
+                    "<td><a href='edit?lang=$r->{'lncode'}'>$r->{'lnname'}</a></td>";
+                }],
+                ['percent', $ML{'.table.done'}, sub {
+                    my $r = shift;
+                    "<td align='right'><b>" .
+                    sprintf("%.02f%%", $r->{'percent'}) . "</b><br />" .
+                    "<font size='-1'>$r->{'_good'}/$r->{'_total'}</font>" .
+                    "</td>";
+                },
+                    sub {
+                        $b->{'percent'} <=> $a->{'percent'} || $b->{'_total'} <=> $a->{'_total'}
+                }],
+                ['lastupdate', $ML{'.table.lastupdate'}, undef, sub {
+                    $b->{'lastupdate'} cmp $a->{'lastupdate'}
+                }]);
+    my $ret;
+    my $sorter = sub { $a->{$sortcol} cmp $b->{$sortcol} };
+
+    $ret .= BML::ml('.text', {'aopts' => "href='$LJ::SITEROOT/admin/translate/teams'"});
+
+    $ret .= "<p><table border='1' cellspacing='1' cellpadding='3'><tr>";
+    foreach (@cols) {
+        if ($sortcol eq $_->[0]) {
+            $ret .= "<td><b>$_->[1]</b></td>";
+        } else {
+            $ret .= "<td><b><a href=\"./?s=$_->[0]\">$_->[1]</a></b></td>";
+        }
+        if ($_->[0] eq $sortcol && $_->[3]) { $sorter = $_->[3]; }
+    }
+    $ret .= "</tr>\n";
+
+    foreach my $r (sort $sorter values %lang) {
+        $ret .= "<tr>";
+        foreach (@cols) {
+            $ret .= $_->[2] ? $_->[2]->($r) : "<td>$r->{$_->[0]}</td>";
+        }
+        $ret .= "</tr>\n";
+    }
+
+    $ret .= "</table>\n";
+    
+    return $ret;
+}
+_code?>
+
+<=body
+page?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/index.bml.text
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/index.bml.text	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,13 @@
+;; -*- coding: utf-8 -*-
+.table.code=Code
+
+.table.done=% Done
+
+.table.langname=Language Name
+
+.table.lastupdate=Last Update
+
+.text=The following table lists the progress by each of the different <a [[aopts]]>translation teams</a>.
+
+.title=Translation Area
+
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/search.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/search.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,100 @@
+<?_code
+{
+    my $lang = $FORM{'lang'};
+    my $l = LJ::Lang::get_lang($lang);
+    return "<b>Invalid language</b>" unless $l;
+
+    my $dbr = LJ::get_db_reader();
+    my $sth;
+
+    my $sql;
+
+    # all queries use the visible flag
+    my $vis_flag = '';
+    $vis_flag = 'AND i.visible = 1' unless $LJ::IS_DEV_SERVER;
+
+    if ($FORM{'search'} eq 'sev')
+    {
+        my $what = ">= 1";
+        if ($FORM{'stale'} =~ /^(\d+)(\+?)$/) {
+            $what = ($2 ? ">=" : "=") . $1;
+        }
+        $sql = qq(
+            SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
+            WHERE l.lnid=$l->{'lnid'} AND l.staleness $what AND l.dmid=i.dmid AND l.itid=i.itid $vis_flag
+            ORDER BY i.dmid, i.itcode
+        );
+    }
+
+    if ($FORM{'search'} eq 'txt')
+    {
+        my $remote = LJ::get_remote();
+        return "This search type is restricted to $l->{'lnname'} translators." unless
+            $remote && ( $remote->has_priv( "translate", $l->{'lncode'} ) ||
+                         $remote->has_priv( "faqedit", "*" ) ); # FAQ admins can search too
+
+        my $qtext = $dbr->quote($FORM{'searchtext'});
+        my $dmid = $FORM{'searchdomain'}+0;
+        my $dmidwhere = $dmid ? "AND i.dmid=$dmid" : "";
+        if ($FORM{'searchwhat'} eq "code") {
+            $sql = qq{
+                SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
+                WHERE l.lnid=$l->{'lnid'} AND l.dmid=i.dmid AND i.itid=l.itid $vis_flag
+                $dmidwhere AND LOCATE($qtext, i.itcode)
+            };
+        } else {
+            my $lnid = $l->{'lnid'};
+            if ($FORM{'searchwhat'} eq "parent") { $lnid = $l->{'parentlnid'}; }
+            $sql = qq{
+                SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l, ml_text t
+                WHERE l.lnid=$lnid AND l.dmid=i.dmid AND i.itid=l.itid
+                $dmidwhere AND t.dmid=l.dmid AND t.txtid=l.txtid AND LOCATE($qtext, t.text) $vis_flag
+                ORDER BY i.itcode
+            };
+        }
+    }
+
+    if ($FORM{'search'} eq 'flg') {
+        return "This type of search isn't available for this language."
+            unless $l->{'lncode'} eq $LJ::DEFAULT_LANG || !$l->{'parentlnid'};
+
+        my $whereflags = join ' AND ',
+            map { $FORM{"searchflag$_"} eq 'yes' ? "$_ = 1" : "$_ = 0" }
+                grep { $FORM{"searchflag$_"} ne 'whatev' } qw(proofed updated);
+        $whereflags = "AND $whereflags"
+            if $whereflags ne '';
+        $sql = qq(
+            SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
+            WHERE l.lnid=$l->{lnid} AND l.dmid=i.dmid AND l.itid=i.itid $whereflags $vis_flag
+            ORDER BY i.dmid, i.itcode
+        );
+    }
+
+    return "Bogus or unimplemented query type." unless $sql;
+
+    my $ret;
+    $sth = $dbr->prepare($sql);
+    $sth->execute;
+    my $page = 0;
+    my @page = ();
+    my $addlink = sub {
+        return unless @page;
+        $page++;
+        my $link = "editpage?lang=$lang&amp;items=" . LJ::eurl(join(",",map{"$_->[0]:$_->[1]"}@page));
+        $ret .= "<b><a target='main' href='$link'>Page $page</a></b><br /><span style='font-size:8pt'>\n";
+        $ret .= "$page[0]->[2]<br />\n";
+        $ret .= "$page[-1]->[2]<br /></span>\n";
+        @page = ();
+    };
+    while (my ($dmid, $itid, $itcode) = $sth->fetchrow_array) {
+        push @page, [ $dmid, $itid, $itcode ];
+        $addlink->() if @page >= 10;
+    }
+    $addlink->();
+
+    if ($page == 0) { $ret .= "<i>(No matches)</i>"; }
+
+    return $ret;
+
+}
+_code?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/searchform.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/searchform.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,80 @@
+<html>
+<head><title>Search Form</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body marginwidth='0' marginheight='0'>
+
+<form target='res' action='search' method='get'>
+<input type='hidden' name='lang' value='<?_code $FORM{'lang'} _code?>'>
+<input type='hidden' name='search' value='sev'>
+
+[<a href="./" target='_top'>&lt;-- Back</a>]
+<?_code
+ my $lang = $FORM{'lang'};
+ my $l = LJ::Lang::get_lang($lang);
+ BML::finish() unless $l;
+ return "<b>" . ($l ? $l->{'lnname'} : "Invalid language") . "</b>";
+_code?>
+
+<p>By Severity: (<a href='help-severity' target='main'>help</a>)<br /><select name='stale'>
+<option value="0">0</option>
+<option value="0+">0+</option>
+<option value="1">1</option>
+<option value="1+" selected='selected'>1+</option>
+<option value="2">2</option>
+<option value="2+">2+</option>
+<option value="3">3</option>
+<option value="3+">3+</option>
+<option value="4">4</option>
+</select><input type='submit' value='Search'/>
+</p>
+</form>
+
+<form target='res' action='search' method='get'>
+<input type='hidden' name='lang' value='<?_code $FORM{'lang'} _code?>'>
+<input type='hidden' name='search' value='txt'>
+
+<p>Search
+<?_code
+ my $ret;
+ my $l = LJ::Lang::get_lang($FORM{'lang'});
+ my $pl = LJ::Lang::get_lang_id($l->{'parentlnid'});
+ my @opt = ("src" => $l->{'lnname'});
+ if ($pl) { push @opt, "parent", $pl->{'lnname'} };
+ push @opt, "code", "Item Code";
+ $ret .= LJ::html_select({ 'name' => 'searchwhat' },
+                         @opt);
+ $ret .= "<br />Area: ";
+ $ret .= LJ::html_select({ 'name' => 'searchdomain' },
+                         0, "(all)",
+                         map { $_->{'dmid'}, $_->{'uniq'} }
+                         sort { $a->{'dmid'} <=> $b->{'dmid'} } LJ::Lang::get_domains());
+ return $ret;
+_code?>
+    <br />Text: <input name='searchtext' size='15'><input type='submit' value='Search'>
+</p>
+</form>
+
+<?_code
+ my $l = LJ::Lang::get_lang($FORM{'lang'});
+ return '' unless $l->{'lncode'} eq $LJ::DEFAULT_LANG || !$l->{'parentlnid'};
+
+ my $ret = <<HTML;
+<form target='res' action='search' method='get'>
+<input type='hidden' name='lang' value='$l->{lncode}'>
+<input type='hidden' name='search' value='flg'>
+<p><table><tr><td>Prf:</td>
+<td><input type='radio' name='searchflagproofed' value='whatev'>Both</td>
+<td><input type='radio' name='searchflagproofed' value='yes'>Yes</td>
+<td><input type='radio' name='searchflagproofed' value='no'>No</td></tr>
+<tr><td>Upd:</td>
+<td><input type='radio' name='searchflagupdated' value='whatev'>Both</td>
+<td><input type='radio' name='searchflagupdated' value='yes'>Yes</td>
+<td><input type='radio' name='searchflagupdated' value='no'>No</td></tr></table>
+<input type='submit' value='Search'></p></form>
+HTML
+ return $ret;
+_code?>
+
+</body>
+</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/teams.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/teams.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,63 @@
+<?page
+title=><?_ml .title _ml?>
+body<=
+<?_code
+{
+    use strict;
+
+    my $dbr = LJ::get_db_reader();
+    my ($ret, $sth);
+
+    LJ::set_active_crumb('translateteams');
+
+    $ret .= "<?h1 $ML{'.teams.header'} h1?>";
+    $ret .= "<?p $ML{'.teams.text'} p?>";
+
+    # get langs
+    $sth = $dbr->prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs");
+    $sth->execute;
+    my %lang;
+    $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref;
+
+    # get each lang's community
+    $sth = $dbr->prepare("SELECT l.lnid, t.text ".
+                        "FROM ml_latest l, ml_items i, ml_text t ".
+                        "WHERE l.dmid=1 AND t.dmid=1 AND i.dmid=1 AND i.itcode='thislang.community' ".
+                        "AND l.itid=i.itid AND t.txtid=l.txtid AND t.lnid=l.lnid");
+    $sth->execute;
+    while ($_ = $sth->fetchrow_hashref) {
+        next unless exists $lang{$_->{'lnid'}};
+        $lang{$_->{'lnid'}}->{'community'} = $_->{'text'};
+    }
+
+    # get people with privs
+    $sth = $dbr->prepare("SELECT pm.arg, u.user FROM useridmap u, priv_list pl, priv_map pm ".
+                        "WHERE pm.userid=u.userid AND pm.prlid=pl.prlid AND pl.privcode='translate'");
+    $sth->execute;
+    my %team;
+    while (my ($arg, $user) = $sth->fetchrow_array) {
+        push @{$team{$arg}}, $user;
+    }
+
+    $ret .= "<p><table cellpadding='5' border='1'>";
+    $ret .= "<tr><th>$ML{'.table.language'}</th><th>$ML{'.table.community'}</th><th>$ML{'.table.users'}</th></tr>";
+
+    foreach my $l (sort { $a->{'lnname'} cmp $b->{'lnname'} } values %lang) {
+        $ret .= "<tr valign='top' align='left'><td><b>$l->{'lnname'}</b></td>";
+        $ret .= "<td>";
+        $ret .= "<?ljcomm $l->{'community'} ljcomm?>" if $l->{'community'};
+        $ret .= "</td><td>";
+        if ($team{$l->{'lncode'}}) {
+            $ret .= join(", ", map { LJ::ljuser($_) }
+            sort @{$team{$l->{'lncode'}}});
+        }
+        $ret .= "</td></tr>\n";
+    }
+
+    $ret .= "</table>";
+    return $ret;
+}
+_code?>
+
+<=body
+page?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/teams.bml.text
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/teams.bml.text	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,13 @@
+;; -*- coding: utf-8 -*-
+.table.community=Community
+
+.table.language=Language
+
+.table.users=Users With Privs
+
+.teams.header=Teams
+
+.teams.text=Translation is being done by the following teams:
+
+.title=Translation Teams
+
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/admin/translate/welcome.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/translate/welcome.bml	Tue Feb 16 15:26:10 2010 +0000
@@ -0,0 +1,7 @@
+Welcome to the translation area.
+
+<p>In the top-left frame you search for phrases to translate.
+
+<p>The lower-left frame shows your search result links, paginated.
+
+<p>This large frame is the work area, in which text is edited.
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/diff.bml
--- a/htdocs/translate/diff.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<style type="text/css">
-del {
-    text-decoration: none;
-    color: #ff0000;
-    background-color: #ffd0d0;
-}
-ins {
-    text-decoration: none;
-    color: #002000;
-    background-color: #20ff20;
-}
-</style>
-</head>
-<body>
-<?_code
-{
-    use strict;
-    use vars qw(%GET);
-    use File::Temp qw/tempfile/;
-    
-    BML::set_content_type("text/html; charset=utf-8");
-    
-    my $lang = $GET{'lang'};
-    my $l = LJ::Lang::get_lang($lang);
-    return "<b>Invalid language</b>" unless $l;
-
-    return "<b>Invalid item</b>" unless $GET{'it'} =~ /^(\d+):(\d+)$/;
-    my ($dmid, $itid) = ($1, $2);
-    
-    my @lnids = $l->{'lnid'};
-    {
-        my $il = $l;
-        while ($il && $il->{'parentlnid'}) {
-            push @lnids, $il->{'parentlnid'};
-            $il = LJ::Lang::get_lang_id($il->{'parentlnid'});
-        }
-    }
-    my $lnids = join(",", @lnids);
-
-    my $dbr = LJ::get_db_reader();
-    my ($sth, $ret);
-
-    my $sth = $dbr->prepare("select * from ml_text where dmid=$dmid and itid=$itid and lnid in ($lnids) ORDER BY txtid");
-    $sth->execute;
-    my @tlist;
-    while (my $t = $sth->fetchrow_hashref) { 
-        next if @tlist && $t->{'text'} eq $tlist[-1]->{'text'};
-        push @tlist, $t; 
-    }
-
-    my $changes = scalar @tlist - 1;
-    return "<b>No changes</b>" unless $changes;
-
-    my $view_change = $GET{'change'} || $changes;
-    return "bogus change" if $view_change < 1 || $view_change > $changes;
-    for (1..$changes) {
-        if ($_ eq $view_change) {
-            $ret .= "<b>[Change $_]</b>\n";
-        } else {
-            $ret .= "<a href='diff?lang=$lang&it=$GET{'it'}&change=$_'>[Change $_]</a>\n";
-        }
-    }
-    $ret .= "<hr>";
-    my $was = $tlist[$view_change-1]->{'text'};
-    my $then = $tlist[$view_change]->{'text'};
-
-    my ($was_alt, $then_alt) = ($was, $then);
-    foreach (\$was_alt, \$then_alt) {
-        $$_ =~ s/\n/*NEWLINE*/g;
-        $$_ =~ s/\s+/\1\n/g;
-        $$_ .= "\n";
-    }
-
-    my ($was_file, $then_file, $fh);
-    my $tries = 0;
-
-    ($fh, $was_file) = tempfile();
-    print $fh $was_alt; close $fh;
-    ($fh, $then_file) = tempfile();
-    print $fh $then_alt; close $fh;
-
-    my @words = split(/\n/, $was_alt);
-    my $diff = `diff -u $was_file $then_file`;
-
-    my $pos = 0;
-    my $mode;
-    my $setmode = sub {
-        my $newmode = shift;
-        return " " if $newmode eq $mode;
-        my $ret;
-        $ret .= "</$mode>" if $mode;
-        $ret .= " ";
-        $ret .= "<$newmode>" if $newmode;
-        $mode = $newmode;
-        return $ret;
-    };
-
-    foreach my $dl (split(/\n/, $diff)) {
-        next if $dl =~ /^(\+\+\+|\-\-\-)/;
-        if ($dl =~ /^\@\@ \-(\d+),(\d+)/) {
-            my $newpos = $1;
-            $ret .= $setmode->("");
-            for (my $i=$pos+1; $i<$newpos; $i++) {
-                my $word = LJ::ehtml($words[$i-1]);
-                $word =~ s/\*NEWLINE\*/<br>\n/g;
-                $ret .= "$word ";
-                $pos++;
-            }
-            next;
-        }
-        if ($dl =~ /^ /) {
-            $pos++;
-            my $word = LJ::ehtml($words[$pos-1]);
-            $word =~ s/\*NEWLINE\*/<br>\n/g;
-            $ret .= $setmode->("") . $word;
-        }
-        if ($dl =~ /^\-/) {
-            $pos++;
-            my $word = LJ::ehtml($words[$pos-1]);
-            $word =~ s/\*NEWLINE\*/<br>\n/g;  
-            $ret .= $setmode->("del") . $word;
-        }
-        if ($dl =~ /^\+(.*)/) {
-            my $word = LJ::ehtml($1);
-            $word =~ s/\*NEWLINE\*/<br>\n/g;
-            $ret .= $setmode->("ins") . $word;
-        }
-    }
-
-    $ret .= $setmode->("");
-    while ($pos < @words) {
-        my $word = LJ::ehtml($words[$pos]);
-        $word =~ s/\*NEWLINE\*/<br>\n/g;
-        $ret .= "$word ";
-        $pos++;
-    }
-
-    $was = LJ::eall($was);
-    $was =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
-    $then = LJ::eall($then);
-    $then =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
-    
-    $ret .= "<p><table width='100%' border='1'><tr valign='top'><td width='50%'><b>Before:</b><br>$was</td>";
-    $ret .= "<td width='50%'><b>After:</b><br>$then</td></tr></table>";
-
-    unlink($was_file, $then_file);
-
-    return $ret;
-
-}
-_code?>
-</body>
-</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/edit.bml
--- a/htdocs/translate/edit.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<html>
-<head>
- <title>Language Editor</title>
-</head>
-
-<frameset cols="200,*">
-  <frameset rows="230,*">
-    <frame name="search" src="searchform?lang=<?_code return $FORM{'lang'}; _code?>">
-    <frame name="res" src="search?lang=<?_code return $FORM{'lang'}; _code?>&amp;stale=1%2B&amp;search=sev">
-  </frameset>
-  <frame name="main" src="welcome">
-</frameset>
-
-</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/editpage.bml
--- a/htdocs/translate/editpage.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,363 +0,0 @@
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<?_code
-{
-    LJ::Hooks::run_hook('trans_editpage_bml_postsave_begin');
-    return LJ::res_includes();
-}
- _code?>
-</head>
-<body>
-<?_code
- use strict;
- use vars qw(%FORM);
-
- BML::set_content_type("text/html; charset=utf-8");
-
- my $lang = $FORM{'lang'};
- my $l = LJ::Lang::get_lang($lang);
- return "<b>Invalid language</b>" unless $l;
- my $lp = $l->{'parentlnid'} ? LJ::Lang::get_lang_id($l->{'parentlnid'}) : undef;
-
- my $dbr = LJ::get_db_reader();
- my $dbh;
- my ($sth, $ret);
-
- my $remote = LJ::get_remote();
- my $can_edit   = $remote && $remote->has_priv( "translate", $l->{'lncode'} );
- my $can_delete = $remote && $remote->has_priv( "translate", "[itemdelete]" );
- my $can_rename = $remote && $remote->has_priv( "translate", "[itemrename]" );
-
- # Extra checkboxes for default language and root language (DW: en_DW and en)
- my $extra_checkboxes = $l->{'lncode'} eq $LJ::DEFAULT_LANG || !defined $lp;
-
- my $mode = {
-     '' => 'view',
-     'save' => 'save',
- }->{$FORM{'mode'}};
- return "bogus mode" unless $mode;
-
- my $MAX_EDIT = 100;
-
- if ($mode eq "view")
- {
-     my @load;
-     foreach (split /,/, $FORM{'items'})
-     {
-         next unless /^(\d+):(\d+)$/;
-         last if @load >= $MAX_EDIT;
-         push @load, { 'dmid' => $1, 'itid'=> $2 };
-     }
-
-     return "Nothing to show." unless @load;
-
-     $ret .= "<form method='post' action='editpage'>";
-     $ret .= LJ::html_hidden('lang', $lang,
-                             'mode', 'save');
-
-     # load item info
-     my %ml_items;
-     my $itwhere = join(" OR ", map { "(dmid=$_->{'dmid'} AND itid=$_->{'itid'})" } @load);
-     $sth = $dbr->prepare("SELECT dmid, itid, itcode, proofed, updated, notes FROM ml_items WHERE $itwhere");
-     $sth->execute;
-     while (my ($dmid, $itid, $itcode, $proofed, $updated, $notes) = $sth->fetchrow_array) {
-         $ml_items{"$dmid-$itid"} = { 'itcode' => $itcode, 'proofed' => $proofed, 'updated' => $updated, 'notes' => $notes };
-     }
-
-     # getting latest mappings for this lang and parent
-     my %ml_text;
-     my %ml_latest;
-     $sth = $dbr->prepare("SELECT lnid, dmid, itid, txtid, chgtime, staleness FROM ml_latest ".
-                          "WHERE ($itwhere) AND lnid IN ($l->{'lnid'}, $l->{'parentlnid'})");
-     $sth->execute;
-     return $dbr->errstr if $dbr->err;
-     while ($_ = $sth->fetchrow_hashref) {
-         $ml_latest{"$_->{'dmid'}-$_->{'itid'}"}->{$_->{'lnid'}} = $_;
-         $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = undef;  # mark to load later
-     }
-
-     # load text
-     $sth = $dbr->prepare("SELECT dmid, txtid, lnid, itid, text FROM ml_text ".
-                          "WHERE " . join(" OR ",
-                                          map { "(dmid=$_->[0] AND txtid=$_->[1])" }
-                                          map { [ split(/-/, $_) ] } keys %ml_text));
-     $sth->execute;
-     while ($_ = $sth->fetchrow_hashref) {
-         $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = $_;
-     }
-
-     if ($can_delete) {
-         $ret .= "<p style='font-size:9pt'><b>To delete an item:</b> edit text to be \"XXDELXX\"</p>";
-     }
-
-     # show all editing items
-     my $ict = 0;
-     foreach my $i (@load)
-     {
-         my ($dmid, $itid) = ($i->{'dmid'}, $i->{'itid'});
-         my $ituq = "$dmid-$itid";
-         my $it = $ml_items{$ituq};
-         my $lat = $ml_latest{$ituq}->{$l->{'lnid'}};
-         next unless $it and $lat;
-         $ict++;
-
-         my $plat;
-         if ($lp && defined $ml_latest{$ituq}->{$lp->{'lnid'}}) {
-             $plat = $ml_latest{$ituq}->{$lp->{'lnid'}};
-         }
-
-         $ret .= LJ::html_hidden("dom_$ict", $dmid,
-                                 "itid_$ict", $itid,
-                                 "oldtxtid_$ict", $lat->{'txtid'},
-                                 "oldptxtid_$ict", $plat ? $plat->{'txtid'} : 0,
-                                 );
-
-         # top bar
-         $ret .= "<table bgcolor='#c0c0c0' width='100%'><tr><td><b>Code:</b> ";
-         if ($dmid != 1) {
-             my $d = LJ::Lang::get_dom_id($dmid);
-             $ret .= "[$d->{'uniq'}] ";
-         }
-
-         my $difflink;
-         if ($lat->{'staleness'}) {
-             $difflink = "($plat->{'chgtime'}, <a target='_new' href='diff?it=$i->{'dmid'}:$i->{'itid'}&lang=$lp->{'lncode'}'>diff</a>)";
-         }
-
-         $ret .= "$it->{'itcode'} $difflink</td>";
-         $ret .= "<td align='right'><b><a target='_new' href='help-severity'>Sev</a>:</b> $lat->{'staleness'}</td>";
-         $ret .= "</tr></table>";
-
-         $ret .= "<dl>";
-         if ($it->{'notes'}) {
-             my $notes = $it->{'notes'};
-             $notes =~ s!\n!<br />!g;
-             $ret .= "<dt><b>Notes:</b></dt><dd>$notes</dd>";
-         }
-
-         my $show_edit = 0;
-         my $use_textarea = 0;
-
-         if ($plat) {
-             $ret .= "<dt><b>$lp->{'lnname'}:</b></dt>";
-             my $t = $ml_text{"$plat->{'dmid'}-$plat->{'txtid'}"}->{'text'};
-             if ($t =~ /\n/) { $use_textarea = 1; }
-             if (length($t) > 255) { $use_textarea = 1; }
-             $t = LJ::eall($t);
-             $t =~ s/\n( *)/"<br \/>" . "&nbsp;"x length($1)/eg;
-             $ret .= "<dd>$t</dd>";
-         }
-
-         my $curtext = LJ::eall($ml_text{"$lat->{'dmid'}-$lat->{'txtid'}"}->{'text'});
-         if ($curtext =~ /\n/) { $use_textarea = 1; }
-         if (length($curtext) > 255) { $use_textarea = 1; }
-         if ($lat->{'staleness'} >= 3) {
-             # if wrong language, why populate it with stuff they'll just have to delete?
-             $curtext = "";
-         }
-
-         $ret .= "<dt><b>$l->{'lnname'}</b>:</b></dt><dd>";
-         my $disabled = "disabled='disabled'";
-         if ($lat->{'staleness'} >= 3) {
-             $disabled = "";
-             # when something's this stale, assume both it's being
-             # edited and that the severity is major (going from wrong
-             # language to right language is a major change, afterall)
-             $ret .= LJ::html_hidden("ed_$ict", "1",
-                                     "sev_$ict", "2",
-                                     );
-         } else {
-             my $js = "a=document.getElementById(\"newtext_$ict\"); a.disabled=!this.checked; if (this.checked) a.focus();";
-             $js .= "a=document.getElementById(\"pr_$ict\"); a.disabled=!this.checked; a=document.getElementById(\"up_$ict\"); a.disabled=!this.checked;"
-                 if $extra_checkboxes;
-             $ret .= "<input name='ed_$ict' type='checkbox' value='1' id='ed_$ict' onClick='$js' /><label for='ed_$ict'>Edit Text</label>";
-             if ($l->{'children'} && @{$l->{'children'}}) {
-                 $ret .= " Severity: ";
-                 $ret .= LJ::html_select({ 'name' => "sev_$ict", "selected" => 1 },
-                                         0 => "Typo/etc (no notify)",
-                                         1 => "Minor (notify translators)",
-                                         2 => "Major (require translation updates)");
-             }
-             $ret .= "<br />" unless $extra_checkboxes;
-         }
-
-         if ( $extra_checkboxes ) {
-             $ret .= " ";
-             $ret .= LJ::html_check( { type => 'checkbox', label => 'Proofed',
-                                       selected => $it->{proofed}, value => 1,
-                                       name => "pr_$ict", id => "pr_$ict",
-                                       disabled => $disabled eq '' ? 0 : 1 } );
-             $ret .= " ";
-             $ret .= LJ::html_check( { type => 'checkbox', label => 'Updated',
-                                       selected => $it->{updated}, value => 1,
-                                       name => "up_$ict", id => "up_$ict",
-                                       disabled => $disabled eq '' ? 0 : 1 } );
-             $ret .= "<br />";
-         }
-
-         if ($use_textarea) {
-             $ret .= "<textarea name='newtext_$ict' id='newtext_$ict' $disabled wrap='soft' rows='10' cols='60'>$curtext</textarea>";
-         } else {
-             $ret .= "<input name='newtext_$ict' id='newtext_$ict' $disabled size='60' value=\"$curtext\"/>";
-         }
-         $ret .= "</dd>\n";
-         $ret .= "</dl>";
-     }
-
-     if ($ict) {
-         $ret .= LJ::html_hidden("ict", $ict);
-         my $disabled = $can_edit ? "" : "disabled='disabled'";
-         $ret .= "<table width='100%' bgcolor='#e0e0e0'><tr><td align='center'><input type='submit' $disabled value='Save' /></td></tr></table>";
-     } else {
-         $ret .= "No items to show.  (since been deleted, perhaps?)";
-     }
-     $ret .= "</form>";
-
-     return $ret;
- }
-
- if ($mode eq "save")
- {
-     my $num = $FORM{'ict'}+0;
-     $num = $MAX_EDIT if $num > $MAX_EDIT;
-
-     my (@errors, @info);
-     unless ($can_edit) {
-         push @errors, "You don't have access to edit text for this language.";
-         $num = 0;
-     }
-
-     unless (LJ::text_in(\%FORM)) {
-         push @errors, "You seem to have changed your browser's encoding to something other than UTF-8.  It needs to be in UTF-8.";
-         push @errors, "Nothing saved.";
-         $num = 0;
-     }
-
-     my $saved = 0;  # do any saves?
-
-     for (my $i=1; $i<=$num; $i++)
-     {
-         next unless $FORM{"ed_$i"};
-         my ($dom, $itid, $oldtxtid, $oldptxtid, $sev, $proofed, $updated) =
-             map { int($FORM{"${_}_$i"}+0) }
-                 qw(dom itid oldtxtid oldptxtid sev pr up);
-
-         my $itcode = $dbr->selectrow_array("SELECT itcode FROM ml_items WHERE dmid=$dom AND itid=$itid");
-         unless (defined $itcode) {
-             push @errors, "Bogus dmid/itid: $dom/$itid";
-             next;
-         }
-
-         $dbh ||= LJ::get_db_writer();
-         my $lat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$l->{'lnid'} AND dmid=$dom AND itid=$itid");
-         unless ($lat) {
-             push @errors, "No existing mapping for $itcode";
-             next;
-         }
-         unless ($lat->{'txtid'} == $oldtxtid) {
-             push @errors, "Another translator updated '$itcode' before you saved, so your edit has been ignored.";
-             next;
-         }
-
-         my $plat;
-         if ($lp) {
-             $plat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$lp->{'lnid'} ".
-                                             "AND dmid=$dom AND itid=$itid");
-             my $ptid = $plat ? $plat->{'txtid'} : 0;
-             unless ($ptid == $oldptxtid) {
-                 push @errors, "The source text of item '$itcode' changed while you were editing, so your edit has been ignored.";
-                 next;
-             }
-         }
-
-         # did they type anything?
-         my $text = $FORM{"newtext_$i"};
-         next unless $text =~ /\S/;
-
-         # delete
-         if ($text eq "XXDELXX") {
-             if ($can_delete) {
-                 $dbh->do("DELETE FROM ml_latest WHERE dmid=$dom AND itid=$itid");
-                 push @info, "Deleted: '$itcode'";
-             } else {
-                 push @errors, "You don't have access to delete items.";
-             }
-             next;
-         }
-
-         # did anything even change, though?
-         my $oldtext = $dbr->selectrow_array("SELECT text FROM ml_text WHERE dmid=$dom AND txtid=$lat->{'txtid'}");
-         if ($oldtext eq $text && $lat->{'staleness'} == 2) {
-             push @errors, "Severity of source language change requires change in text for item '$itcode'";
-             next;
-         }
-
-         # keep old txtid if text didn't change.
-         my $opts = {};
-         if ($oldtext eq $text) {
-             $opts->{'txtid'} = $lat->{'txtid'};
-             $text = undef;
-             $sev = 0;
-         }
-
-         # if setting text for first time, push down to children langs
-         if ($lat->{'staleness'} == 4) {
-             $opts->{'childrenlatest'} = 1;
-         }
-
-         # severity of change:
-         $opts->{'changeseverity'} = $sev;
-
-         # set userid of writer
-         $opts->{'userid'} = $remote->{'userid'};
-
-         my ($res, $msg) = LJ::Lang::web_set_text($dom, $l->{'lncode'}, $itcode, $text, $opts);
-         if ($res) {
-             push @info, "OK: $itcode";
-             $saved = 1;
-
-             if ( $extra_checkboxes ) {
-                 # Not gonna bother to refactor to LJ::Lang as the whole
-                 # translation system will get thrown away and redone later.
-                 # FIXME: make sure my words don't come back to haunt me.
-                 $dbh->do( "UPDATE ml_items SET proofed = ?, updated = ? " .
-                           "WHERE dmid = ? AND itid = ?", undef, $proofed ? 1 : 0,
-                           $updated ? 1 : 0, $dom, $itid );
-
-                 if ( $dbh->err ) {
-                     push @errors, $dbh->errstr;
-                 } else {
-                     push @info, "OK: $itcode (flags)";
-                 }
-             }
-         } else {
-             push @errors, $msg;
-         }
-
-         push @info, LJ::Hooks::run_hook('trans_editpage_bml_postsave', $opts)
-             if LJ::Hooks::are_hooks('trans_editpage_bml_postsave');
-     }
-
-     $dbh ||= LJ::get_db_writer();
-     $dbh->do("UPDATE ml_langs SET lastupdate=NOW() WHERE lnid=$l->{'lnid'}") if $saved;
-
-     if (@errors) {
-         $ret .= "<b>ERRORS:</b><ul>";
-         foreach (@errors) { $ret .= "<li>$_</li>"; }
-         $ret .= "</ul>";
-     }
-     if (@info) {
-         $ret .= "<b>Results:</b><ul>";
-         foreach (@info) { $ret .= "<li>$_</li>"; }
-         $ret .= "</ul>";
-     }
-     if (! @errors && ! @info) {
-         $ret .= "<i>No errors & nothing saved.</i>";
-     }
-     return $ret;
- }
-
-_code?>
-</body>
-</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/help-severity.bml
--- a/htdocs/translate/help-severity.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-<h1>Description of severity levels:</h1>
-
-<table cellpadding='3'>
-<tr valign='top'><td><b>0</b></td><td>Translate is up-to-date</td></tr>
-<tr valign='top'><td><b>1</b></td><td>Parent language has changed a little.  Your translation might need updating.</td></tr>
-<tr valign='top'><td><b>2</b></td><td>Parent language has changed.  Your translation probably needs updating.</td></tr>
-<tr valign='top'><td><b>3</b></td><td>New text was added in parent language which you haven't yet translated.</td></tr>
-<tr valign='top'><td><b>4</b></td><td>Item code in use but no text exists yet for any language.</td></tr>
-</table>
-
-<h2>Searching</h2>
-When searching, you can search for a certain severity level (0, 1, 2, 3, 4) or search for everything at or above a certain severity level (0+, 1+, 2+, 3+).
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/index.bml
--- a/htdocs/translate/index.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-<?page
-title=><?_ml .title _ml?>
-body<=
-
-<?_code
-{
-    use strict;
-    
-    my $dbr = LJ::get_db_reader();
-    my $sth;
-
-    LJ::set_active_crumb('translate');
-    
-    $sth = $dbr->prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs");
-    $sth->execute;
-    my %lang;
-    $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref;
- 
-    $sth = $dbr->prepare("SELECT lnid, staleness > 1, COUNT(*) FROM ml_latest GROUP by 1, 2");
-    $sth->execute;
-    while (my ($lnid, $stale, $ct) = $sth->fetchrow_array) {
-        next unless exists $lang{$lnid};
-        $lang{$lnid}->{'_total'} += $ct;
-        $lang{$lnid}->{'_good'} += (1-$stale) * $ct;
-        $lang{$lnid}->{'percent'} = 100 * $lang{$lnid}->{'_good'} / ($lang{$lnid}->{'_total'}||1);
-    }
-
-    my $sortcol = exists $lang{'1'}->{$FORM{'s'}} ? $FORM{'s'} : "lnname";
-    my @cols = (['lncode', $ML{'.table.code'}],
-                ['lnname', $ML{'.table.langname'}, sub {
-                    my $r = shift;
-                    "<td><a href='edit?lang=$r->{'lncode'}'>$r->{'lnname'}</a></td>";
-                }],
-                ['percent', $ML{'.table.done'}, sub {
-                    my $r = shift;
-                    "<td align='right'><b>" .
-                    sprintf("%.02f%%", $r->{'percent'}) . "</b><br />" .
-                    "<font size='-1'>$r->{'_good'}/$r->{'_total'}</font>" .
-                    "</td>";
-                },
-                    sub {
-                        $b->{'percent'} <=> $a->{'percent'} || $b->{'_total'} <=> $a->{'_total'}
-                }],
-                ['lastupdate', $ML{'.table.lastupdate'}, undef, sub {
-                    $b->{'lastupdate'} cmp $a->{'lastupdate'}
-                }]);
-    my $ret;
-    my $sorter = sub { $a->{$sortcol} cmp $b->{$sortcol} };
-
-    $ret .= BML::ml('.text', {'aopts' => "href='$LJ::SITEROOT/translate/teams'"});
-
-    $ret .= "<p><table border='1' cellspacing='1' cellpadding='3'><tr>";
-    foreach (@cols) {
-        if ($sortcol eq $_->[0]) {
-            $ret .= "<td><b>$_->[1]</b></td>";
-        } else {
-            $ret .= "<td><b><a href=\"./?s=$_->[0]\">$_->[1]</a></b></td>";
-        }
-        if ($_->[0] eq $sortcol && $_->[3]) { $sorter = $_->[3]; }
-    }
-    $ret .= "</tr>\n";
-
-    foreach my $r (sort $sorter values %lang) {
-        $ret .= "<tr>";
-        foreach (@cols) {
-            $ret .= $_->[2] ? $_->[2]->($r) : "<td>$r->{$_->[0]}</td>";
-        }
-        $ret .= "</tr>\n";
-    }
-
-    $ret .= "</table>\n";
-    
-    return $ret;
-}
-_code?>
-
-<=body
-page?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/index.bml.text
--- a/htdocs/translate/index.bml.text	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-;; -*- coding: utf-8 -*-
-.table.code=Code
-
-.table.done=% Done
-
-.table.langname=Language Name
-
-.table.lastupdate=Last Update
-
-.text=The following table lists the progress by each of the different <a [[aopts]]>translation teams</a>.
-
-.title=Translation Area
-
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/search.bml
--- a/htdocs/translate/search.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-<?_code
-{
-    my $lang = $FORM{'lang'};
-    my $l = LJ::Lang::get_lang($lang);
-    return "<b>Invalid language</b>" unless $l;
-
-    my $dbr = LJ::get_db_reader();
-    my $sth;
-
-    my $sql;
-
-    # all queries use the visible flag
-    my $vis_flag = '';
-    $vis_flag = 'AND i.visible = 1' unless $LJ::IS_DEV_SERVER;
-
-    if ($FORM{'search'} eq 'sev')
-    {
-        my $what = ">= 1";
-        if ($FORM{'stale'} =~ /^(\d+)(\+?)$/) {
-            $what = ($2 ? ">=" : "=") . $1;
-        }
-        $sql = qq(
-            SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
-            WHERE l.lnid=$l->{'lnid'} AND l.staleness $what AND l.dmid=i.dmid AND l.itid=i.itid $vis_flag
-            ORDER BY i.dmid, i.itcode
-        );
-    }
-
-    if ($FORM{'search'} eq 'txt')
-    {
-        my $remote = LJ::get_remote();
-        return "This search type is restricted to $l->{'lnname'} translators." unless
-            $remote && ( $remote->has_priv( "translate", $l->{'lncode'} ) ||
-                         $remote->has_priv( "faqedit", "*" ) ); # FAQ admins can search too
-
-        my $qtext = $dbr->quote($FORM{'searchtext'});
-        my $dmid = $FORM{'searchdomain'}+0;
-        my $dmidwhere = $dmid ? "AND i.dmid=$dmid" : "";
-        if ($FORM{'searchwhat'} eq "code") {
-            $sql = qq{
-                SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
-                WHERE l.lnid=$l->{'lnid'} AND l.dmid=i.dmid AND i.itid=l.itid $vis_flag
-                $dmidwhere AND LOCATE($qtext, i.itcode)
-            };
-        } else {
-            my $lnid = $l->{'lnid'};
-            if ($FORM{'searchwhat'} eq "parent") { $lnid = $l->{'parentlnid'}; }
-            $sql = qq{
-                SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l, ml_text t
-                WHERE l.lnid=$lnid AND l.dmid=i.dmid AND i.itid=l.itid
-                $dmidwhere AND t.dmid=l.dmid AND t.txtid=l.txtid AND LOCATE($qtext, t.text) $vis_flag
-                ORDER BY i.itcode
-            };
-        }
-    }
-
-    if ($FORM{'search'} eq 'flg') {
-        return "This type of search isn't available for this language."
-            unless $l->{'lncode'} eq $LJ::DEFAULT_LANG || !$l->{'parentlnid'};
-
-        my $whereflags = join ' AND ',
-            map { $FORM{"searchflag$_"} eq 'yes' ? "$_ = 1" : "$_ = 0" }
-                grep { $FORM{"searchflag$_"} ne 'whatev' } qw(proofed updated);
-        $whereflags = "AND $whereflags"
-            if $whereflags ne '';
-        $sql = qq(
-            SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l
-            WHERE l.lnid=$l->{lnid} AND l.dmid=i.dmid AND l.itid=i.itid $whereflags $vis_flag
-            ORDER BY i.dmid, i.itcode
-        );
-    }
-
-    return "Bogus or unimplemented query type." unless $sql;
-
-    my $ret;
-    $sth = $dbr->prepare($sql);
-    $sth->execute;
-    my $page = 0;
-    my @page = ();
-    my $addlink = sub {
-        return unless @page;
-        $page++;
-        my $link = "editpage?lang=$lang&amp;items=" . LJ::eurl(join(",",map{"$_->[0]:$_->[1]"}@page));
-        $ret .= "<b><a target='main' href='$link'>Page $page</a></b><br /><span style='font-size:8pt'>\n";
-        $ret .= "$page[0]->[2]<br />\n";
-        $ret .= "$page[-1]->[2]<br /></span>\n";
-        @page = ();
-    };
-    while (my ($dmid, $itid, $itcode) = $sth->fetchrow_array) {
-        push @page, [ $dmid, $itid, $itcode ];
-        $addlink->() if @page >= 10;
-    }
-    $addlink->();
-
-    if ($page == 0) { $ret .= "<i>(No matches)</i>"; }
-
-    return $ret;
-
-}
-_code?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/searchform.bml
--- a/htdocs/translate/searchform.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-<html>
-<head><title>Search Form</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-</head>
-<body marginwidth='0' marginheight='0'>
-
-<form target='res' action='search' method='get'>
-<input type='hidden' name='lang' value='<?_code $FORM{'lang'} _code?>'>
-<input type='hidden' name='search' value='sev'>
-
-[<a href="./" target='_top'>&lt;-- Back</a>]
-<?_code
- my $lang = $FORM{'lang'};
- my $l = LJ::Lang::get_lang($lang);
- BML::finish() unless $l;
- return "<b>" . ($l ? $l->{'lnname'} : "Invalid language") . "</b>";
-_code?>
-
-<p>By Severity: (<a href='help-severity' target='main'>help</a>)<br /><select name='stale'>
-<option value="0">0</option>
-<option value="0+">0+</option>
-<option value="1">1</option>
-<option value="1+" selected='selected'>1+</option>
-<option value="2">2</option>
-<option value="2+">2+</option>
-<option value="3">3</option>
-<option value="3+">3+</option>
-<option value="4">4</option>
-</select><input type='submit' value='Search'/>
-</p>
-</form>
-
-<form target='res' action='search' method='get'>
-<input type='hidden' name='lang' value='<?_code $FORM{'lang'} _code?>'>
-<input type='hidden' name='search' value='txt'>
-
-<p>Search
-<?_code
- my $ret;
- my $l = LJ::Lang::get_lang($FORM{'lang'});
- my $pl = LJ::Lang::get_lang_id($l->{'parentlnid'});
- my @opt = ("src" => $l->{'lnname'});
- if ($pl) { push @opt, "parent", $pl->{'lnname'} };
- push @opt, "code", "Item Code";
- $ret .= LJ::html_select({ 'name' => 'searchwhat' },
-                         @opt);
- $ret .= "<br />Area: ";
- $ret .= LJ::html_select({ 'name' => 'searchdomain' },
-                         0, "(all)",
-                         map { $_->{'dmid'}, $_->{'uniq'} }
-                         sort { $a->{'dmid'} <=> $b->{'dmid'} } LJ::Lang::get_domains());
- return $ret;
-_code?>
-    <br />Text: <input name='searchtext' size='15'><input type='submit' value='Search'>
-</p>
-</form>
-
-<?_code
- my $l = LJ::Lang::get_lang($FORM{'lang'});
- return '' unless $l->{'lncode'} eq $LJ::DEFAULT_LANG || !$l->{'parentlnid'};
-
- my $ret = <<HTML;
-<form target='res' action='search' method='get'>
-<input type='hidden' name='lang' value='$l->{lncode}'>
-<input type='hidden' name='search' value='flg'>
-<p><table><tr><td>Prf:</td>
-<td><input type='radio' name='searchflagproofed' value='whatev'>Both</td>
-<td><input type='radio' name='searchflagproofed' value='yes'>Yes</td>
-<td><input type='radio' name='searchflagproofed' value='no'>No</td></tr>
-<tr><td>Upd:</td>
-<td><input type='radio' name='searchflagupdated' value='whatev'>Both</td>
-<td><input type='radio' name='searchflagupdated' value='yes'>Yes</td>
-<td><input type='radio' name='searchflagupdated' value='no'>No</td></tr></table>
-<input type='submit' value='Search'></p></form>
-HTML
- return $ret;
-_code?>
-
-</body>
-</html>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/teams.bml
--- a/htdocs/translate/teams.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-<?page
-title=><?_ml .title _ml?>
-body<=
-<?_code
-{
-    use strict;
-
-    my $dbr = LJ::get_db_reader();
-    my ($ret, $sth);
-
-    LJ::set_active_crumb('translateteams');
-
-    $ret .= "<?h1 $ML{'.teams.header'} h1?>";
-    $ret .= "<?p $ML{'.teams.text'} p?>";
-
-    # get langs
-    $sth = $dbr->prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs");
-    $sth->execute;
-    my %lang;
-    $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref;
-
-    # get each lang's community
-    $sth = $dbr->prepare("SELECT l.lnid, t.text ".
-                        "FROM ml_latest l, ml_items i, ml_text t ".
-                        "WHERE l.dmid=1 AND t.dmid=1 AND i.dmid=1 AND i.itcode='thislang.community' ".
-                        "AND l.itid=i.itid AND t.txtid=l.txtid AND t.lnid=l.lnid");
-    $sth->execute;
-    while ($_ = $sth->fetchrow_hashref) {
-        next unless exists $lang{$_->{'lnid'}};
-        $lang{$_->{'lnid'}}->{'community'} = $_->{'text'};
-    }
-
-    # get people with privs
-    $sth = $dbr->prepare("SELECT pm.arg, u.user FROM useridmap u, priv_list pl, priv_map pm ".
-                        "WHERE pm.userid=u.userid AND pm.prlid=pl.prlid AND pl.privcode='translate'");
-    $sth->execute;
-    my %team;
-    while (my ($arg, $user) = $sth->fetchrow_array) {
-        push @{$team{$arg}}, $user;
-    }
-
-    $ret .= "<p><table cellpadding='5' border='1'>";
-    $ret .= "<tr><th>$ML{'.table.language'}</th><th>$ML{'.table.community'}</th><th>$ML{'.table.users'}</th></tr>";
-
-    foreach my $l (sort { $a->{'lnname'} cmp $b->{'lnname'} } values %lang) {
-        $ret .= "<tr valign='top' align='left'><td><b>$l->{'lnname'}</b></td>";
-        $ret .= "<td>";
-        $ret .= "<?ljcomm $l->{'community'} ljcomm?>" if $l->{'community'};
-        $ret .= "</td><td>";
-        if ($team{$l->{'lncode'}}) {
-            $ret .= join(", ", map { LJ::ljuser($_) }
-            sort @{$team{$l->{'lncode'}}});
-        }
-        $ret .= "</td></tr>\n";
-    }
-
-    $ret .= "</table>";
-    return $ret;
-}
-_code?>
-
-<=body
-page?>
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/teams.bml.text
--- a/htdocs/translate/teams.bml.text	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-;; -*- coding: utf-8 -*-
-.table.community=Community
-
-.table.language=Language
-
-.table.users=Users With Privs
-
-.teams.header=Teams
-
-.teams.text=Translation is being done by the following teams:
-
-.title=Translation Teams
-
diff -r 9323f181bcb6 -r 8428f0b6ae2d htdocs/translate/welcome.bml
--- a/htdocs/translate/welcome.bml	Tue Feb 16 15:09:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-Welcome to the translation area.
-
-<p>In the top-left frame you search for phrases to translate.
-
-<p>The lower-left frame shows your search result links, paginated.
-
-<p>This large frame is the work area, in which text is edited.
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org