Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.205
diff -u -p -r1.205 locale.inc
--- includes/locale.inc	22 Feb 2009 17:55:29 -0000	1.205
+++ includes/locale.inc	23 Feb 2009 23:02:13 -0000
@@ -2605,6 +2605,8 @@ function locale_batch_by_language($langc
   // Collect all files to import for all enabled modules and themes.
   $files = array();
   $components = array();
+
+  $language_with_fallbacks = _locale_get_language_with_fallbacks($langcode);
   $query = db_select('system', 's');
   $query->fields('s', array('name', 'filename'));
   $query->condition('s.status', 1);
@@ -2613,11 +2615,22 @@ function locale_batch_by_language($langc
   }
   $result = $query->execute();
   foreach ($result as $component) {
-    // Collect all files for all components, names as $langcode.po or
-    // with names ending with $langcode.po. This allows for filenames
-    // like node-module.de.po to let translators use small files and
-    // be able to import in smaller chunks.
-    $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)' . $langcode . '\.po$/', array('recurse' => FALSE)));
+    // Iterate through a language and its potential fallbacks.
+    // We need to do this in order to ensure that the language takes
+    // precedence over its fallback.
+    foreach ($language_with_fallbacks as $language) {
+      // Collect all files for all components, names as $language.po or
+      // with names ending with $language.po. This allows for filenames
+      // like node-module.de.po to let translators use small files and
+      // be able to import in smaller chunks.
+      $new_files = file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)' . $language . '\.po$/', array('recurse' => FALSE));
+      // Whether for the original or a fallback language, the imports
+      // need to be assigned to the original language.
+      foreach (array_keys($new_files) as $key) {
+        $new_files[$key]->langcode = $langcode;
+      }
+      $files = array_merge($files, $new_files);
+    }
     $components[] = $component->name;
   }
 
@@ -2640,16 +2653,32 @@ function locale_batch_by_component($comp
   $languages = language_list('enabled');
   unset($languages[1]['en']);
   if (count($languages[1])) {
-    $language_list = join('|', array_keys($languages[1]));
-    // Collect all files to import for all $components.
-    $result = db_query("SELECT name, filename FROM {system} WHERE status = 1");
-    while ($component = db_fetch_object($result)) {
-      if (in_array($component->name, $components)) {
-        // Collect all files for this component in all enabled languages, named
-        // as $langcode.po or with names ending with $langcode.po. This allows
-        // for filenames like node-module.de.po to let translators use small
-        // files and be able to import in smaller chunks.
-        $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)(' . $language_list . ')\.po$/', array('recurse' => FALSE)));
+    foreach (array_keys($languages[1]) as $langcode) {
+      $language_with_fallbacks = _locale_get_language_with_fallbacks($langcode);
+      // Collect all files to import for all $components.
+      $query = db_select('system', 's');
+      $query->fields('s', array('name', 'filename'));
+      $query->condition('s.status', 1);
+      $result = $query->execute();
+      foreach ($result as $component) {
+        if (in_array($component->name, $components)) {
+          // Iterate through a language and its potential fallbacks.
+          // We need to do this in order to ensure that the language takes
+          // precedence over its fallback.
+          foreach ($language_with_fallbacks as $language) {
+            // Collect all files for this component in all enabled languages, named
+            // as $language.po or with names ending with $language.po. This allows
+            // for filenames like node-module.de.po to let translators use small
+            // files and be able to import in smaller chunks.
+            $new_files = file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)' . $language . '\.po$/', array('recurse' => FALSE));
+            // Whether for the original or a fallback language, the imports
+            // need to be assigned to the original language.
+            foreach (array_keys($new_files) as $key) {
+              $new_files[$key]->langcode = $langcode;
+            }
+            $files = array_merge($files, $new_files);
+          }
+        }
       }
     }
     return _locale_batch_build($files, $finished);
@@ -2675,7 +2704,7 @@ function _locale_batch_build($files, $fi
     $operations = array();
     foreach ($files as $file) {
       // We call _locale_batch_import for every batch operation.
-      $operations[] = array('_locale_batch_import', array($file->filepath));
+      $operations[] = array('_locale_batch_import', array($file->filepath, $file->langcode));
     }
     $batch = array(
       'operations'    => $operations,
@@ -2700,15 +2729,18 @@ function _locale_batch_build($files, $fi
  *
  * @param $filepath
  *   Path to a file to import.
- * @param $results
+ * @param $langcode_override
+ *   A language code to be set to the imported strings. Enables the use
+ *   of language import fallbacks.
+ * @param $context
  *   Contains a list of files imported.
  */
-function _locale_batch_import($filepath, &$context) {
+function _locale_batch_import($filepath, $langcode_override, &$context) {
   // The filename is either {langcode}.po or {prefix}.{langcode}.po, so
   // we can extract the language code to use for the import from the end.
   if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) {
     $file = (object) array('filename' => basename($filepath), 'filepath' => $filepath);
-    _locale_import_read_po('db-store', $file, LOCALE_IMPORT_KEEP, $langcode[2]);
+    _locale_import_read_po('db-store', $file, LOCALE_IMPORT_KEEP, $langcode_override ? $langcode_override : $langcode[2]);
     $context['results'][] = $filepath;
   }
 }
@@ -2734,5 +2766,21 @@ function _locale_batch_language_finished
 }
 
 /**
+ * Return an array of a language and its fallbacks, if any.
+ *
+ * By default, if a language code has more than two digits, the first
+ * two digits are used as a fallback.
+ */
+function _locale_get_language_with_fallbacks($langcode) {
+  $langcodes = array($langcode);
+  if (strlen($langcode) > 2) {
+    $langcodes[] = substr($langcode, 0, 2);
+  }
+  // Allow other modules to alter the language fallbacks.
+  drupal_alter('locale_language_fallbacks', $langcodes, $langcode);
+  return $langcodes;
+}
+
+/**
  * @} End of "locale-autoimport"
  */
