diff --git a/modules/locale.module b/modules/locale.module
index f0a053bf68e9d58afb8269d2c7dffbc0bda2f3f1..384d2f8a9194ddf3784dde7e9d08db909201dc45 100644
--- a/modules/locale.module
+++ b/modules/locale.module
@@ -103,7 +103,7 @@ function locale_overview() {
   $result = db_query("SELECT * FROM locales ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>". check_output($locale->location) ."</I></SMALL></TD><TD ALIGN=\"center\">". check_output(locale_languages($locale)) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\">edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -116,7 +116,7 @@ function locale_translated($language) {
   $result = db_query("SELECT * FROM locales WHERE $language != '' ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>original string</TH><TH>translated string</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>original string</TH><TH>translated string</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."</TD><TD>". check_output($locale->$language) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\"> edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -129,7 +129,7 @@ function locale_untranslated($language) {
   $result = db_query("SELECT * FROM locales WHERE $language = '' ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>string</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>string</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>$locale->location</I></SMALL></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\"> edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -138,6 +138,36 @@ function locale_untranslated($language) {
   return $output;
 }
 
+function locale_search() {
+  global $edit, $languages, $REQUEST_URI;
+
+  if (is_array($edit)) {
+    if ($edit[language] && $edit[status]) $query[] = check_input($edit[language]) . (check_input($edit[status]) == 1 ? " !=" : " =") ." ''";
+    if ($edit[module]) $query[] = "location LIKE '%module.php?mod=". check_input($edit[module]) ."%'";
+    if ($edit[string]) $query[] = "string LIKE '%". check_input($edit[string]) ."%'";
+    
+    $result = db_query("SELECT * FROM locales". (count($query) ? " WHERE ". @implode(" && ", $query) : ""));
+
+    $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
+    $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
+    while ($locale = db_fetch_object($result)) {
+      $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>". check_output($locale->location) ."</I></SMALL></TD><TD ALIGN=\"center\">". check_output(locale_languages($locale)) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\">edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
+    }
+    $output .= "</TABLE>\n";
+    
+  }
+  $form .= form_select("Language", "language", $edit[langauge], array_merge(array(0=>"All"), $languages));
+  $form .= form_select("Status", "status", $edit[status], array("All", "Translated", "Untranslated"), "Only used when a language is selected.");
+  $form .= form_select("Module", "module", $edit[module], array_merge(array(0=>"All"), module_list()));
+  $form .= form_textfield("String", "string", $edit[string], 30, 30, "Leave blank to show all strings.");
+
+  $form .= form_submit("Search");
+  
+  $output .= form($REQUEST_URI, $form);
+
+  return $output;
+}
+
 function locale_admin() {
   global $id, $edit, $op, $language;
 
@@ -145,7 +175,7 @@ function locale_admin() {
     print status("locale disabled.");
   }
   else if (user_access("administer locales")) {
-    print "<SMALL>". locale_links(1) . locale_links(0) ."<A HREF=\"admin.php?mod=locale\">overview</A> | <A HREF=\"admin.php?mod=locale&op=help\">help</A></SMALL><HR>\n";
+    print "<SMALL>". locale_links(1) . locale_links(0) ."<A HREF=\"admin.php?mod=locale&op=search\">search</A> | <A HREF=\"admin.php?mod=locale\">overview</A> | <A HREF=\"admin.php?mod=locale&op=help\">help</A></SMALL><HR>\n";
 
     switch ($op) {
       case "delete":
@@ -158,15 +188,18 @@ function locale_admin() {
       case "edit":
         print locale_edit(check_input($id));
         break;
-      case "Save translations":
-        print locale_save(check_input($id), $edit);
-        break;
       case "translated":
         print locale_translated($language);
         break;
       case "untranslated":
         print locale_untranslated($language);
         break;
+      case "Search":
+      case "search":
+        print locale_search();
+        break;
+      case "Save translations":
+        print locale_save(check_input($id), $edit);
       default:
         print locale_overview();
     }
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index f0a053bf68e9d58afb8269d2c7dffbc0bda2f3f1..384d2f8a9194ddf3784dde7e9d08db909201dc45 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -103,7 +103,7 @@ function locale_overview() {
   $result = db_query("SELECT * FROM locales ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>". check_output($locale->location) ."</I></SMALL></TD><TD ALIGN=\"center\">". check_output(locale_languages($locale)) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\">edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -116,7 +116,7 @@ function locale_translated($language) {
   $result = db_query("SELECT * FROM locales WHERE $language != '' ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>original string</TH><TH>translated string</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>original string</TH><TH>translated string</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."</TD><TD>". check_output($locale->$language) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\"> edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -129,7 +129,7 @@ function locale_untranslated($language) {
   $result = db_query("SELECT * FROM locales WHERE $language = '' ORDER BY string");
 
   $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
-  $output .= " <TR><TH>string</TH><TH COLSPAN=\"2\">operations</TH><TR>\n";
+  $output .= " <TR><TH>string</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
   while ($locale = db_fetch_object($result)) {
     $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>$locale->location</I></SMALL></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\"> edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
   }
@@ -138,6 +138,36 @@ function locale_untranslated($language) {
   return $output;
 }
 
+function locale_search() {
+  global $edit, $languages, $REQUEST_URI;
+
+  if (is_array($edit)) {
+    if ($edit[language] && $edit[status]) $query[] = check_input($edit[language]) . (check_input($edit[status]) == 1 ? " !=" : " =") ." ''";
+    if ($edit[module]) $query[] = "location LIKE '%module.php?mod=". check_input($edit[module]) ."%'";
+    if ($edit[string]) $query[] = "string LIKE '%". check_input($edit[string]) ."%'";
+    
+    $result = db_query("SELECT * FROM locales". (count($query) ? " WHERE ". @implode(" && ", $query) : ""));
+
+    $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
+    $output .= " <TR><TH>string</TH><TH>languages</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
+    while ($locale = db_fetch_object($result)) {
+      $output .= " <TR><TD>". check_output($locale->string) ."<BR><SMALL><I>". check_output($locale->location) ."</I></SMALL></TD><TD ALIGN=\"center\">". check_output(locale_languages($locale)) ."</TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=edit&id=$locale->id\">edit locale</A></TD><TD NOWRAP><A HREF=\"admin.php?mod=locale&op=delete&id=$locale->id\">delete locale</A></TD></TR>";
+    }
+    $output .= "</TABLE>\n";
+    
+  }
+  $form .= form_select("Language", "language", $edit[langauge], array_merge(array(0=>"All"), $languages));
+  $form .= form_select("Status", "status", $edit[status], array("All", "Translated", "Untranslated"), "Only used when a language is selected.");
+  $form .= form_select("Module", "module", $edit[module], array_merge(array(0=>"All"), module_list()));
+  $form .= form_textfield("String", "string", $edit[string], 30, 30, "Leave blank to show all strings.");
+
+  $form .= form_submit("Search");
+  
+  $output .= form($REQUEST_URI, $form);
+
+  return $output;
+}
+
 function locale_admin() {
   global $id, $edit, $op, $language;
 
@@ -145,7 +175,7 @@ function locale_admin() {
     print status("locale disabled.");
   }
   else if (user_access("administer locales")) {
-    print "<SMALL>". locale_links(1) . locale_links(0) ."<A HREF=\"admin.php?mod=locale\">overview</A> | <A HREF=\"admin.php?mod=locale&op=help\">help</A></SMALL><HR>\n";
+    print "<SMALL>". locale_links(1) . locale_links(0) ."<A HREF=\"admin.php?mod=locale&op=search\">search</A> | <A HREF=\"admin.php?mod=locale\">overview</A> | <A HREF=\"admin.php?mod=locale&op=help\">help</A></SMALL><HR>\n";
 
     switch ($op) {
       case "delete":
@@ -158,15 +188,18 @@ function locale_admin() {
       case "edit":
         print locale_edit(check_input($id));
         break;
-      case "Save translations":
-        print locale_save(check_input($id), $edit);
-        break;
       case "translated":
         print locale_translated($language);
         break;
       case "untranslated":
         print locale_untranslated($language);
         break;
+      case "Search":
+      case "search":
+        print locale_search();
+        break;
+      case "Save translations":
+        print locale_save(check_input($id), $edit);
       default:
         print locale_overview();
     }