Index: l10n_client.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/l10n_client/l10n_client.module,v
retrieving revision 1.13
diff -u -r1.13 l10n_client.module
--- l10n_client.module	29 Apr 2008 00:32:37 -0000	1.13
+++ l10n_client.module	25 Jul 2008 16:20:39 -0000
@@ -6,6 +6,9 @@
  *   Localization client. Provides on-page translation editing.
  */
 
+// Number of strings for paging on translation pages
+define('L10N_CLIENT_STRINGS', 100);
+
 /**
  * Implementation of hook_menu().
  */
@@ -18,7 +21,24 @@
     'access arguments' => array('use on-page translation'),
     'type' => MENU_CALLBACK,
   );
-
+  // Helper pages to group all translated/untranslated strings  
+  $items['locale'] = array(
+    'title' => 'Translate strings',
+    'page callback' => 'l10n_client_translate_page',
+    'access arguments' => array('use on-page translation'),
+  );
+  $items['locale/untranslated'] = array(
+    'title' => 'Untranslated',
+    'page arguments' => array('untranslated'),
+    'access arguments' => array('use on-page translation'),
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  );
+  $items['locale/translated'] = array(
+    'title' => 'Translated',
+    'page arguments' => array('translated'),
+    'access arguments' => array('use on-page translation'),
+    'type' => MENU_LOCAL_TASK,
+  );
   // Direct copy of the import tab from locale module to
   // make space for the "Reimport package" tab below.
   $items['admin/build/translate/import/file'] = array(
@@ -90,6 +110,60 @@
 }
 
 /**
+ * Menu callback. Translation pages.
+ * 
+ * These pages just list strings so they can be added to the string list for translation below
+ * 
+ * Note: Includes 'hidden' textgroup support that can be used manually or by other modules
+ */
+function l10n_client_translate_page($status = 'untranslated', $textgroup = 'default', $translate = TRUE) {
+  global $language, $l10n_client_strings;
+
+  $output = '';
+  // Build query for strings
+  $sql = "SELECT s.source, t.translation, t.language FROM {locales_source} s ";
+  switch ($status) {
+    case 'translated':
+      $sql .= " INNER JOIN {locales_target} t ON s.lid = t.lid";
+      $sql .= " WHERE t.language = '$language->language' AND t.translation != ''";
+      break;
+    case 'untranslated':
+    default:
+      $sql .= " LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '$language->language'";
+      $sql .= " WHERE (t.translation IS NULL OR t.translation = '')";
+      break;
+  }
+  // Add textgroup if provided
+  if ($textgroup) {
+    $sql .= " AND s.textgroup ='" . db_escape_string($textgroup) . "'";
+  }
+  // Order alphabetically
+  $sql .= ' ORDER BY s.source';
+  
+  // For 'default' textgroup and English language we don't allow translation
+  $translate = ($textgroup == 'default' && $language->language == 'en') ? FALSE : $translate;
+  
+  $result = pager_query($sql, L10N_CLIENT_STRINGS);
+  while ($data = db_fetch_object($result)) {
+    // Array to display as table
+    $list[] = array($data->source, $data->translation);
+    // Add to the list for the translation tool if 'translate' enabled
+    if ($translate) {
+      $l10n_client_strings[$data->source] = (empty($data->translation) ? TRUE : $data->translation);
+    }
+  }
+  if (!empty($list)) { 
+    // We add a pager above and below content to make navigation easier
+    $output .= $pager = theme('pager', NULL, L10N_CLIENT_STRINGS);
+    $output .= theme('table', array(), $list);
+    $output .= $pager;
+  } else {
+    $output .= t('No strings to translate');
+  }
+  return $output;
+}
+
+/**
  * Implementation of hook_footer().
  *
  * Output a form to the page and a list of strings used to build
@@ -98,65 +172,89 @@
 function l10n_client_footer() {
   global $conf, $language;
   
-  if (user_access('use on-page translation')) {
-    // Get all strings used on the page.
-    $strings = locale();
-    
-    if (is_array($strings) && isset($strings[$language->language])) {
-      // If we have strings for the page language, restructure the data.
-      $l10n_strings = array();
-      foreach ($strings[$language->language] as $string => $translation) {
-        $l10n_strings[] = array($string, $translation);
-      }
-      array_multisort($l10n_strings);
-      // Include string selector on page.
-      $string_list = _l10n_client_string_list($l10n_strings);
-      // Include editing form on page.
-      $l10n_form = drupal_get_form('l10n_client_form', $l10n_strings);
-      // Include search form on page.
-      $l10n_search = drupal_get_form('l10n_client_search_form');
-
-      // We need this hack as JS addition does not work this late on the page.
-      //$l10n_json = '<script type="text/javascript">jQuery.extend(Drupal, { l10nStrings: '. drupal_to_js($l10n_strings) .' });</script>';   
-      $l10n_dom = _l10n_client_dom_strings($l10n_strings);
-
-      // UI Labels
-      $string_label = '<h2>'. t('Page Text') .'</h2>';
-      $source_label = '<h2>'. t('Source') .'</h2>';
-      $translation_label = '<h2>'. t('Translation to %language', array('%language' => $language->native)) .'</h2>';
-      $toggle_label = t('Translate Text');
-
-
-      $output = "
-        <div id='l10n-client' class='hidden'>
-          <div class='labels'>
-            <span class='toggle'>$toggle_label</span>
-            <div class='label strings'>$string_label</div>
-            <div class='label source'>$source_label</div>
-            <div class='label translation'>$translation_label</div>
-          </div>
-          <div id='l10n-client-string-select'>
-            $string_list
-            $l10n_search
+  // Check permission and get all strings used on the page.
+  if (user_access('use on-page translation') && ($page_strings = _l10n_client_page_strings())) {
+    // If we have strings for the page language, restructure the data.
+    $l10n_strings = array();
+    foreach ($page_strings as $string => $translation) {
+      $l10n_strings[] = array($string, $translation);
+    }
+    array_multisort($l10n_strings);
+    // Include string selector on page.
+    $string_list = _l10n_client_string_list($l10n_strings);
+    // Include editing form on page.
+    $l10n_form = drupal_get_form('l10n_client_form', $l10n_strings);
+    // Include search form on page.
+    $l10n_search = drupal_get_form('l10n_client_search_form');
+
+    // We need this hack as JS addition does not work this late on the page.
+    //$l10n_json = '<script type="text/javascript">jQuery.extend(Drupal, { l10nStrings: '. drupal_to_js($l10n_strings) .' });</script>';   
+    $l10n_dom = _l10n_client_dom_strings($l10n_strings);
+
+    // UI Labels
+    $string_label = '<h2>'. t('Page Text') .'</h2>';
+    $source_label = '<h2>'. t('Source') .'</h2>';
+    $translation_label = '<h2>'. t('Translation to %language', array('%language' => $language->native)) .'</h2>';
+    $toggle_label = t('Translate Text');
+
+
+    $output = "
+      <div id='l10n-client' class='hidden'>
+        <div class='labels'>
+          <span class='toggle'>$toggle_label</span>
+          <div class='label strings'>$string_label</div>
+          <div class='label source'>$source_label</div>
+          <div class='label translation'>$translation_label</div>
+        </div>
+        <div id='l10n-client-string-select'>
+          $string_list
+          $l10n_search
+        </div>
+        <div id='l10n-client-string-editor'>
+          <div class='source'>
+            <div class='source-text'></div>
           </div>
-          <div id='l10n-client-string-editor'>
-            <div class='source'>
-              <div class='source-text'></div>
-            </div>
-            <div class='translation'>
-              $l10n_form
-            </div>
+          <div class='translation'>
+            $l10n_form
           </div>
         </div>
-        $l10n_dom
-      ";
+      </div>
+      $l10n_dom
+    ";
 
-      return $output;
-    }
+    return $output;
   }
 }
 
 /**
+ * Get the strings to translate for this page. These will be:
+ * - The ones added in $l10n_client_strings by this or other modules
+ * - The strings tored by the locale function (not for for this module's own pages)
+ * 
+ * Any module can add strings to translate into the global variable $l10n_client_strings
+ */
+function _l10n_client_page_strings() {
+  global $language, $l10n_client_strings;
+
+  // Get the page strins stored by this or other modules
+  $strings = !empty($l10n_client_strings) ? $l10n_client_strings : array();
+  
+  // If this is not the module's translation page, merge all strings used on the page.
+  if (arg(0) != 'locale' && is_array($locale = locale()) && isset($locale[$language->language])){
+    $strings = array_merge($strings, $locale[$language->language]);
+    
+    // Also select other strings for this path. Other users may have run into these strings for the same page.
+    $result = db_query("SELECT s.source, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.location = '%s'", $language->language, request_uri());
+    while ($data = db_fetch_object($result)) {
+      if (!array_key_exists($data->source, $strings)) {
+        $strings[$data->source] = (empty($data->translation) ? TRUE : $data->translation);
+      }
+    }
+  }
+  
+  return $strings;
+}
+/**
  * Helper function for the string list DOM tree
  */
 function _l10n_client_dom_strings($strings) {
