diff --git a/core/includes/gettext.inc b/core/includes/gettext.inc
index 95e84cf..951e2ec 100644
--- a/core/includes/gettext.inc
+++ b/core/includes/gettext.inc
@@ -499,6 +499,7 @@ function _locale_import_one_string_db(&$report, $langcode, $context, $source, $t
             'translation' => $translation,
             'plid' => $plid,
             'plural' => $plural,
+            'override' => LOCALE_TARGET_DEFAULT,
           ))
           ->execute();
 
@@ -511,6 +512,7 @@ function _locale_import_one_string_db(&$report, $langcode, $context, $source, $t
             'translation' => $translation,
             'plid' => $plid,
             'plural' => $plural,
+            'override' => LOCALE_TARGET_DEFAULT,
           ))
           ->condition('language', $langcode)
           ->condition('lid', $lid)
@@ -535,7 +537,8 @@ function _locale_import_one_string_db(&$report, $langcode, $context, $source, $t
            'language' => $langcode,
            'translation' => $translation,
            'plid' => $plid,
-           'plural' => $plural
+           'plural' => $plural,
+           'override' => LOCALE_TARGET_DEFAULT,
         ))
         ->execute();
 
@@ -866,13 +869,23 @@ function _locale_import_parse_quoted($string) {
  * @param $language
  *   Language object to generate the output for, or NULL if generating
  *   translation template.
+ * @param $override
+ *   Override status of translation strings; if not NULL, only translations
+ *   with this status (LOCALE_TARGET_DEFAULT / LOCALE_TARGET_CUSTOM) will be
+ *   exported. Ignored if $language is NULL.
  *
  * @return
  *   An array of translated strings that can be used to generate an export.
  */
-function _locale_export_get_strings($language = NULL) {
+function _locale_export_get_strings($language = NULL, $override = NULL) {
   if (isset($language)) {
-    $result = db_query("SELECT s.lid, s.source, s.context, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language ORDER BY t.plid, t.plural", array(':language' => $language->langcode));
+    $where = 't.language = :language';
+    $args = array(':language' => $language->langcode);
+    if (isset($override)) {
+      $where .= ' AND override = :override';
+      $args[':override'] = $override;
+    }
+    $result = db_query("SELECT s.lid, s.source, s.context, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND " . $where . " ORDER BY t.plid, t.plural", $args);
   }
   else {
     $result = db_query("SELECT s.lid, s.source, s.context, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid ORDER BY t.plid, t.plural");
diff --git a/core/includes/locale.inc b/core/includes/locale.inc
index 8a381ed..9baf918 100644
--- a/core/includes/locale.inc
+++ b/core/includes/locale.inc
@@ -73,6 +73,16 @@ define('LOCALE_JS_OBJECT_CONTEXT', '
 ');
 
 /**
+ * 'default translation' as provided by Drupal translation service.
+ */
+const LOCALE_TARGET_DEFAULT = 0;
+
+/**
+ * 'custom translation' e.g. provided by user through UI / custom .po file.
+ */
+const LOCALE_TARGET_CUSTOM = 1;
+
+/**
  * Translation import mode overwriting all existing translations
  * if new translated version available.
  */
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index a4982e1..fe05d9c 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -145,6 +145,17 @@ function locale_translate_export_po_form($form, &$form_state, $names) {
     '#options' => $names,
     '#description' => t('Select the language to export in Gettext Portable Object (<em>.po</em>) format.'),
   );
+  $form['override'] = array('#type' => 'select',
+    '#title' => t('Translation status'),
+    '#options' => array(
+      'translated' => t('Translated strings'),
+      'translated_default' => t('Translated strings, default translation'),
+      'translated_custom' => t('Translated strings, custom translation'),
+    ),
+    '#default_value' => 'translated',
+    '#description' => t('Select the kind of translations to export. For other kinds, strings will be exported without translation.'),
+  );
+
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Export'));
   return $form;
@@ -172,11 +183,15 @@ function locale_translate_export_pot_form() {
 function locale_translate_export_po_form_submit($form, &$form_state) {
   // If template is required, language code is not given.
   $language = NULL;
+  $override = NULL;
   if (isset($form_state['values']['langcode'])) {
     $languages = language_list();
     $language = $languages[$form_state['values']['langcode']];
+    if ($form_state['values']['override'] != 'translated') {
+      $override = $form_state['values']['override'] == 'translated_default' ? LOCALE_TARGET_DEFAULT : LOCALE_TARGET_CUSTOM;
+    }
   }
-  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language)));
+  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $override)));
 }
 
 /**
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index a75ee2e..90164e7 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -188,6 +188,11 @@ function locale_schema() {
         'default' => 0,
         'description' => 'Plural index number in case of plural strings.',
       ),
+      'status' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0, // LOCALE_TARGET_DEFAULT
+      ),
     ),
     'primary key' => array('language', 'lid', 'plural'),
     'foreign keys' => array(
@@ -275,6 +280,25 @@ function locale_update_8001() {
 }
 
 /**
+ * Add override column to locales_target.
+ */
+function locale_update_8002() {
+  $spec = array(
+    'type' => 'int',
+    'not null' => TRUE,
+    'default' => 0, // LOCALE_TARGET_DEFAULT
+  );
+  db_add_field('locales_target', 'override', $spec);
+
+  // If l10n_update module is installed copy its status data.
+  if (db_field_exists('locales_target', 'l10n_status')) {
+    db_update('locales_target')
+      ->expression('override', 'l10n_status')
+      ->execute();
+  }
+}
+
+/**
  * @} End of "addtogroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index e41bae5..670a2ff 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -36,10 +36,15 @@ function _locale_translate_seek() {
   $sql_query = db_select('locales_source', 's');
   $sql_query->leftJoin('locales_target', 't', 't.lid = s.lid');
   $sql_query->fields('s', array('source', 'location', 'context', 'lid'));
-  $sql_query->fields('t', array('translation', 'language'));
+  $sql_query->fields('t', array('translation', 'language', 'override'));
 
   // Compute LIKE section.
   switch ($query['translation']) {
+    case 'translated_custom':
+    case 'translated_default':
+      $sql_query->condition('t.override',
+        $query['translation'] == 'translated_custom' ? LOCALE_TARGET_CUSTOM : LOCALE_TARGET_DEFAULT, '=');
+      // No break!
     case 'translated':
       $sql_query->condition('t.translation', '%' . db_like($query['string']) . '%', 'LIKE');
       $sql_query->orderBy('t.translation', 'DESC');
@@ -172,7 +177,13 @@ function locale_translation_filters() {
 
   $filters['translation'] = array(
     'title' => t('Search in'),
-    'options' => array('all' => t('Both translated and untranslated strings'), 'translated' => t('Only translated strings'), 'untranslated' => t('Only untranslated strings')),
+    'options' => array(
+      'all' => t('Both translated and untranslated strings'),
+      'translated' => t('Translated strings'),
+      'translated_default' => t('Translated strings, default translation'),
+      'translated_custom' => t('Translated strings, custom translation'),
+      'untranslated' => t('Untranslated strings')
+    ),
   );
 
   return $filters;
@@ -353,21 +364,23 @@ function locale_translate_edit_form_submit($form, &$form_state) {
     $translation = db_query("SELECT translation FROM {locales_target} WHERE lid = :lid AND language = :language", array(':lid' => $lid, ':language' => $key))->fetchField();
     if (!empty($value)) {
       // Only update or insert if we have a value to use.
-      if (!empty($translation)) {
+      if (!empty($translation) && $translation != $value) {
         db_update('locales_target')
           ->fields(array(
             'translation' => $value,
+            'override' => LOCALE_TARGET_CUSTOM,
           ))
           ->condition('lid', $lid)
           ->condition('language', $key)
           ->execute();
       }
-      else {
+      if (empty($translation)) {
         db_insert('locales_target')
           ->fields(array(
             'lid' => $lid,
             'translation' => $value,
             'language' => $key,
+            'override' => LOCALE_TARGET_CUSTOM,
           ))
           ->execute();
       }
