Index: l10n_client.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/l10n_client/Attic/l10n_client.css,v
retrieving revision 1.6.2.2
diff -u -p -r1.6.2.2 l10n_client.css
--- l10n_client.css	20 Apr 2010 22:16:00 -0000	1.6.2.2
+++ l10n_client.css	8 Dec 2010 14:33:26 -0000
@@ -174,3 +174,17 @@ how it wants to round. */
 
 #l10n-client-data {
   display:none;}
+
+.l10n-client-feedback {
+  background-color: #DF8;
+  padding: 5px;
+  font-style: italic;
+  margin-bottom: 10px;
+}
+.l10n-client-feedback.message-warning {
+  background-color: #FD8;
+}
+.l10n-client-feedback.message-error {
+  background-color: #F00;
+  color: #fff;
+}
Index: l10n_client.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/l10n_client/Attic/l10n_client.js,v
retrieving revision 1.10.2.9.2.1
diff -u -p -r1.10.2.9.2.1 l10n_client.js
--- l10n_client.js	8 Dec 2010 12:27:41 -0000	1.10.2.9.2.1
+++ l10n_client.js	8 Dec 2010 14:33:26 -0000
@@ -195,7 +195,8 @@ Drupal.behaviors.l10nClient = function (
         $('#l10n-client-string-select li').eq(Drupal.l10nClient.selected).removeClass('untranslated').removeClass('active').addClass('translated').text(newTranslationDisplay);
 
         // Empty input fields.
-        $('#l10n-client-string-editor .source-text').html('');
+        var messageValue = Drupal.parseJson(data);
+        $('#l10n-client-string-editor .source-text').html(messageValue.message);
         $('#l10n-client-form .translation-target').val('');
 
       },
Index: l10n_client.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/l10n_client/Attic/l10n_client.module,v
retrieving revision 1.22.2.13.2.4
diff -u -p -r1.22.2.13.2.4 l10n_client.module
--- l10n_client.module	8 Dec 2010 12:43:29 -0000	1.22.2.13.2.4
+++ l10n_client.module	8 Dec 2010 14:33:26 -0000
@@ -73,6 +73,17 @@ function l10n_client_perm() {
 }
 
 /**
+ * Implement hook_theme().
+ */
+function l10n_client_theme($existing, $type, $theme, $path) {
+  return array(
+    'l10n_client_message' => array(
+      'arguments' => array('message' => '', 'level' => WATCHDOG_ERROR),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_init().
  */
 function l10n_client_init() {
@@ -430,14 +441,62 @@ function l10n_client_save_string() {
         _locale_import_one_string_db($report, $language->language, $_POST['source'], $_POST['target'], $_POST['textgroup'], NULL, LOCALE_IMPORT_OVERWRITE);
         cache_clear_all('locale:', 'cache', TRUE);
         _locale_invalidate_js($language->language);
+        if (!empty($report['skips'])) {
+          $message = theme('l10n_client_message', t('Not saved locally due to invalid HTML content.'));
+        }
+        elseif (!empty($report['additions']) || !empty($report['updates'])) {
+          $message = theme('l10n_client_message', t('Translation saved locally.'), WATCHDOG_INFO);
+        }
+        elseif (!empty($report['deletes'])) {
+          $message = theme('l10n_client_message', t('Translation successfuly removed locally.'), WATCHDOG_INFO);
+        }
+        else {
+          $message = theme('l10n_client_message', t('Unknown error while saving translation locally.'));
+        }
 
         // Submit to remote server if enabled.
-        if (variable_get('l10n_client_use_server', FALSE) && user_access('submit translations to localization server') && !empty($user->l10n_client_key)) {
-          l10n_client_submit_translation($language->language, $_POST['source'], $_POST['target'], $user->l10n_client_key, l10n_client_user_token($user));
+        if (variable_get('l10n_client_use_server', FALSE) && user_access('submit translations to localization server') && ($_POST['textgroup'] == 'default')) {
+          if (!empty($user->l10n_client_key)) {
+            $remote_result = l10n_client_submit_translation($language->language, $_POST['source'], $_POST['target'], $user->l10n_client_key, l10n_client_user_token($user));
+            $message .= theme('l10n_client_message', $remote_result[1], $remote_result[0] ? WATCHDOG_INFO : WATCHDOG_ERROR);
+          }
+          else {
+            $server_url = variable_get('l10n_client_server', 'http://localize.drupal.org');
+            $user_edit_url = url('user/'. $user->uid .'/edit', array('absolute' => TRUE));
+            $message .= theme('l10n_client_message', t('You could share your work with !l10n_server if you set your API key at !user_link.', array('!l10n_server' => l($server_url, $server_url), '!user_link' => l($user_edit_url, 'user/'. $user->uid .'/edit'))), WATCHDOG_WARNING);
+          }
         }
       }
+      else {
+        $message = theme('l10n_client_message', t('Not saved due to source string missing.'));
+      }
+    }
+    else {
+      $message = theme('l10n_client_message', t('Not saved due to missing form values.'));
     }
   }
+  else {
+    $message = theme('l10n_client_message', t('Not saved due to insufficient permissions.'));
+  }
+  drupal_json(array('message' => $message));
+  exit;
+}
+
+/**
+ * Theme function to wrap l10n_client messages in proper markup.
+ */
+function theme_l10n_client_message($message, $level) {
+  switch ($level) {
+    case WATCHDOG_INFO:
+      return '<div class="l10n-client-feedback message-info">'. $message .'</div>';
+      break;
+    case WATCHDOG_WARNING:
+      return '<div class="l10n-client-feedback message-warning">'. $message .'</div>';
+      break;
+    case WATCHDOG_ERROR:
+      return '<div class="l10n-client-feedback message-error">'. $message .'</div>';
+      break;
+  }
 }
 
 // -----------------------------------------------------------------------------
@@ -555,9 +614,10 @@ function l10n_client_user_token($account
 function l10n_client_submit_translation($langcode, $source, $translation, $user_key, $user_token) {
   $server_uid = current(split(':', $user_key));
   $signature = md5($user_key . $langcode . $source . $translation . $user_token);
+  $server_url = variable_get('l10n_client_server', 'http://localize.drupal.org');
 
   $response = xmlrpc(
-    variable_get('l10n_client_server', 'http://localize.drupal.org') .'/xmlrpc.php',
+    $server_url .'/xmlrpc.php',
     'l10n.submit.translation',
     $langcode,
     $source,
@@ -569,14 +629,17 @@ function l10n_client_submit_translation(
 
   if (!empty($response) && isset($response['status'])) {
     if ($response['status']) {
-      watchdog('l10n_client', 'Translation sent and accepted by remote server.');
+      $message = t('Translation sent and accepted by @server.', array('@server' => $server_url));
+      watchdog('l10n_client', 'Translation sent and accepted by @server.', array('@server' => $server_url));
     } else {
-      watchdog('l10n_client', 'Translation rejected by remote server. Reason: %reason', array('%reason' => $response['reason']), WATCHDOG_WARNING);
+      $message = t('Translation rejected by @server. Reason: %reason', array('%reason' => $response['reason'], '@server' => $server_url));
+      watchdog('l10n_client', 'Translation rejected by @server. Reason: %reason', array('%reason' => $response['reason'], '@server' => $server_url), WATCHDOG_WARNING);
     }
-    return $response['status'];
+    return array($response['status'], $message);
   }
   else {
-    watchdog('l10n_client', 'The connection with the remote server failed with the following error: %error_code: %error_message.', array('%error_code' => xmlrpc_errno(), '%error_message' => xmlrpc_error_msg()), WATCHDOG_ERROR);
-    return FALSE;
+    $message = t('The connection with @server failed with the following error: %error_code: %error_message.', array('%error_code' => xmlrpc_errno(), '%error_message' => xmlrpc_error_msg(), '@server' => $server_url));
+    watchdog('l10n_client', 'The connection with @server failed with the following error: %error_code: %error_message.', array('%error_code' => xmlrpc_errno(), '%error_message' => xmlrpc_error_msg(), '@server' => $server_url), WATCHDOG_ERROR);
+    return array(FALSE, $message);
   }
 }
