Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.210
diff -u -r1.210 locale.inc
--- includes/locale.inc	2 Apr 2009 20:39:44 -0000	1.210
+++ includes/locale.inc	6 Apr 2009 22:56:15 -0000
@@ -2385,6 +2385,7 @@
   }
 
   // Construct the JavaScript file, if there are translations.
+  $data_hash = NULL;
   $data = $status = '';
   if (!empty($translations)) {
 
@@ -2403,22 +2404,23 @@
   $dir = file_create_path(variable_get('locale_js_directory', 'languages'));
 
   // Delete old file, if we have no translations anymore, or a different file to be saved.
-  if (!empty($language->javascript) && (!$data || $language->javascript != $data_hash)) {
+  $changed_hash = $language->javascript != $data_hash;
+  if (!empty($language->javascript) && (!$data || $changed_hash)) {
     file_unmanaged_delete(file_create_path($dir . '/' . $language->language . '_' . $language->javascript . '.js'));
     $language->javascript = '';
     $status = 'deleted';
   }
 
-  // Only create a new file if the content has changed.
-  if ($data && $language->javascript != $data_hash) {
+  // Only create a new file if the content has changed or the original file got lost.
+  $dest = $dir .'/'. $language->language .'_'. $data_hash .'.js';
+  if ($data && ($changed_hash || !file_exists($dest))) {
     // Ensure that the directory exists and is writable, if possible.
     file_check_directory($dir, TRUE);
 
     // Save the file.
-    $dest = $dir . '/' . $language->language . '_' . $data_hash . '.js';
     if (file_unmanaged_save_data($data, $dest)) {
       $language->javascript = $data_hash;
-      $status = ($status == 'deleted') ? 'updated' : 'created';
+      $status = ($status == 'deleted') ? 'updated' : ($changed_hash ? 'created' : 'rebuilt');
     }
     else {
       $language->javascript = '';
@@ -2427,8 +2429,9 @@
   }
 
   // Save the new JavaScript hash (or an empty value if the file
-  // just got deleted). Act only if some operation was executed.
-  if ($status) {
+  // just got deleted). Act only if some operation was executed that 
+  // changed the hash code.
+  if ($status && $changed_hash) {
     db_update('languages')
       ->fields(array(
         'javascript' => $language->javascript,
@@ -2451,6 +2454,9 @@
     case 'updated':
       watchdog('locale', 'Updated JavaScript translation file for the language %language.', array('%language' => t($language->name)));
       return TRUE;
+    case 'rebuilt':
+      watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $language->javascript), WATCHDOG_WARNING);
+      // Let slip through.      
     case 'created':
       watchdog('locale', 'Created JavaScript translation file for the language %language.', array('%language' => t($language->name)));
       return TRUE;
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.22
diff -u -r1.22 locale.test
--- modules/locale/locale.test	1 Apr 2009 20:00:46 -0000	1.22
+++ modules/locale/locale.test	6 Apr 2009 22:56:16 -0000
@@ -305,6 +305,32 @@
     $this->assertNoText($name, t('Search now can not find the name.'));
   }
 
+  function testJavaScriptTranslation() {
+    $user = $this->drupalCreateUser(array('translate interface', 'administer languages', 'access administration pages'));
+    $this->drupalLogin($user);
+    
+    // Add French language.
+    $this->drupalPost('admin/international/language/add', array('langcode' => $langcode = 'fr'), t('Add language'));
+    
+    // Build the JavaScript translation file for French.
+    $this->drupalGet('admin/international/translate/translate');
+    
+    $string = db_fetch_object(db_query('SELECT min(lid) AS lid FROM {locales_source} WHERE location LIKE \'%.js%\' AND textgroup = \'default\''));
+    $edit = array('translations['. $langcode .']' => 'french translation');
+    $this->drupalPost('admin/international/translate/edit/' . $string->lid, $edit, t('Save translations'));
+    locale_inc_callback('_locale_rebuild_js', $langcode);
+    $file = db_fetch_object(db_query('SELECT javascript FROM {languages} WHERE language = \'%s\'', $langcode));
+    $js_file = file_create_path(variable_get('locale_js_directory', 'languages')) . '/'. $langcode .'_' . $file->javascript . '.js';
+    $this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('not found'))));
+            
+    // Test JavaScript translation rebuilding.
+    file_unmanaged_delete($js_file);
+    $this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found'))));
+    cache_clear_all();
+    locale_inc_callback('_locale_rebuild_js', $langcode);
+    $this->assertTrue($result = file_exists($js_file), t('JavaScript file rebuilt: %file', array('%file' => $result ? $js_file : t('not found'))));
+  }
+
   /**
    * Tests the validation of the translation input.
    */
@@ -897,7 +923,7 @@
 
     // Add a new language and optionally set it as default.
     require_once DRUPAL_ROOT . '/includes/locale.inc';
-    locale_add_language('fr', 'French', 'Français', LANGUAGE_LTR, '', '', TRUE, $this->ui_language == 'fr');
+    locale_add_language('fr', 'French', 'FranÃ§ais', LANGUAGE_LTR, '', '', TRUE, $this->ui_language == 'fr');
 
     // Check the UI language.
     drupal_init_language();
