diff --git a/redirect.admin.inc b/redirect.admin.inc
index 176f105..dae552e 100644
--- a/redirect.admin.inc
+++ b/redirect.admin.inc
@@ -624,6 +624,12 @@ function redirect_settings_form($form, &$form_state) {
     '#description' => t('This feature requires <a href="@performance">Cache pages for anonymous users</a> to be enabled and the %variable variable to be TRUE.', array('@performance' => url('admin/config/development/performance'), '%variable' => "\$conf['page_cache_invoke_hooks']")),
     '#disabled' => !variable_get('cache', 0) || !variable_get('page_cache_invoke_hooks', TRUE),
   );
+  $form['redirect_error_log'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Log 404 errors.'),
+    '#default_value' => variable_get('redirect_error_log', TRUE),
+    '#description' => t('In case you directly import 404 errors from the webserver, you need to disable logging to avoid duplicates.'),
+  );
   $form['redirect_purge_inactive'] = array(
     '#type' => 'select',
     '#title' => t('Delete redirects that have not been accessed for'),
@@ -682,6 +688,9 @@ function redirect_settings_form_submit($form, &$form_state) {
   redirect_page_cache_clear();
 }
 
+/**
+ * List all 404 errors.
+ */
 function redirect_404_list($form = NULL) {
   $destination = drupal_get_destination();
 
@@ -691,47 +700,62 @@ function redirect_404_list($form = NULL) {
   $keys = implode('/', $keys);
   $build['redirect_list_404_filter_form'] = drupal_get_form('redirect_list_404_filter_form', $keys);
 
+  $languages = language_list('enabled');
+  $multilanguage = count($languages['1']) > 1;
+
   $header = array(
     array('data' => t('Page'), 'field' => 'message'),
     array('data' => t('Count'), 'field' => 'count', 'sort' => 'desc'),
     array('data' => t('Last accessed'), 'field' => 'timestamp'),
-    array('data' => t('Operations')),
   );
+  if ($multilanguage) {
+    $header[] = array('data' => t('Language'), 'field' => 'language');
+  }
+  $header[] = array('data' => t('Operations'));
 
-  $count_query = db_select('watchdog', 'w');
-  $count_query->addExpression('COUNT(DISTINCT(w.message))');
-  $count_query->leftJoin('redirect', 'r', 'w.message = r.source');
-  $count_query->condition('w.type', 'page not found');
+  $count_query = db_select('redirect_error', 're');
+  $count_query->addExpression('COUNT(DISTINCT(re.source))');
+  $count_query->leftJoin('redirect', 'r', 're.source = r.source');
   $count_query->isNull('r.rid');
-  redirect_build_filter_query($count_query, array('w.message'), $keys);
+  redirect_build_filter_query($count_query, array('re.source'), $keys);
 
-  $query = db_select('watchdog', 'w')->extend('PagerDefault')->extend('TableSort');
-  $query->fields('w', array('message'));
-  $query->addExpression('COUNT(wid)', 'count');
+  $query = db_select('redirect_error', 're')->extend('PagerDefault')->extend('TableSort');
+  $query->fields('re', array('source', 'language'));
+  $query->addExpression('COUNT(reid)', 'count');
   $query->addExpression('MAX(timestamp)', 'timestamp');
-  $query->leftJoin('redirect', 'r', 'w.message = r.source');
+  $query->leftJoin('redirect', 'r', 're.source = r.source');
   $query->isNull('r.rid');
-  $query->condition('w.type', 'page not found');
-  $query->groupBy('w.message');
+  $query->groupBy('re.source');
   $query->orderByHeader($header);
   $query->limit(25);
-  redirect_build_filter_query($query, array('w.message'), $keys);
+  redirect_build_filter_query($query, array('re.source'), $keys);
   $query->setCountQuery($count_query);
   $results = $query->execute();
 
   $rows = array();
   foreach ($results as $result) {
     $row = array();
-    $row['source'] = l($result->message, $result->message, array('query' => $destination));
+    $row['source'] = l($result->source, $result->source, array('query' => $destination));
     $row['count'] = $result->count;
     $row['timestamp'] = format_date($result->timestamp, 'short');
+    if ($multilanguage) {
+      //$row['language'] = $result->language;
+      $row['language'] = $result->language;
+      if ($result->language == '' || isset($languages[$result->language])) {
+        $row['language'] = $result->language == '' ? t('Language neutral') : t($languages[$result->language]->name);
+      }
+      else {
+        $row['language'] = t('Undefined language (@langcode)', array('@langcode' => $result->language));
+      }
+    }
 
     $operations = array();
     if (redirect_access('create', 'redirect')) {
       $operations['add'] = array(
         'title' => t('Add redirect'),
         'href' => 'admin/config/search/redirect/add/',
-        'query' => array('source' => $result->message) + $destination,
+        // @todo add language here!
+        'query' => array('source' => $result->source) + $destination,
       );
     }
     $row['operations'] = array(
diff --git a/redirect.install b/redirect.install
index fa67aaa..d12ef41 100644
--- a/redirect.install
+++ b/redirect.install
@@ -98,6 +98,47 @@ function redirect_schema() {
       'source_language' => array('source', 'language'),
     ),
   );
+  $schema['redirect_error'] =  array(
+    'description' => 'Stores information on redirect errors.',
+    'fields' => array(
+      'reid'  => array(
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => 'Primary Key: Unique redirect error ID.',
+      ),
+      'source' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'description' => 'The source path where the error happened.',
+      ),
+      'uid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The {users}.uid of the user who created the error.',
+      ),
+      'language' => array(
+        'description' => 'The language this error is for; if blank, language is undefined',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => 'und',
+      ),
+      'timestamp' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The timestamp of when the error was created.'
+      ),
+    ),
+    'primary key' => array('reid'),
+    'indexes' => array(
+      'source_language' => array('source', 'language'),
+    ),
+  );
 
   return $schema;
 }
@@ -356,3 +397,53 @@ function _redirect_migrate_path_redirect_variables() {
     variable_del($old_variable);
   }
 }
+
+/**
+ * Add redirect_error table.
+ */
+function redirect_update_7001(&$sandbox) {
+  $schema = array(
+    'description' => 'Stores information on redirect errors.',
+    'fields' => array(
+      'reid'  => array(
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => 'Primary Key: Unique redirect error ID.',
+      ),
+      'source' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'description' => 'The source path where the error happened.',
+      ),
+      'uid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The {users}.uid of the user who created the error.',
+      ),
+      'language' => array(
+        'description' => 'The language this error is for; if blank, language is undefined',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => 'und',
+      ),
+      'timestamp' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The timestamp of when the error was created.'
+      ),
+    ),
+    'primary key' => array('reid'),
+    'indexes' => array(
+      'source_language' => array('source', 'language'),
+    ),
+  );
+  db_create_table('redirect_error', $schema);
+
+  // We don't do any data migration as watchdog records are volatile.
+}
diff --git a/redirect.module b/redirect.module
index 8c47b75..b1572ba 100644
--- a/redirect.module
+++ b/redirect.module
@@ -1565,3 +1565,41 @@ function redirect_redirect_operations() {
   );
   return $operations;
 }
+
+/**
+ * Implements hook_watchdog.
+ *
+ * Write a redirect_error per 404.
+ */
+function redirect_watchdog(array $log_entry) {
+  if ($log_entry['type'] == 'page not found') {
+    if (!variable_get('redirect_error_log', TRUE)) {
+      return;
+    }
+    global $user;
+    global $language;
+    $langcode = $language->language;
+    if (module_exists('locale')) {
+      require_once DRUPAL_ROOT . '/includes/language.inc';
+      module_load_include('locale.inc', 'locale');
+      // Fetch language from URL.
+      $languages = language_list();
+      // We need a workaround for language negotiation as the language is already cutoff from $_GET['q'].
+      $saveq = $_GET['q'];
+      $_GET['q'] = request_path();
+      $url_langcode  = locale_language_from_url($languages);
+      $langcode = $url_langcode===FALSE?'':$url_langcode;
+      $_GET['q'] = $saveq;
+    }
+    // Write record.
+    $record = array(
+      'source' => $log_entry['message'],
+      'uid' => $user->uid,
+      // @todo fix for cases where language prefix is missing.
+      'language' => $langcode,
+      'status_code' => '404',
+      'timestamp' => $log_entry['timestamp'],
+    );
+    drupal_write_record('redirect_error', $record);
+  }
+}
diff --git a/redirect.test b/redirect.test
index 1c237f8..fc74555 100644
--- a/redirect.test
+++ b/redirect.test
@@ -181,6 +181,13 @@ class RedirectFunctionalTest extends RedirectTestHelper {
     $this->drupalLogout();
     $this->drupalGet('invalid-path3');
     $this->assertNoLink('Add an URL redirect from this page to another location');
+
+    // @todo check if the record is in redirect_error table.
+    // @todo check if it is listed in the admin/config/search/redirect/404.
+    // @todo check that counter increases / counts right.
+    // @todo add one language / check.
+    // @todo check if the language is shown on list.
+    // @todo add language neutral callback / check neutral col.
   }
 
   function testPageCache() {
