Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.266
diff -u -r1.266 locale.inc
--- includes/locale.inc	3 Jan 2011 18:03:54 -0000	1.266
+++ includes/locale.inc	17 Feb 2011 16:37:59 -0000
@@ -586,159 +586,250 @@
  */
 function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
 
-  $fd = fopen($file->uri, "rb"); // File will get closed by PHP on return
+  // The file will get closed by PHP on returning from this function.
+  $fd = fopen($file->uri, 'rb');
   if (!$fd) {
     _locale_import_message('The translation import failed, because the file %filename could not be read.', $file);
     return FALSE;
   }
+
+  /*
+   * The parser context. Can be:
+   *  - 'COMMENT' (#)
+   *  - 'MSGID' (msgid)
+   *  - 'MSGID_PLURAL' (msgid_plural)
+   *  - 'MSGCTXT' (msgctxt)
+   *  - 'MSGSTR' (msgstr or msgstr[])
+   *  - 'MSGSTR_ARR' (msgstr_arg)
+   */
+  $context = 'COMMENT';
+
+  // Current entry being read.
+  $current = array();
 
-  $context = "COMMENT"; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
-  $current = array();   // Current entry being read
-  $plural = 0;          // Current plural form
-  $lineno = 0;          // Current line
+  // Current plurality for 'msgstr[]'.
+  $plural = 0;
+
+  // Current line.
+  $lineno = 0;
 
   while (!feof($fd)) {
-    $line = fgets($fd, 10*1024); // A line should not be this long
+    // A line should not be longer than 10 * 1024.
+    $line = fgets($fd, 10 * 1024);
+
     if ($lineno == 0) {
       // The first line might come with a UTF-8 BOM, which should be removed.
       $line = str_replace("\xEF\xBB\xBF", '', $line);
     }
+
     $lineno++;
+
+    // Trim away the linefeed.
     $line = trim(strtr($line, array("\\\n" => "")));
 
-    if (!strncmp("#", $line, 1)) { // A comment
-      if ($context == "COMMENT") { // Already in comment context: add
-        $current["#"][] = substr($line, 1);
+    if (!strncmp('#', $line, 1)) {
+      // Lines starting with '#' are comments.
+
+      if ($context == 'COMMENT') {
+        // Already in comment token, insert the comment.
+        $current['#'][] = substr($line, 1);
       }
-      elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one
+      elseif (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in string token, close it out.
         _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
-        $current = array();
-        $current["#"][] = substr($line, 1);
-        $context = "COMMENT";
+
+        // Start a new entry for the comment.
+        $current         = array();
+        $current['#'][]  = substr($line, 1);
+
+        $context = 'COMMENT';
       }
-      else { // Parse error
+      else {
+        // A comment following any other token is a syntax error.
         _locale_import_message('The translation file %filename contains an error: "msgstr" was expected but not found on line %line.', $file, $lineno);
         return FALSE;
       }
     }
-    elseif (!strncmp("msgid_plural", $line, 12)) {
-      if ($context != "MSGID") { // Must be plural form for current entry
+    elseif (!strncmp('msgid_plural', $line, 12)) {
+      // A plural form for the current message.
+
+      if ($context != 'MSGID') {
+        // A plural form cannot be added to anything else but the id directly.
         _locale_import_message('The translation file %filename contains an error: "msgid_plural" was expected but not found on line %line.', $file, $lineno);
         return FALSE;
       }
+
+      // Remove 'msgid_plural' and trim away whitespace.
       $line = trim(substr($line, 12));
+      // At this point, $line should now contain only the plural form.
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The plural form must be wrapped in quotes.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $current["msgid"] = $current["msgid"] . "\0" . $quoted;
-      $context = "MSGID_PLURAL";
+
+      // Append the plural form to the current entry.
+      $current['msgid'] .= '\0' . $quoted;
+
+      $context = 'MSGID_PLURAL';
     }
-    elseif (!strncmp("msgid", $line, 5)) {
-      if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {   // End current entry, start a new one
+    elseif (!strncmp('msgid', $line, 5)) {
+      // Starting a new message.
+
+      if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in a message string, close it out.
         _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+
+        // Start a new context for the id.
         $current = array();
       }
-      elseif ($context == "MSGID") { // Already in this context? Parse error
+      elseif ($context == 'MSGID') {
+        // We are currently already in the context, meaning we passed an id with no data.
         _locale_import_message('The translation file %filename contains an error: "msgid" is unexpected on line %line.', $file, $lineno);
         return FALSE;
       }
+
+      // Remove 'msgid' and trim away whitespace.
       $line = trim(substr($line, 5));
+      // At this point, $line should now contain only the message id.
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The message id must be wrapped in quotes.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $current["msgid"] = $quoted;
-      $context = "MSGID";
+
+      $current['msgid'] = $quoted;
+      $context = 'MSGID';
     }
-    elseif (!strncmp("msgctxt", $line, 7)) {
-      if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {   // End current entry, start a new one
+    elseif (!strncmp('msgctxt', $line, 7)) {
+      // Starting a new context.
+
+      if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in a message, start a new one.
         _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
         $current = array();
       }
-      elseif (!empty($current["msgctxt"])) { // Already in this context? Parse error
+      elseif (!empty($current['msgctxt'])) {
+        // A context cannot apply to another context.
         _locale_import_message('The translation file %filename contains an error: "msgctxt" is unexpected on line %line.', $file, $lineno);
         return FALSE;
       }
+
+      // Remove 'msgctxt' and trim away whitespaces.
       $line = trim(substr($line, 7));
+      // At this point, $line should now contain the context.
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The context string must be quoted.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $current["msgctxt"] = $quoted;
-      $context = "MSGCTXT";
+
+      $current['msgctxt'] = $quoted;
+
+      $context = 'MSGCTXT';
     }
-    elseif (!strncmp("msgstr[", $line, 7)) {
-      if (($context != "MSGID") && ($context != "MSGCTXT") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) { // Must come after msgid, msgxtxt, msgid_plural, or msgstr[]
+    elseif (!strncmp('msgstr[', $line, 7)) {
+      // A message string for a specific plurality.
+
+      if (($context != 'MSGID') && ($context != 'MSGCTXT') && ($context != 'MSGID_PLURAL') && ($context != 'MSGSTR_ARR')) {
+        // Message strings must come after msgid, msgxtxt, msgid_plural, or other msgstr[] entries.
         _locale_import_message('The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.', $file, $lineno);
         return FALSE;
       }
-      if (strpos($line, "]") === FALSE) {
+
+      // Ensure the plurality is terminated.
+      if (strpos($line, ']') === FALSE) {
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $frombracket = strstr($line, "[");
-      $plural = substr($frombracket, 1, strpos($frombracket, "]") - 1);
+
+      // Extract the plurality.
+      $frombracket = strstr($line, '[');
+      $plural = substr($frombracket, 1, strpos($frombracket, ']') - 1);
+
+      // Skip to the next whitespace and trim away any further whitespace, bringing $line to the message data.
       $line = trim(strstr($line, " "));
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The string must be quoted.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $current["msgstr"][$plural] = $quoted;
-      $context = "MSGSTR_ARR";
+
+      $current['msgstr'][$plural] = $quoted;
+
+      $context = 'MSGSTR_ARR';
     }
     elseif (!strncmp("msgstr", $line, 6)) {
-      if (($context != "MSGID") && ($context != "MSGCTXT")) {   // Should come just after a msgid or msgctxt block
+      // A string for the an id or context.
+
+      if (($context != 'MSGID') && ($context != 'MSGCTXT')) {
+        // Strings are only valid within an id or context scope.
         _locale_import_message('The translation file %filename contains an error: "msgstr" is unexpected on line %line.', $file, $lineno);
         return FALSE;
       }
+
+      // Remove 'msgstr' and trim away away whitespaces.
       $line = trim(substr($line, 6));
+      // At this point, $line should now contain the message.
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The string must be quoted.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      $current["msgstr"] = $quoted;
-      $context = "MSGSTR";
+
+      $current['msgstr'] = $quoted;
+
+      $context = 'MSGSTR';
     }
-    elseif ($line != "") {
+    elseif ($line != '') {
+      // Anything that is not a token may be a continuation of a previous token.
+
       $quoted = _locale_import_parse_quoted($line);
       if ($quoted === FALSE) {
+        // The string must be quoted.
         _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
         return FALSE;
       }
-      if (($context == "MSGID") || ($context == "MSGID_PLURAL")) {
-        $current["msgid"] .= $quoted;
+
+      // Append the string to the current context.
+      if (($context == 'MSGID') || ($context == 'MSGID_PLURAL')) {
+        $current['msgid'] .= $quoted;
       }
-      elseif ($context == "MSGCTXT") {
-        $current["msgctxt"] .= $quoted;
+      elseif ($context == 'MSGCTXT') {
+        $current['msgctxt'] .= $quoted;
       }
-      elseif ($context == "MSGSTR") {
-        $current["msgstr"] .= $quoted;
+      elseif ($context == 'MSGSTR') {
+        $current['msgstr'] .= $quoted;
       }
-      elseif ($context == "MSGSTR_ARR") {
-        $current["msgstr"][$plural] .= $quoted;
+      elseif ($context == 'MSGSTR_ARR') {
+        $current['msgstr'][$plural] .= $quoted;
       }
       else {
+        // No valid context to append to.
         _locale_import_message('The translation file %filename contains an error: there is an unexpected string on line %line.', $file, $lineno);
         return FALSE;
       }
     }
   }
 
-  // End of PO file, flush last entry.
-  if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {
+  // End of PO file, closed out the last entry.
+  if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
     _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
   }
-  elseif ($context != "COMMENT") {
+  elseif ($context != 'COMMENT') {
     _locale_import_message('The translation file %filename ended unexpectedly at line %line.', $file, $lineno);
     return FALSE;
   }
-
 }
 
 /**
