diff --git a/includes/gettext.inc b/includes/gettext.inc
index a3d2a7c..393a42e 100644
--- a/includes/gettext.inc
+++ b/includes/gettext.inc
@@ -387,8 +387,8 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
     case 'db-store':
       // We got header information.
       if ($value['msgid'] == '') {
-        $languages = language_list();
-        if (($mode != LOCALE_IMPORT_KEEP) || empty($languages[$lang]->plurals)) {
+        $locale_plurals = variable_get('locale_translation_plurals', array());
+        if (($mode != LOCALE_IMPORT_KEEP) || empty($locale_plurals[$lang]['plurals'])) {
           // Since we only need to parse the header if we ought to update the
           // plural formula, only run this if we don't need to keep existing
           // data untouched or if we don't have an existing plural formula.
@@ -396,24 +396,17 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
 
           // Get the plural formula and update in database.
           if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->uri)) {
-            list($nplurals, $plural) = $p;
-            db_update('languages')
-              ->fields(array(
-                'plurals' => $nplurals,
-                'formula' => $plural,
-              ))
-              ->condition('language', $lang)
-              ->execute();
+            list($nplurals, $formula) = $p;
           }
           else {
-            db_update('languages')
-              ->fields(array(
-                'plurals' => 0,
-                'formula' => '',
-              ))
-              ->condition('language', $lang)
-              ->execute();
+            $nplurals = 0;
+            $formula = '';
           }
+          $locale_plurals[$lang] = array(
+            'plurals' => $nplurals,
+            'formula' => $formula,
+          );
+          variable_set('locale_translation_plurals', $locale_plurals);
         }
         $header_done = TRUE;
       }
@@ -918,6 +911,8 @@ function _locale_export_get_strings($language = NULL) {
 function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
   global $user;
 
+  $locale_plurals = variable_get('locale_translation_plurals', array());
+
   if (!isset($header)) {
     if (isset($language)) {
       $header = '# ' . $language->name . ' translation of ' . variable_get('site_name', 'Drupal') . "\n";
@@ -933,8 +928,8 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
       $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";
+      if (!empty($locale_plurals[$language->language]['formula'])) {
+        $header .= "\"Plural-Forms: nplurals=" . $locale_plurals[$language->language]['plurals'] . "; plural=" . strtr($locale_plurals[$language->language]['formula'], array('$' => '')) . ";\\n\"\n";
       }
     }
     else {
@@ -972,7 +967,7 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
         $output .= 'msgid_plural ' . _locale_export_string($strings[$plural]['source']);
         if (isset($language)) {
           $translation = $string['translation'];
-          for ($i = 0; $i < $language->plurals; $i++) {
+          for ($i = 0; $i < $locale_plurals[$language->language]['plurals']; $i++) {
             $output .= 'msgstr[' . $i . '] ' . _locale_export_string($translation);
             if ($plural) {
               $translation = _locale_export_remove_plural($strings[$plural]['translation']);
diff --git a/includes/locale.inc b/includes/locale.inc
index 01c35fa..bd82fcd 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -751,8 +751,9 @@ function _locale_rebuild_js($langcode = NULL) {
 
     $data = "Drupal.locale = { ";
 
-    if (!empty($language->formula)) {
-      $data .= "'pluralFormula': function (\$n) { return Number({$language->formula}); }, ";
+    $locale_plurals = variable_get('locale_translation_plurals', array());
+    if (!empty($locale_plurals[$language->language])) {
+      $data .= "'pluralFormula': function (\$n) { return Number({$locale_plurals[$language->language]['formula']}); }, ";
     }
 
     $data .= "'strings': " . drupal_json_encode($translations) . " };";
@@ -764,10 +765,11 @@ function _locale_rebuild_js($langcode = NULL) {
   $dir = 'public://' . variable_get('locale_js_directory', 'languages');
 
   // Delete old file, if we have no translations anymore, or a different file to be saved.
-  $changed_hash = $language->javascript != $data_hash;
-  if (!empty($language->javascript) && (!$data || $changed_hash)) {
-    file_unmanaged_delete($dir . '/' . $language->language . '_' . $language->javascript . '.js');
-    $language->javascript = '';
+  $locale_javascripts = variable_get('locale_translation_javascript', array());
+  $changed_hash = !isset($locale_javascripts[$language->language]) || ($locale_javascripts[$language->language] != $data_hash);
+  if (!empty($locale_javascripts[$language->language]) && (!$data || $changed_hash)) {
+    file_unmanaged_delete($dir . '/' . $language->language . '_' . $locale_javascripts[$language->language] . '.js');
+    $locale_javascripts[$language->language] = '';
     $status = 'deleted';
   }
 
@@ -780,7 +782,7 @@ function _locale_rebuild_js($langcode = NULL) {
 
     // Save the file.
     if (file_unmanaged_save_data($data, $dest)) {
-      $language->javascript = $data_hash;
+      $locale_javascripts[$language->language] = $data_hash;
       // If we deleted a previous version of the file and we replace it with a
       // new one we have an update.
       if ($status == 'deleted') {
@@ -798,7 +800,7 @@ function _locale_rebuild_js($langcode = NULL) {
       }
     }
     else {
-      $language->javascript = '';
+      $locale_javascripts[$language->language] = '';
       $status = 'error';
     }
   }
@@ -807,22 +809,7 @@ function _locale_rebuild_js($langcode = NULL) {
   // 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,
-      ))
-      ->condition('language', $language->language)
-      ->execute();
-
-    // Update the default language variable if the default language has been altered.
-    // This is necessary to keep the variable consistent with the database
-    // version of the language and to prevent checking against an outdated hash.
-    $default_langcode = language_default()->language;
-    drupal_static_reset('language_list');
-    if ($default_langcode == $language->language) {
-      $default = language_load($default_langcode);
-      variable_set('language_default', $default);
-    }
+    variable_set('locale_translation_javascript', $locale_javascripts);
   }
 
   // Log the operation and return success flag.
@@ -831,7 +818,7 @@ function _locale_rebuild_js($langcode = NULL) {
       watchdog('locale', 'Updated JavaScript translation file for the language %language.', array('%language' => $language->name));
       return TRUE;
     case 'rebuilt':
-      watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $language->javascript), WATCHDOG_WARNING);
+      watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $locale_javascripts[$language->language]), WATCHDOG_WARNING);
       // Proceed to the 'created' case as the JavaScript translation file has
       // been created again.
     case 'created':
diff --git a/modules/locale/locale.install b/modules/locale/locale.install
index 6cca4c4..2a317e8 100644
--- a/modules/locale/locale.install
+++ b/modules/locale/locale.install
@@ -22,10 +22,10 @@ function locale_uninstall() {
   $locale_js_directory = 'public://' . variable_get('locale_js_directory', 'languages');
 
   if (is_dir($locale_js_directory)) {
-    $files = db_query('SELECT language, javascript FROM {languages}');
-    foreach ($files as $file) {
-      if (!empty($file->javascript)) {
-        file_unmanaged_delete($locale_js_directory . '/' . $file->language . '_' . $file->javascript . '.js');
+    $locale_javascripts = variable_get('locale_translation_javascript', array());
+    foreach ($locale_javascripts as $langcode => $file_suffix) {
+      if (!empty($file_suffix)) {
+        file_unmanaged_delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
       }
     }
     // Delete the JavaScript translations directory if empty.
@@ -47,6 +47,8 @@ function locale_uninstall() {
   variable_del('javascript_parsed');
   variable_del('locale_field_language_fallback');
   variable_del('locale_cache_length');
+  variable_del('locale_translation_plurals');
+  variable_del('locale_translation_javascript');
 
   foreach (language_types() as $type) {
     variable_del("language_negotiation_$type");
@@ -97,19 +99,6 @@ function locale_schema() {
         'default' => 0,
         'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).',
       ),
-      'plurals' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Number of plural indexes in this language.',
-      ),
-      'formula' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Plural formula in PHP code to evaluate to get plural indexes.',
-      ),
       'domain' => array(
         'type' => 'varchar',
         'length' => 128,
@@ -130,13 +119,6 @@ function locale_schema() {
         'default' => 0,
         'description' => 'Weight, used in lists of languages.',
       ),
-      'javascript' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Location of JavaScript translation file.',
-      ),
     ),
     'primary key' => array('language'),
     'indexes' => array(
@@ -250,6 +232,30 @@ function locale_update_8000() {
 }
 
 /**
+ * Decouple interface translation related data from language objects.
+ */
+function locale_update_8001() {
+  // Gather data from existing languages table and save in variables.
+  $languages = db_query('SELECT * FROM {languages}')->execute();
+  $plurals = array();
+  $javascript = array();
+  foreach ($languages as $language) {
+    $plurals[$language->language] = array(
+      'plurals' => $language->plurals,
+      'formula' => $language->formula,
+    );
+    $javascript[$language->language] = $language->javascript;
+  }
+  variable_set('locale_translation_plurals', $plurals);
+  variable_set('locale_translation_javascript', $javascript);
+
+  // Drop now unneeded columns.
+  db_drop_field('languages', 'plurals');
+  db_drop_field('languages', 'formula');
+  db_drop_field('languages', 'javascript');
+}
+
+/**
  * @} End of "addtogroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
  */
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 9eab429..777b76b 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -722,19 +722,18 @@ function locale_reset() {
  */
 function locale_get_plural($count, $langcode = NULL) {
   global $language;
-  $locale_formula = &drupal_static(__FUNCTION__, array());
+  $locale_plurals = &drupal_static(__FUNCTION__, array());
   $plurals = &drupal_static(__FUNCTION__ . ':plurals', array());
 
   $langcode = $langcode ? $langcode : $language->language;
 
   if (!isset($plurals[$langcode][$count])) {
-    if (empty($locale_formula)) {
-      $language_list = language_list();
-      $locale_formula[$langcode] = $language_list[$langcode]->formula;
+    if (empty($locale_plural_formulas)) {
+      $locale_plurals = variable_get('locale_translation_plurals', array());
     }
-    if ($locale_formula[$langcode]) {
+    if (!empty($locale_plurals[$langcode])) {
       $n = $count;
-      $plurals[$langcode][$count] = @eval('return intval(' . $locale_formula[$langcode] . ');');
+      $plurals[$langcode][$count] = @eval('return intval(' . $locale_plurals[$langcode]['formula'] . ');');
       return $plurals[$langcode][$count];
     }
     else {
@@ -916,9 +915,10 @@ function locale_js_alter(&$javascript) {
   }
 
   // Add the translation JavaScript file to the page.
-  if ($files && !empty($language->javascript)) {
+  $locale_javascripts = variable_get('locale_translation_javascript', array());
+  if ($files && !empty($locale_javascripts[$language->language])) {
     // Add the translation JavaScript file to the page.
-    $file = $dir . '/' . $language->language . '_' . $language->javascript . '.js';
+    $file = $dir . '/' . $language->language . '_' . $locale_javascripts[$language->language] . '.js';
     $javascript[$file] = drupal_js_defaults($file);
   }
 }
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index fa19eb3..e70d44f 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -483,14 +483,8 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
     require_once DRUPAL_ROOT . '/includes/locale.inc';
     _locale_rebuild_js($langcode);
 
-    // Retrieve the JavaScript translation hash code for the custom language to
-    // check that the translation file has been properly built.
-    $file = db_select('languages', 'l')
-      ->fields('l', array('javascript'))
-      ->condition('language', $langcode)
-      ->execute()
-      ->fetchObject();
-    $js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/' . $langcode . '_' . $file->javascript . '.js';
+    $locale_javascripts = variable_get('locale_translation_javascript', array());
+    $js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/' . $langcode . '_' . $locale_javascripts[$langcode] . '.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.
@@ -740,7 +734,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 9, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
 
     // This import should have saved plural forms to have 2 variants.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural number initialized.'));
+    $locale_plurals = variable_get('locale_translation_plurals', array());
+    $this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural number initialized.'));
 
     // Ensure we were redirected correctly.
     $this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
@@ -786,7 +781,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
 
     // This import should not have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural numbers untouched.'));
+    $locale_plurals = variable_get('locale_translation_plurals', array());
+    $this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural numbers untouched.'));
 
     // Try importing a .po file with overriding strings, and ensure existing
     // strings are overwritten.
@@ -806,7 +802,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
     // This import should have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 3, t('Plural numbers changed.'));
+    $locale_plurals = variable_get('locale_translation_plurals', array());
+    $this->assert($locale_plurals['fr']['plurals'] == 3, t('Plural numbers changed.'));
   }
 
   /**
@@ -1230,8 +1227,8 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
     $edit = array('translations[fr]' => 'french translation');
     $this->drupalPost('admin/config/regional/translate/edit/' . $string->lid, $edit, t('Save translations'));
     _locale_rebuild_js('fr');
-    $file = db_query('SELECT javascript FROM {languages} WHERE language = :language', array(':language' => 'fr'))->fetchObject();
-    $js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $file->javascript . '.js';
+    $locale_javascripts = variable_get('locale_translation_javascript', array());
+    $js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $locale_javascripts['fr'] . '.js';
     $this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('none'))));
 
     // Disable string caching.
