Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.140
diff -u -p -r1.140 locale.inc
--- includes/locale.inc	18 Jun 2007 09:41:30 -0000	1.140
+++ includes/locale.inc	18 Jun 2007 12:13:32 -0000
@@ -729,7 +729,12 @@ function locale_translate_export_pot_for
  */
 function locale_translate_export_po_form_submit($form, &$form_state) {
   // If template is required, language code is not given.
-  _locale_export_po(isset($form_state['values']['langcode']) ? $form_state['values']['langcode'] : NULL, $form_state['values']['group']);
+  $language = NULL;
+  if (isset($form_state['values']['langcode'])) {
+    $languages = language_list();
+    $language = $languages[$form_state['values']['langcode']];
+  }
+  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $form_state['values']['group'])));
 }
 /**
  * @} End of "locale-translate-export"
@@ -1681,109 +1686,115 @@ function _locale_parse_js_file($filepath
  */
 
 /**
- * Exports a Portable Object (Template) file for a language
+ * Generates a structured array of all strings with translations in
+ * $language, if given. This array can be used to generate an export
+ * of the string in the database.
  *
  * @param $language
- *   Language code to generate the output for, or NULL if generating
+ *   Language object to generate the output for, or NULL if generating
  *   translation template.
  * @param $group
  *   Text group to export PO file from (eg. 'default' for interface translations)
  */
-function _locale_export_po($language = NULL, $group = 'default') {
-  global $user;
-  $header = '';
-  // Get language specific strings, or all strings
+function _locale_export_get_strings($language = NULL, $group = 'default') {
   if (isset($language)) {
-    $meta = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $language));
-    $result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.textgroup = '%s' ORDER BY t.plid, t.plural", $language, $group);
+    $result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.textgroup = '%s' ORDER BY t.plid, t.plural", $language->language, $group);
   }
   else {
     $result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $group);
   }
-
-  // Build array out of the database results
-  $parent = array();
+  $strings = array();
   while ($child = db_fetch_object($result)) {
-    if ($child->source != '') {
-      $parent[$child->lid]['comment'] = $child->location;
-      $parent[$child->lid]['msgid'] = $child->source;
-      $parent[$child->lid]['translation'] = isset($child->translation) ? $child->translation : '';
-      if ($child->plid) {
-        $parent[$child->lid]['child'] = 1;
-        $parent[$child->plid]['plural'] = $child->lid;
-      }
+    $string = array(
+      'comment'     => $child->location,
+      'source'      => $child->source,
+      'translation' => isset($child->translation) ? $child->translation : ''
+    );
+    if ($child->plid) {
+      // Has a parent lid. Since we process in the order of plids,
+      // we already have the parent in the array, so we can add the
+      // lid to the next plural version to it. This builds a linked
+      // list of plurals.
+      $string['child'] = TRUE;
+      $strings[$child->plid]['plural'] = $child->lid;
     }
+    $strings[$child->lid] = $string;
   }
+  return $strings;
+}
 
-  // Generating Portable Object file for a language
-  if (isset($language)) {
-    $filename = $language .'.po';
-    $header = "# $meta->name translation of ". variable_get('site_name', 'Drupal') ."\n";
-    $header .= '# Copyright (c) '. date('Y') .' '. $user->name .' <'. $user->mail .">\n";
-    $header .= "#\n";
-    $header .= "msgid \"\"\n";
-    $header .= "msgstr \"\"\n";
-    $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
-    $header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
-    $header .= "\"PO-Revision-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
-    $header .= "\"Last-Translator: ". $user->name .' <'. $user->mail .">\\n\"\n";
-    $header .= "\"Language-Team: ". $meta->name .' <'. $user->mail .">\\n\"\n";
-    $header .= "\"MIME-Version: 1.0\\n\"\n";
-    $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
-    $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
-    if ($meta->formula && $meta->plurals) {
-      $header .= "\"Plural-Forms: nplurals=". $meta->plurals ."; plural=". strtr($meta->formula, array('$' => '')) .";\\n\"\n";
+/**
+ * Generates the PO(T) file contents for given strings.
+ * 
+ * @param $language
+ *   Language object to generate the output for, or NULL if generating
+ *   translation template.
+ * @param $strings
+ *   Array of strings to export. See _locale_export_get_strings()
+ *   on how it should be formatted.
+ * @param $header
+ *   The header portion to use for the output file. Defaults
+ *   are provided for PO and POT files.
+ */
+function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
+  global $user;
+  
+  if (!isset($header)) {
+    if (isset($language)) {
+      $header = '# '. $language->name .' translation of '. variable_get('site_name', 'Drupal') ."\n";
+      $header .= '# Generated by '. $user->name .' <'. $user->mail .">\n";
+      $header .= "#\n";
+      $header .= "msgid \"\"\n";
+      $header .= "msgstr \"\"\n";
+      $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
+      $header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
+      $header .= "\"PO-Revision-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
+      $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"MIME-Version: 1.0\\n\"\n";
+      $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
+      $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
+      if ($language->formula && $language->plurals) {
+        $header .= "\"Plural-Forms: nplurals=". $language->plurals ."; plural=". strtr($language->formula, array('$' => '')) .";\\n\"\n";
+      }
+    }
+    else {
+      $header = "# LANGUAGE translation of PROJECT\n";
+      $header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n";
+      $header .= "#\n";
+      $header .= "msgid \"\"\n";
+      $header .= "msgstr \"\"\n";
+      $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
+      $header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
+      $header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
+      $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"MIME-Version: 1.0\\n\"\n";
+      $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
+      $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
+      $header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
     }
-    $header .= "\n";
-    watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $meta->name, '%filename' => $filename));
-  }
-
-  // Generating Portable Object Template
-  else {
-    $filename = 'drupal.pot';
-    $header = "# LANGUAGE translation of PROJECT\n";
-    $header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n";
-    $header .= "#\n";
-    $header .= "msgid \"\"\n";
-    $header .= "msgstr \"\"\n";
-    $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
-    $header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
-    $header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
-    $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
-    $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
-    $header .= "\"MIME-Version: 1.0\\n\"\n";
-    $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
-    $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
-    $header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
-    $header .= "\n";
-    watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
   }
-
-  // Start download process
-  header("Content-Disposition: attachment; filename=$filename");
-  header("Content-Type: text/plain; charset=utf-8");
-
-  print $header;
-
-  foreach ($parent as $lid => $message) {
-    if (!isset($message['child'])) {
-      if ($message['comment']) {
-        print '#: '. $message['comment'] ."\n";
-      }
-      print 'msgid '. _locale_export_print($message['msgid']);
-      if (!empty($message['plural'])) {
-        $plural = $message['plural'];
-        print 'msgid_plural '. _locale_export_print($parent[$plural]['msgid']);
+  
+  $output = $header ."\n";
+  
+  foreach ($strings as $lid => $string) {
+    // Only process non-children, children are output below their parent.
+    if (!isset($string['child'])) {
+      if ($string['comment']) {
+        $output .= '#: '. $string['comment'] ."\n";
+      }
+      $output .= 'msgid '. _locale_export_string($string['source']);
+      if (!empty($string['plural'])) {
+        $plural = $string['plural'];
+        $output .= 'msgid_plural '. _locale_export_string($strings[$plural]['source']);
         if (isset($language)) {
-          $translation = $message['translation'];
-          for ($i = 0; $i < $meta->plurals; $i++) {
-            print 'msgstr['. $i .'] '. _locale_export_print($translation);
+          $translation = $string['translation'];
+          for ($i = 0; $i < $language->plurals; $i++) {
+            $output .= 'msgstr['. $i .'] '. _locale_export_string($translation);
             if ($plural) {
-              $translation = $parent[$plural]['translation'];
-              if ($i > 1) {
-                $translation = _locale_export_remove_plural($translation);
-              }
-              $plural = $parent[$plural]['plural'];
+              $translation = _locale_export_remove_plural($strings[$plural]['translation']);
+              $plural = isset($strings[$plural]['plural']) ? $strings[$plural]['plural'] : 0;
             }
             else {
               $translation = '';
@@ -1791,28 +1802,50 @@ function _locale_export_po($language = N
           }
         }
         else {
-          print 'msgstr[0] ""'."\n";
-          print 'msgstr[1] ""'."\n";
+          $output .= 'msgstr[0] ""'."\n";
+          $output .= 'msgstr[1] ""'."\n";
         }
       }
       else {
-        if (isset($language)) {
-          print 'msgstr '. _locale_export_print($message['translation']);
-        }
-        else {
-          print 'msgstr ""'."\n";
-        }
+        $output .= 'msgstr '. _locale_export_string($string['translation']);
       }
-      print "\n";
+      $output .= "\n";
     }
   }
+  return $output;
+}
+
+/**
+ * Write a generated PO or POT file to the output.
+ *
+ * @param $language
+ *   Language object to generate the output for, or NULL if generating
+ *   translation template.
+ * @param $output
+ *   The PO(T) file to output as a string. See _locale_export_generate_po()
+ *   on how it can be generated.
+ */
+function _locale_export_po($language = NULL, $output = NULL) {
+  // Log the export event.
+  if (isset($language)) {
+    $filename = $language->language .'.po';
+    watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $language->name, '%filename' => $filename));
+  }
+  else {
+    $filename = 'drupal.pot';
+    watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
+  }
+  // Download the file fo the client.
+  header("Content-Disposition: attachment; filename=$filename");
+  header("Content-Type: text/plain; charset=utf-8");
+  print $output;
   die();
 }
 
 /**
  * Print out a string on multiple lines
  */
-function _locale_export_print($str) {
+function _locale_export_string($str) {
   $stri = addcslashes($str, "\0..\37\\\"");
   $parts = array();
 
