diff --git a/includes/locale.inc b/includes/locale.inc
index d0b11f8..780459b 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -522,11 +522,8 @@ function locale_add_language($langcode, $name = NULL, $native = NULL, $direction
  * @param $mode
  *   Should existing translations be replaced LOCALE_IMPORT_KEEP or
  *   LOCALE_IMPORT_OVERWRITE.
- * @param $group
- *   Text group to import PO file into (eg. 'default' for interface
- *   translations).
  */
-function _locale_import_po($file, $langcode, $mode, $group = NULL) {
+function _locale_import_po($file, $langcode, $mode) {
   // Try to allocate enough time to parse and import the data.
   drupal_set_time_limit(240);
 
@@ -537,7 +534,7 @@ function _locale_import_po($file, $langcode, $mode, $group = NULL) {
   }
 
   // Get strings from file (returns on failure after a partial import, or on success)
-  $status = _locale_import_read_po('db-store', $file, $mode, $langcode, $group);
+  $status = _locale_import_read_po('db-store', $file, $mode, $langcode);
   if ($status === FALSE) {
     // Error messages are set in _locale_import_read_po().
     return FALSE;
@@ -579,11 +576,8 @@ function _locale_import_po($file, $langcode, $mode, $group = NULL) {
  *   LOCALE_IMPORT_OVERWRITE.
  * @param $lang
  *   Language code.
- * @param $group
- *   Text group to import PO file into (eg. 'default' for interface
- *   translations).
  */
-function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
+function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL) {
 
   // The file will get closed by PHP on returning from this function.
   $fd = fopen($file->uri, 'rb');
@@ -635,7 +629,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
       }
       elseif (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
         // We are currently in string token, close it out.
-        _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+        _locale_import_one_string($op, $current, $mode, $lang, $file);
 
         // Start a new entry for the comment.
         $current         = array();
@@ -679,7 +673,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
 
       if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
         // We are currently in a message string, close it out.
-        _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+        _locale_import_one_string($op, $current, $mode, $lang, $file);
 
         // Start a new context for the id.
         $current = array();
@@ -709,7 +703,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
 
       if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
         // We are currently in a message, start a new one.
-        _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+        _locale_import_one_string($op, $current, $mode, $lang, $file);
         $current = array();
       }
       elseif (!empty($current['msgctxt'])) {
@@ -823,7 +817,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
 
   // End of PO file, closed out the last entry.
   if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
-    _locale_import_one_string($op, $current, $mode, $lang, $file, $group);
+    _locale_import_one_string($op, $current, $mode, $lang, $file);
   }
   elseif ($context != 'COMMENT') {
     _locale_import_message('The translation file %filename ended unexpectedly at line %line.', $file, $lineno);
@@ -865,11 +859,8 @@ function _locale_import_message($message, $file, $lineno = NULL) {
  * @param $file
  *   Object representation of file being imported, only required when op is
  *   'db-store'.
- * @param $group
- *   Text group to import PO file into (eg. 'default' for interface
- *   translations).
  */
-function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NULL, $file = NULL, $group = 'default') {
+function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NULL, $file = NULL) {
   $report = &drupal_static(__FUNCTION__, array('additions' => 0, 'updates' => 0, 'deletes' => 0, 'skips' => 0));
   $header_done = &drupal_static(__FUNCTION__ . ':header_done', FALSE);
   $strings = &drupal_static(__FUNCTION__ . ':strings', array());
@@ -940,7 +931,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
             if ($key == 0) {
               $plid = 0;
             }
-            $plid = _locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english[$key], $trans, $group, $comments, $mode, $plid, $key);
+            $plid = _locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english[$key], $trans, $comments, $mode, $plid, $key);
           }
         }
 
@@ -948,7 +939,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
           // A simple string to import.
           $english = $value['msgid'];
           $translation = $value['msgstr'];
-          _locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english, $translation, $group, $comments, $mode);
+          _locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english, $translation, $comments, $mode);
         }
       }
   } // end of db-store operation
@@ -968,8 +959,6 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
  *   Source string.
  * @param $translation
  *   Translation to language specified in $langcode.
- * @param $textgroup
- *   Name of textgroup to store translation in.
  * @param $location
  *   Location value to save with source string.
  * @param $mode
@@ -982,14 +971,12 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
  * @return
  *   The string ID of the existing string modified or the new string added.
  */
-function _locale_import_one_string_db(&$report, $langcode, $context, $source, $translation, $textgroup, $location, $mode, $plid = 0, $plural = 0) {
-  $lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = :context AND textgroup = :textgroup", array(':source' => $source, ':context' => $context, ':textgroup' => $textgroup))->fetchField();
+function _locale_import_one_string_db(&$report, $langcode, $context, $source, $translation, $location, $mode, $plid = 0, $plural = 0) {
+  $lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = :context", array(':source' => $source, ':context' => $context))->fetchField();
 
   if (!empty($translation)) {
     // Skip this string unless it passes a check for dangerous code.
-    // Text groups other than default still can contain HTML tags
-    // (i.e. translatable blocks).
-    if ($textgroup == "default" && !locale_string_is_safe($translation)) {
+    if (!locale_string_is_safe($translation)) {
       $report['skips']++;
       $lid = 0;
     }
@@ -1040,7 +1027,6 @@ function _locale_import_one_string_db(&$report, $langcode, $context, $source, $t
           'location' => $location,
           'source' => $source,
           'context' => (string) $context,
-          'textgroup' => $textgroup,
         ))
         ->execute();
 
@@ -1413,7 +1399,7 @@ function _locale_parse_js_file($filepath) {
       // Remove the quotes and string concatenations from the string.
       $string = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($string, 1, -1)));
 
-      $source = db_query("SELECT lid, location FROM {locales_source} WHERE source = :source AND textgroup = 'default'", array(':source' => $string))->fetchObject();
+      $source = db_query("SELECT lid, location FROM {locales_source} WHERE source = :source", array(':source' => $string))->fetchObject();
       if ($source) {
         // We already have this source string and now have to add the location
         // to the location column, if this file is not yet present in there.
@@ -1439,7 +1425,6 @@ function _locale_parse_js_file($filepath) {
             'location' => $filepath,
             'source' => $string,
             'context' => '',
-            'textgroup' => 'default',
           ))
           ->execute();
       }
@@ -1460,16 +1445,13 @@ function _locale_parse_js_file($filepath) {
  * @param $language
  *   Language object to generate the output for, or NULL if generating
  *   translation template.
- * @param $group
- *   Text group to export PO file from (eg. 'default' for interface
- *   translations).
  */
-function _locale_export_get_strings($language = NULL, $group = 'default') {
+function _locale_export_get_strings($language = 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 WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':language' => $language->language, ':textgroup' => $group));
+    $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->language));
   }
   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 WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':textgroup' => $group));
+    $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");
   }
   $strings = array();
   foreach ($result as $child) {
@@ -1740,7 +1722,7 @@ function _locale_rebuild_js($langcode = NULL) {
 
   // Construct the array for JavaScript translations.
   // Only add strings with a translation to the translations array.
-  $result = db_query("SELECT s.lid, s.source, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE '%.js%' AND s.textgroup = :textgroup", array(':language' => $language->language, ':textgroup' => 'default'));
+  $result = db_query("SELECT s.lid, s.source, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE '%.js%'", array(':language' => $language->language));
 
   $translations = array();
   foreach ($result as $data) {
diff --git a/modules/locale/locale.admin.inc b/modules/locale/locale.admin.inc
index ad7a583..8a4e71f 100644
--- a/modules/locale/locale.admin.inc
+++ b/modules/locale/locale.admin.inc
@@ -779,12 +779,6 @@ function locale_translate_import_form($form) {
     '#default_value' => $default,
     '#description' => t('Choose the language you want to add strings into. If you choose a language which is not yet set up, it will be added.'),
   );
-  $form['import']['group'] = array('#type' => 'radios',
-    '#title' => t('Text group'),
-    '#default_value' => 'default',
-    '#options' => module_invoke_all('locale', 'groups'),
-    '#description' => t('Imported translations will be added to this text group.'),
-  );
   $form['import']['mode'] = array('#type' => 'radios',
     '#title' => t('Mode'),
     '#default_value' => LOCALE_IMPORT_KEEP,
@@ -818,7 +812,7 @@ function locale_translate_import_form_submit($form, &$form_state) {
     }
 
     // Now import strings into the language
-    if ($return = _locale_import_po($file, $langcode, $form_state['values']['mode'], $form_state['values']['group']) == FALSE) {
+    if ($return = _locale_import_po($file, $langcode, $form_state['values']['mode']) == FALSE) {
       $variables = array('%filename' => $file->filename);
       drupal_set_message(t('The translation import of %filename failed.', $variables), 'error');
       watchdog('locale', 'The translation import of %filename failed.', $variables, WATCHDOG_ERROR);
@@ -868,11 +862,6 @@ 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['group'] = array('#type' => 'radios',
-    '#title' => t('Text group'),
-    '#default_value' => 'default',
-    '#options' => module_invoke_all('locale', 'groups'),
-  );
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Export'));
   return $form;
@@ -887,11 +876,6 @@ function locale_translate_export_pot_form() {
     '#title' => t('Export template'),
     '#description' => t('Generate a Gettext Portable Object Template (<em>.pot</em>) file with all strings from the Drupal locale database.'),
   );
-  $form['group'] = array('#type' => 'radios',
-    '#title' => t('Text group'),
-    '#default_value' => 'default',
-    '#options' => module_invoke_all('locale', 'groups'),
-  );
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Export'));
   // Reuse PO export submission callback.
@@ -909,7 +893,7 @@ function locale_translate_export_po_form_submit($form, &$form_state) {
     $languages = language_list();
     $language = $languages[$form_state['values']['langcode']];
   }
-  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $form_state['values']['group'])));
+  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language)));
 }
 
 /**
diff --git a/modules/locale/locale.api.php b/modules/locale/locale.api.php
index 2808f33..e327401 100644
--- a/modules/locale/locale.api.php
+++ b/modules/locale/locale.api.php
@@ -11,19 +11,6 @@
  */
 
 /**
- * Allows modules to define their own text groups that can be translated.
- *
- * @param $op
- *   Type of operation. Currently, only supports 'groups'.
- */
-function hook_locale($op = 'groups') {
-  switch ($op) {
-    case 'groups':
-      return array('custom' => t('Custom'));
-  }
-}
-
-/**
  * Allows modules to act after language initialization has been performed.
  *
  * This is primarily needed to provide translation for configuration variables
diff --git a/modules/locale/locale.install b/modules/locale/locale.install
index a144813..7fbc81d 100644
--- a/modules/locale/locale.install
+++ b/modules/locale/locale.install
@@ -177,13 +177,6 @@ function locale_schema() {
         'size' => 'big',
         'description' => 'Drupal path in case of online discovered translations or file path in case of imported strings.',
       ),
-      'textgroup' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => 'default',
-        'description' => 'A module defined group of translations, see hook_locale().',
-      ),
       'source' => array(
         'type' => 'text',
         'mysql_type' => 'blob',
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 871048b..da8ad13 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -48,8 +48,7 @@ function locale_help($path, $arg) {
       $output = '<p>' . t('Determine the language from a request/session parameter. Example: "http://example.com?language=de" sets language to German based on the use of "de" within the "language" parameter.') . '</p>';
       return $output;
     case 'admin/config/regional/translate':
-      $output = '<p>' . t('This page provides an overview of available translatable strings. Drupal displays translatable strings in text groups; modules may define additional text groups containing other translatable strings. Because text groups provide a method of grouping related strings, they are often used to focus translation efforts on specific areas of the Drupal interface.') . '</p>';
-      $output .= '<p>' . t('See the <a href="@languages">Languages page</a> for more information on adding support for additional languages.', array('@languages' => url('admin/config/regional/language'))) . '</p>';
+      $output = '<p>' . t('This page provides an overview of available translatable strings. See the <a href="@languages">Languages page</a> for more information on adding support for additional languages.', array('@languages' => url('admin/config/regional/language'))) . '</p>';
       return $output;
     case 'admin/config/regional/translate/import':
       $output = '<p>' . t('This page imports the translated strings contained in an individual Gettext Portable Object (<em>.po</em>) file. Normally distributed as part of a translation package (each translation package may contain several <em>.po</em> files), a <em>.po</em> file may need to be imported after offline editing in a Gettext translation editor. Importing an individual <em>.po</em> file may be a lengthy process.') . '</p>';
@@ -58,7 +57,7 @@ function locale_help($path, $arg) {
     case 'admin/config/regional/translate/export':
       return '<p>' . t('This page exports the translated strings used by your site. An export file may be in Gettext Portable Object (<em>.po</em>) form, which includes both the original string and the translation (used to share translations with others), or in Gettext Portable Object Template (<em>.pot</em>) form, which includes the original strings only (used to create new translations with a Gettext translation editor).') . '</p>';
     case 'admin/config/regional/translate/translate':
-      return '<p>' . t('This page allows a translator to search for specific translated and untranslated strings, and is used when creating or editing translations. (Note: For translation tasks involving many strings, it may be more convenient to <a href="@export">export</a> strings for offline editing in a desktop Gettext translation editor.) Searches may be limited to strings found within a specific text group or in a specific language.', array('@export' => url('admin/config/regional/translate/export'))) . '</p>';
+      return '<p>' . t('This page allows a translator to search for specific translated and untranslated strings, and is used when creating or editing translations. (Note: For translation tasks involving many strings, it may be more convenient to <a href="@export">export</a> strings for offline editing in a desktop Gettext translation editor.) Searches may be limited to strings in a specific language.', array('@export' => url('admin/config/regional/translate/export'))) . '</p>';
     case 'admin/structure/block/manage/%/%':
       if ($arg[4] == 'locale' && $arg[5] == 'language') {
         return '<p>' . t('This block is only shown if <a href="@languages">at least two languages are enabled</a> and <a href="@configuration">language negotiation</a> is set to <em>URL</em> or <em>Session</em>.', array('@languages' => url('admin/config/regional/language'), '@configuration' => url('admin/config/regional/language/configure'))) . '</p>';
@@ -258,16 +257,6 @@ function locale_permission() {
 }
 
 /**
- * Implements hook_locale().
- */
-function locale_locale($op = 'groups') {
-  switch ($op) {
-    case 'groups':
-      return array('default' => t('Built-in interface'));
-  }
-}
-
-/**
  * Form builder callback to display language selection widget.
  *
  * @ingroup forms
@@ -655,7 +644,7 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
         // Refresh database stored cache of translations for given language.
         // We only store short strings used in current version, to improve
         // performance and consume less memory.
-        $result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = 'default' AND s.version = :version AND LENGTH(s.source) < :length", array(':language' => $langcode, ':version' => VERSION, ':length' => variable_get('locale_cache_length', 75)));
+        $result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.version = :version AND LENGTH(s.source) < :length", array(':language' => $langcode, ':version' => VERSION, ':length' => variable_get('locale_cache_length', 75)));
         foreach ($result as $data) {
           $locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
         }
@@ -669,7 +658,7 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
   if (!isset($locale_t[$langcode][$context][$string])) {
 
     // We do not have this translation cached, so get it from the DB.
-    $translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default'", array(
+    $translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context", array(
       ':language' => $langcode,
       ':source' => $string,
       ':context' => (string) $context,
@@ -697,7 +686,6 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
           'location' => request_uri(),
           'source' => $string,
           'context' => (string) $context,
-          'textgroup' => 'default',
           'version' => VERSION,
         ))
         ->execute();
diff --git a/modules/locale/locale.pages.inc b/modules/locale/locale.pages.inc
index b4ccb6b..45816b9 100644
--- a/modules/locale/locale.pages.inc
+++ b/modules/locale/locale.pages.inc
@@ -1,11 +1,8 @@
 <?php
 
 /**
- * @defgroup locale-translate-administration-screens Translation administration screens
- * @{
- * Screens for translation administration.
- *
- * These functions provide various screens to view, edit and delete translations.
+ * @file
+ * Interface translation summary, editing and deletion user interfaces.
  */
 
 /**
@@ -14,32 +11,26 @@
 function locale_translate_overview_screen() {
   drupal_static_reset('language_list');
   $languages = language_list('language');
-  $groups = module_invoke_all('locale', 'groups');
-
-  // Build headers with all groups in order.
-  $headers = array_merge(array(t('Language')), array_values($groups));
-
-  // Collect summaries of all source strings in all groups.
-  $sums = db_query("SELECT COUNT(*) AS strings, textgroup FROM {locales_source} GROUP BY textgroup");
-  $groupsums = array();
-  foreach ($sums as $group) {
-    $groupsums[$group->textgroup] = $group->strings;
-  }
+  $headers = array(t('Language'), t('Interface translation status'));
+  $num_strings = db_query("SELECT COUNT(*) FROM {locales_source}")->fetchField();
 
   // Set up overview table with default values, ensuring common order for values.
   $rows = array();
   foreach ($languages as $langcode => $language) {
-    $rows[$langcode] = array('name' => ($langcode == 'en' ? t('English (built-in)') : t($language->name)));
-    foreach ($groups as $group => $name) {
-      $rows[$langcode][$group] = ($langcode == 'en' ? t('n/a') : '0/' . (isset($groupsums[$group]) ? $groupsums[$group] : 0) . ' (0%)');
-    }
+    $rows[$langcode] = array(
+      'name' => ($langcode == 'en' ? t('English (built-in)') : t($language->name)),
+      'status' => ($langcode == 'en' ? t('n/a') : '0/' . $num_strings . ' (0%)'),
+    );
   }
 
-  // Languages with at least one record in the locale table.
-  $translations = db_query("SELECT COUNT(*) AS translation, t.language, s.textgroup FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid GROUP BY textgroup, language");
-  foreach ($translations as $data) {
-    $ratio = (!empty($groupsums[$data->textgroup]) && $data->translation > 0) ? round(($data->translation/$groupsums[$data->textgroup]) * 100.0, 2) : 0;
-    $rows[$data->language][$data->textgroup] = $data->translation . '/' . $groupsums[$data->textgroup] . " ($ratio%)";
+  if (!empty($num_strings)) {
+    // If we have source strings, match translations and compute progress. Not
+    // all languages may have information.
+    $translations = db_query("SELECT COUNT(*) AS translation, t.language FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid GROUP BY language");
+    foreach ($translations as $data) {
+      $ratio = ($data->translation > 0) ? round(($data->translation/$num_strings) * 100.0, 2) : 0;
+      $rows[$data->language]['status'] = $data->translation . '/' . $num_strings . " ($ratio%)";
+    }
   }
 
   return theme('table', array('header' => $headers, 'rows' => $rows));
@@ -68,7 +59,6 @@ function _locale_translate_seek() {
   if (!($query = _locale_translate_seek_query())) {
     $query = array(
       'translation' => 'all',
-      'group' => 'all',
       'language' => 'all',
       'string' => '',
     );
@@ -76,7 +66,7 @@ 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', 'textgroup'));
+  $sql_query->fields('s', array('source', 'location', 'context', 'lid'));
   $sql_query->fields('t', array('translation', 'language'));
 
   // Compute LIKE section.
@@ -110,22 +100,15 @@ function _locale_translate_seek() {
     $limit_language = $query['language'];
   }
 
-  // Add a condition on the text group.
-  if (!empty($query['group']) && $query['group'] != 'all') {
-    $sql_query->condition('s.textgroup', $query['group']);
-  }
-
   $sql_query = $sql_query->extend('PagerDefault')->limit(50);
   $locales = $sql_query->execute();
 
-  $groups = module_invoke_all('locale', 'groups');
-  $header = array(t('Text group'), t('String'), t('Context'), ($limit_language) ? t('Language') : t('Languages'), array('data' => t('Operations'), 'colspan' => '2'));
+  $header = array(t('String'), t('Context'), ($limit_language) ? t('Language') : t('Languages'), array('data' => t('Operations'), 'colspan' => '2'));
 
   $strings = array();
   foreach ($locales as $locale) {
     if (!isset($strings[$locale->lid])) {
       $strings[$locale->lid] = array(
-        'group' => $locale->textgroup,
         'languages' => array(),
         'location' => $locale->location,
         'source' => $locale->source,
@@ -140,7 +123,6 @@ function _locale_translate_seek() {
   $rows = array();
   foreach ($strings as $lid => $string) {
     $rows[] = array(
-      $groups[$string['group']],
       array('data' => check_plain(truncate_utf8($string['source'], 150, FALSE, TRUE)) . '<br /><small>' . $string['location'] . '</small>'),
       $string['context'],
       array('data' => _locale_translate_language_list($string['languages'], $limit_language), 'align' => 'center'),
@@ -181,7 +163,7 @@ function _locale_translate_seek_query() {
   $query = &drupal_static(__FUNCTION__);
   if (!isset($query)) {
     $query = array();
-    $fields = array('string', 'language', 'translation', 'group');
+    $fields = array('string', 'language', 'translation');
     foreach ($fields as $field) {
       if (isset($_SESSION['locale_translation_filter'][$field])) {
         $query[$field] = $_SESSION['locale_translation_filter'][$field];
@@ -217,12 +199,6 @@ function locale_translation_filters() {
     'options' => array('all' => t('Both translated and untranslated strings'), 'translated' => t('Only translated strings'), 'untranslated' => t('Only untranslated strings')),
   );
 
-  $groups = module_invoke_all('locale', 'groups');
-  $filters['group'] = array(
-    'title' => t('Limit search to'),
-    'options' => array_merge(array('all' => t('All text groups')), $groups),
-  );
-
   return $filters;
 }
 
@@ -286,7 +262,7 @@ function locale_translation_filter_form() {
  * Validate result from locale translation filter form.
  */
 function locale_translation_filter_form_validate($form, &$form_state) {
-  if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['language']) && empty($form_state['values']['group'])) {
+  if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['language'])) {
     form_set_error('type', t('You must select something to filter by.'));
   }
 }
@@ -313,25 +289,15 @@ function locale_translation_filter_form_submit($form, &$form_state) {
   $form_state['redirect'] = 'admin/config/regional/translate/translate';
 }
 
-/**
- * @} End of "locale-translate-administration-screens"
- */
-
-/**
- * @defgroup locale-translate-edit-delete Translation editing/deletion interface
- * @{
- * Edit and delete translation strings.
- *
- * These functions provide the user interface to edit and delete
- * translation strings.
- */
 
 /**
  * User interface for string editing.
+ *
+ * @ingroup forms
  */
 function locale_translate_edit_form($form, &$form_state, $lid) {
   // Fetch source string, if possible.
-  $source = db_query('SELECT source, context, textgroup, location FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject();
+  $source = db_query('SELECT source, context, location FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject();
   if (!$source) {
     drupal_set_message(t('String not found.'), 'error');
     drupal_goto('admin/config/regional/translate/translate');
@@ -354,10 +320,6 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
     '#type'  => 'value',
     '#value' => $lid
   );
-  $form['textgroup'] = array(
-    '#type'  => 'value',
-    '#value' => $source->textgroup,
-  );
   $form['location'] = array(
     '#type'  => 'value',
     '#value' => $source->location
@@ -366,10 +328,7 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
   // Include default form controls with empty values for all languages.
   // This ensures that the languages are always in the same order in forms.
   $languages = language_list();
-  $default = language_default();
-  // We don't need the default language value, that value is in $source.
-  $omit = $source->textgroup == 'default' ? 'en' : $default->language;
-  unset($languages[($omit)]);
+  unset($languages['en']);
   $form['translations'] = array('#tree' => TRUE);
   // Approximate the number of rows to use in the default textarea.
   $rows = min(ceil(str_word_count($source->source) / 12), 10);
@@ -383,7 +342,7 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
   }
 
   // Fetch translations and fill in default values in the form.
-  $result = db_query("SELECT DISTINCT translation, language FROM {locales_target} WHERE lid = :lid AND language <> :omit", array(':lid' => $lid, ':omit' => $omit));
+  $result = db_query("SELECT DISTINCT translation, language FROM {locales_target} WHERE lid = :lid", array(':lid' => $lid));
   foreach ($result as $translation) {
     $form['translations'][$translation->language]['#default_value'] = $translation->translation;
   }
@@ -397,10 +356,8 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
  * Validate string editing form submissions.
  */
 function locale_translate_edit_form_validate($form, &$form_state) {
-  // Locale string check is needed for default textgroup only.
-  $safe_check_needed = $form_state['values']['textgroup'] == 'default';
   foreach ($form_state['values']['translations'] as $key => $value) {
-    if ($safe_check_needed && !locale_string_is_safe($value)) {
+    if (!locale_string_is_safe($value)) {
       form_set_error('translations', t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
       watchdog('locale', 'Attempted submission of a translation string with disallowed HTML: %string', array('%string' => $value), WATCHDOG_WARNING);
     }
@@ -473,6 +430,8 @@ function locale_translate_delete_page($lid) {
 
 /**
  * User interface for the string deletion confirmation screen.
+ *
+ * @ingroup forms
  */
 function locale_translate_delete_form($form, &$form_state, $source) {
   $form['lid'] = array('#type' => 'value', '#value' => $source->lid);
@@ -495,6 +454,3 @@ function locale_translate_delete_form_submit($form, &$form_state) {
   drupal_set_message(t('The string has been removed.'));
   $form_state['redirect'] = 'admin/config/regional/translate/translate';
 }
-/**
- * @} End of "locale-translate-edit-delete"
- */
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index 3ae6d91..6dad7e0 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -247,7 +247,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     // assertText() seems to remove the input field where $name always could be
@@ -302,7 +301,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     // Assume this is the only result, given the random name.
@@ -357,9 +355,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
     // table and translate it.
     $query = db_select('locales_source', 'l');
     $query->addExpression('min(l.lid)', 'lid');
-    $result = $query->condition('l.location', '%.js%', 'LIKE')
-      ->condition('l.textgroup', 'default')
-      ->execute();
+    $result = $query->condition('l.location', '%.js%', 'LIKE')->execute();
     $url = 'admin/config/regional/translate/edit/' . $result->fetchObject()->lid;
     $edit = array('translations['. $langcode .']' => $this->randomName());
     $this->drupalPost($url, $edit, t('Save translations'));
@@ -431,7 +427,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     // Find the edit path.
@@ -497,7 +492,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     // assertText() seems to remove the input field where $name always could be
@@ -511,7 +505,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'translated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t("Search didn't find the string."));
@@ -522,7 +515,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'untranslated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('Search found the string.'));
@@ -545,7 +537,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $translation,
       'language' => 'all',
       'translation' => 'translated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('Search found the translation.'));
@@ -556,7 +547,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $name,
       'language' => 'all',
       'translation' => 'untranslated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t("Search didn't find the source string."));
@@ -567,7 +557,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $translation,
       'language' => 'all',
       'translation' => 'untranslated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t("Search didn't find the translation."));
@@ -577,7 +566,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $translation,
       'language' => $langcode,
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('Search found the translation.'));
@@ -587,7 +575,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $translation,
       'language' => 'en',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t("Search didn't find the translation."));
@@ -598,7 +585,6 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
       'string' => $unavailable_string,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t("Search didn't find the invalid string."));
@@ -651,7 +637,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
 
 
-    // Try importing a .po file with invalid tags in the default text group.
+    // Try importing a .po file with invalid tags.
     $this->importPoFile($this->getBadPoFile(), array(
       'langcode' => 'fr',
     ));
@@ -662,22 +648,11 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertRaw($skip_message, t('Unsafe strings were skipped.'));
 
 
-    // Try importing a .po file with invalid tags in a non default text group.
-    $this->importPoFile($this->getBadPoFile(), array(
-      'langcode' => 'fr',
-      'group' => 'custom',
-    ));
-
-    // The import should have created 3 strings.
-    $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' => 3, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
-
-
     // Try importing a .po file which doesn't exist.
     $name = $this->randomName(16);
     $this->drupalPost('admin/config/regional/translate/import', array(
       'langcode' => 'fr',
       'files[file]' => $name,
-      'group' => 'custom',
     ), t('Import'));
     $this->assertEqual($this->getUrl(), url('admin/config/regional/translate/import', array('absolute' => TRUE)), t('Correct page redirection.'));
     $this->assertText(t('File to import not found.'), t('File to import not found message.'));
@@ -697,7 +672,6 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
       'string' => 'Montag',
       'language' => 'fr',
       'translation' => 'translated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
@@ -719,7 +693,6 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
       'string' => 'Montag',
       'language' => 'fr',
       'translation' => 'translated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
@@ -760,7 +733,6 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
       'string' => 'lundi',
       'language' => $langcode,
       'translation' => 'translated',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String successfully imported.'));
@@ -807,7 +779,6 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
       'string' => $str,
       'language' => 'all',
       'translation' => 'all',
-      'group' => 'all',
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     // assertText() seems to remove the input field where $str always could be
@@ -1144,9 +1115,8 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
     $user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
     $this->drupalLogin($user);
     $this->drupalGet('admin/config/regional/translate/translate');
-    $string = db_query('SELECT min(lid) AS lid FROM {locales_source} WHERE location LIKE :location AND textgroup = :textgroup', array(
+    $string = db_query('SELECT min(lid) AS lid FROM {locales_source} WHERE location LIKE :location', array(
       ':location' => '%.js%',
-      ':textgroup' => 'default',
     ))->fetchObject();
     $edit = array('translations[fr]' => 'french translation');
     $this->drupalPost('admin/config/regional/translate/edit/' . $string->lid, $edit, t('Save translations'));
diff --git a/modules/locale/tests/locale_test.module b/modules/locale/tests/locale_test.module
index 14a2588..b29d665 100644
--- a/modules/locale/tests/locale_test.module
+++ b/modules/locale/tests/locale_test.module
@@ -6,16 +6,6 @@
  */
 
 /**
- * Implements hook_locale().
- */
-function locale_test_locale($op = 'groups') {
-  switch ($op) {
-    case 'groups':
-      return array('custom' => t('Custom'));
-  }
-}
-
-/**
  * Implements hook_boot().
  *
  * For testing domain language negotiation, we fake it by setting
