Index: webform.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/webform.module,v
retrieving revision 1.196.2.54
diff -u -p -r1.196.2.54 webform.module
--- webform.module	8 Sep 2010 05:23:47 -0000	1.196.2.54
+++ webform.module	27 Sep 2010 15:25:45 -0000
@@ -1066,18 +1066,7 @@ function webform_node_load($node) {
   $result = db_query('SELECT * FROM {webform_component} WHERE nid = %d ORDER BY weight, name', $node->nid);
   while ($c = db_fetch_array($result)) {
     $component =& $additions['webform']['components'][$c['cid']];
-    $component['nid'] = $node->nid;
-    $component['cid'] = $c['cid'];
-    $component['form_key'] = $c['form_key'] ? $c['form_key'] : $c['cid'];
-    $component['name'] = t($c['name']);
-    $component['type'] = $c['type'];
-    $component['value'] = $c['value'];
-    $component['extra'] = unserialize($c['extra']);
-    $component['mandatory'] = $c['mandatory'];
-    $component['pid'] = $c['pid'];
-    $component['weight'] = $c['weight'];
-
-    webform_component_defaults($component);
+    webform_component_init($component, $c);
   }
 
   // Organize the components into a fieldset-based order.
@@ -1091,6 +1080,24 @@ function webform_node_load($node) {
 }
 
 /**
+ * TODO
+ */
+function webform_component_init(&$component, $data) {
+  $component['nid'] = $data['nid'];
+  $component['cid'] = $data['cid'];
+  $component['form_key'] = $data['form_key'] ? $data['form_key'] : $data['cid'];
+  $component['name'] = $data['name'];
+  $component['type'] = $data['type'];
+  $component['value'] = $data['value'];
+  $component['extra'] = unserialize($data['extra']);
+  $component['mandatory'] = $data['mandatory'];
+  $component['pid'] = $data['pid'];
+  $component['weight'] = $data['weight'];
+
+  webform_component_defaults($component);
+}
+
+/**
  * Implementation of hook_link().
  * Always add a "view form" link.
  */
@@ -1601,6 +1608,9 @@ function _webform_client_form_rule_check
 function _webform_client_form_add_component($node, $component, $component_value, &$parent_fieldset, &$form, $form_state, $submission, $format = 'form', $page_num = 0, $filter = TRUE) {
   $cid = $component['cid'];
 
+  // Translate the current component.
+  $component = webform_component_translate($component, $filter);
+
   // Load with submission information if necessary.
   if ($format != 'form') {
     // This component is display only.
@@ -1873,8 +1883,13 @@ function webform_client_form_submit($for
     return;
   }
 
-  $node = node_load($form_state['values']['details']['nid']);
+  $nid = $form_state['values']['details']['nid'];
+  $node = node_load($nid);
 
+  if (webform_translation_supported_type($node)) {
+    $node = node_load($node->tnid);
+  }
+
   // Check if user is submitting as a draft.
   $is_draft = $form_state['values']['op'] == t('Save Draft');
 
@@ -2060,7 +2075,7 @@ function webform_client_form_submit($for
     $redirect = array($parts['path'], $query, $parts['fragment']);
   }
   else {
-    $redirect = array('node/' . $node->nid . '/done', 'sid=' . $sid);
+    $redirect = array('node/' . $nid . '/done', 'sid=' . $sid);
   }
 
   // Show a message if manually set.
@@ -2893,11 +2908,48 @@ function webform_set_breadcrumb($node, $
 }
 
 /**
+ * Implementation of hook_locale().
+ */
+function webform_locale($op = 'groups', $group = NULL) {
+  switch ($op) {
+    case 'groups':
+      return array('webform' => t('Webform'));
+    case 'info':
+      $info['webform']['refresh callback'] = 'webform_locale_refresh';
+      $info['webform']['format'] = FALSE;
+      return $info;
+  }
+}
+
+/**
+ * Refresh locale strings.
+ */
+function webform_locale_refresh() {
+  module_load_include('inc', 'webform', 'includes/webform.components');
+
+  $result = db_query('SELECT * FROM {webform_component}');
+  while ($c = db_fetch_array($result)) {
+    $component = array();
+    webform_component_init($component, $c);
+    webform_component_translate($component, TRUE, TRUE);
+  }
+
+  return TRUE;
+}
+
+/**
  * Wrapper function for tt() if i18nstrings enabled.
  */
-function webform_tt($name, $string, $langcode = NULL, $update = FALSE) {
-  if (function_exists('tt')) {
-    return tt($name, $string, $langcode, $update);
+function webform_tt($name = NULL, $string = NULL, $langcode = NULL, $update = FALSE) {
+  $translate = function_exists('i18nstrings');
+  if (empty($name)) {
+    return $translate;
+  }
+  elseif ($translate) {
+    if ($update) {
+      i18nstrings_update($name, $string);
+    }
+    return i18nstrings($name, $string, $langcode);
   }
   else {
     return $string;
@@ -2905,6 +2957,52 @@ function webform_tt($name, $string, $lan
 }
 
 /**
+ * TODO
+ */
+function webform_translation_supported_type($node) {
+  // TODO: content type option
+  return webform_tt();
+}
+
+/**
+ * TODO
+ */
+function webform_translation_sync($node, $data, $store_callback, $insert = FALSE) {
+  if ($translations = translation_node_get_translations($node->tnid)) {
+    unset($translations[$node->language]);
+    $store_callback .= '_'. ($insert ? 'insert' : 'update');
+    $count = 0;
+
+    foreach ($translations as $langcode => $translation) {
+      $data['nid'] = $translation->nid;
+      $store_callback($data);
+      $count++;
+    }
+
+    drupal_set_message(format_plural($count, 'One webform translation has been synchronized.', 'All @count webform translations have been synchronized.'));
+  }
+}
+
+/**
+ * TODO
+ */
+function webform_node_translation_sync($node) {
+  if ($translations = translation_node_get_translations($node->tnid)) {
+    unset($translations[$node->language]);
+    $count = 0;
+
+    foreach ($translations as $langcode => $translation) {
+      $translation = node_load($translation->nid);
+      $translation->webform = $node->webform;
+      node_save($translation);
+      $count++;
+    }
+
+    drupal_set_message(format_plural($count, 'One webform translation has been synchronized.', 'All @count webform translations have been synchronized.'));
+  }
+}
+
+/**
  * Implementation of hook_views_api().
  */
 function webform_views_api() {
Index: components/select.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/components/select.inc,v
retrieving revision 1.39.2.20
diff -u -p -r1.39.2.20 select.inc
--- components/select.inc	10 Sep 2010 17:41:17 -0000	1.39.2.20
+++ components/select.inc	27 Sep 2010 14:10:21 -0000
@@ -254,6 +254,14 @@ function _webform_edit_validate_options(
 }
 
 /**
+ * Implementation of _webform_translate_component().
+ */
+function _webform_translate_select($component, $filter = TRUE, $update = FALSE) {
+  $component['extra']['options_array'] = _webform_select_options_translate($component, $filter, $update);
+  return $component;
+}
+
+/**
  * Implementation of _webform_render_component().
  */
 function _webform_render_select($component, $value = NULL, $filter = TRUE) {
@@ -266,7 +274,7 @@ function _webform_render_select($compone
 
   // Convert the user-entered options list into an array.
   $default_value = $filter ? _webform_filter_values($component['value'], NULL, NULL, NULL, FALSE) : $component['value'];
-  $options = _webform_select_options($component, !$component['extra']['aslist'], $filter);
+  $options = empty($component['extra']['options_array']) ? _webform_select_options($component, !$component['extra']['aslist'], $filter) : $component['extra']['options_array'];
 
   if ($component['extra']['optrand']) {
     _webform_shuffle_options($options);
@@ -727,6 +735,36 @@ function _webform_select_options($compon
 }
 
 /**
+ * TODO
+ */
+function _webform_select_options_translate($component, $filter = TRUE, $update = FALSE) {
+  if (!webform_tt()) {
+    return FALSE;
+  }
+
+  $options = _webform_select_options($component, !$component['extra']['aslist'], $filter);
+  $toptions = array();
+  $group_index = 0;
+
+  foreach ($options as $key => $value) {
+    if (is_array($value)) {
+      $group = $key;
+      $group = webform_tt("webform:component:{$component['cid']}:group:$group_index", $group, NULL, $update);
+      $group_index++;
+
+      foreach ($value as $key => $value) {
+        $toptions[$group][$key] = webform_tt("webform:component:{$component['cid']}:option:$key", $value, NULL, $update);
+      }
+    }
+    else {
+      $toptions[$key] = webform_tt("webform:component:{$component['cid']}:option:$key", $value, NULL, $update);
+    }
+  }
+
+  return $toptions;
+}
+
+/**
  * Load Webform select option info from 3rd party modules.
  */
 function _webform_select_options_info() {
Index: components/textfield.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/components/textfield.inc,v
retrieving revision 1.21.2.3
diff -u -p -r1.21.2.3 textfield.inc
--- components/textfield.inc	21 Mar 2010 03:38:12 -0000	1.21.2.3
+++ components/textfield.inc	27 Sep 2010 14:10:21 -0000
@@ -118,6 +118,21 @@ function _webform_edit_textfield($compon
 }
 
 /**
+ * Implementation of _webform_translate_component().
+ */
+function _webform_translate_textfield($component, $filter = TRUE, $update = FALSE) {
+  if (!empty($component['value'])) {
+    $component['value'] = webform_tt("webform:component:{$component['cid']}:value", $component['value'], NULL, $update);
+  }
+  foreach (array('field_prefix', 'field_suffix') as $field) {
+    if (!empty($component['extra'][$field])) {
+      $component['extra'][$field] = webform_tt("webform:component:{$component['cid']}:$field", $component['extra'][$field], NULL, $update);
+    }
+  }
+  return $component;
+}
+
+/**
  * Implementation of _webform_render_component().
  */
 function _webform_render_textfield($component, $value = NULL, $filter = TRUE) {
Index: includes/webform.components.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/includes/webform.components.inc,v
retrieving revision 1.25.2.18
diff -u -p -r1.25.2.18 webform.components.inc
--- includes/webform.components.inc	23 Sep 2010 03:19:31 -0000	1.25.2.18
+++ includes/webform.components.inc	27 Sep 2010 15:27:26 -0000
@@ -576,6 +576,13 @@ function webform_component_edit_form_sub
     $cid = webform_component_insert($form_state['values']);
   }
 
+  // Create the translation sources for the component.
+  webform_component_translate($form_state['values'], TRUE, TRUE);
+  // TODO
+  if (webform_translation_supported_type($node)) {
+    webform_component_translation_sync($node, $form_state['values'], isset($cid));
+  }
+
   // Since Webform components have been updated but the node itself has not
   // been saved, it is necessary to explicitly clear the cache to make sure
   // the updated webform is visible to anonymous users.
@@ -719,6 +726,34 @@ function webform_component_clone(&$node,
 }
 
 /**
+ * Translate the given component.
+ * TODO
+ */
+function webform_component_translate($component, $filter = TRUE, $update = FALSE) {
+  if (webform_tt()) {
+    $tcomponent = webform_component_invoke($component['type'], 'translate', $component, $filter, $update);
+    if (!isset($tcomponent)) {
+      $tcomponent = $component;
+    }
+    $tcomponent['name'] = webform_tt("webform:component:{$component['cid']}:name", $component['name'], NULL, $update);
+    if (!empty($tcomponent['extra']['description'])) {
+      $tcomponent['extra']['description'] = webform_tt("webform:component:{$component['cid']}:description", $component['extra']['description'], NULL, $update);
+    }
+  }
+  else {
+    $tcomponent = $component;
+  }
+  return $tcomponent;
+}
+
+/**
+ * TODO
+ */
+function webform_component_translation_sync($node, $component, $insert = FALSE) {
+  webform_translation_sync($node, $component, 'webform_component', $insert);
+}
+
+/**
  * Check if a component has a particular feature.
  */
 function webform_component_feature($type, $feature) {
Index: includes/webform.emails.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/includes/webform.emails.inc,v
retrieving revision 1.9.2.10
diff -u -p -r1.9.2.10 webform.emails.inc
--- includes/webform.emails.inc	30 Aug 2010 20:22:15 -0000	1.9.2.10
+++ includes/webform.emails.inc	27 Sep 2010 15:11:51 -0000
@@ -399,10 +399,12 @@ function webform_email_edit_form_validat
  * Submit handler for webform_email_edit_form().
  */
 function webform_email_edit_form_submit($form, &$form_state) {
+  $node = $form_state['values']['node'];
+
   // Merge the e-mail, name, address, and subject options into single values.
   $email = array(
     'eid' => $form_state['values']['eid'],
-    'nid' => $form_state['values']['node']->nid,
+    'nid' => $node->nid,
   );
 
   foreach (array('email', 'from_name', 'from_address', 'subject') as $field) {
@@ -436,19 +438,31 @@ function webform_email_edit_form_submit(
   // We actually maintain an *exclusion* list, so any new components will
   // default to being included in the %email_values token until unchecked.
   $included = array_keys(array_filter((array) $form_state['values']['components']));
-  $excluded = array_diff(array_keys($form_state['values']['node']->webform['components']), $included);
+  $excluded = array_diff(array_keys($node->webform['components']), $included);
   $email['excluded_components'] = $excluded;
 
   if (empty($form_state['values']['eid'])) {
     drupal_set_message(t('Email settings added.'));
-    $cid = webform_email_insert($email);
+    $eid = webform_email_insert($email);
   }
   else {
     drupal_set_message(t('Email settings updated.'));
     webform_email_update($email);
   }
 
-  $form_state['redirect'] = array('node/' . $form_state['values']['node']->nid . '/webform/emails');
+  // TODO
+  if (webform_translation_supported_type($node)) {
+    webform_email_translation_sync($node, $email, isset($eid));
+  }
+
+  $form_state['redirect'] = array('node/' . $node->nid . '/webform/emails');
+}
+
+/**
+ * TODO
+ */
+function webform_email_translation_sync($node, $email, $insert = FALSE) {
+  webform_translation_sync($node, $email, 'webform_email', $insert);
 }
 
 /**
Index: includes/webform.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/includes/webform.pages.inc,v
retrieving revision 1.10.2.3
diff -u -p -r1.10.2.3 webform.pages.inc
--- includes/webform.pages.inc	4 Sep 2010 18:14:04 -0000	1.10.2.3
+++ includes/webform.pages.inc	27 Sep 2010 15:21:50 -0000
@@ -219,6 +219,11 @@ function webform_configure_form_submit($
 
   node_save($node);
 
+  // TODO
+  if (webform_translation_supported_type($node)) {
+    webform_node_translation_sync($node);
+  }
+
   drupal_set_message(t('The form settings have been updated.'));
 }
 
Index: includes/webform.report.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/includes/webform.report.inc,v
retrieving revision 1.16.2.9
diff -u -p -r1.16.2.9 webform.report.inc
--- includes/webform.report.inc	8 Sep 2010 05:23:47 -0000	1.16.2.9
+++ includes/webform.report.inc	27 Sep 2010 14:10:21 -0000
@@ -17,6 +17,11 @@ module_load_include('inc', 'webform', 'i
 function webform_results_submissions($node, $user_filter, $pager_count) {
   global $user;
 
+  $nid = $node->nid;
+  if (webform_translation_supported_type($node)) {
+    $node = node_load($node->tnid);
+  }
+
   if (isset($_GET['results']) && is_numeric($_GET['results'])) {
     $pager_count = $_GET['results'];
   }
@@ -76,6 +81,11 @@ function webform_results_submissions($no
     $rows[] = $row;
   }
 
+  // Restore the original node if no submission is found.
+  if (empty($rows) && webform_translation_supported_type($node)) {
+    $node = node_load($nid);
+  }
+
   $element['#theme'] = 'webform_results_submissions';
   $element['#node'] = $node;
   $element['#submissions'] = $submissions;
@@ -173,6 +183,10 @@ function template_preprocess_webform_res
  * Create a table containing all submitted values for a webform node.
  */
 function webform_results_table($node, $pager_count = 0) {
+  if (webform_translation_supported_type($node)) {
+    $node = node_load($node->tnid);
+  }
+
   if (isset($_GET['results']) && is_numeric($_GET['results'])) {
     $pager_count = $_GET['results'];
   }
@@ -290,8 +304,8 @@ function webform_results_clear_form($for
 }
 
 function webform_results_clear_form_submit($form, &$form_state) {
-  webform_results_clear($form_state['values']['nid']);
   $node = node_load($form_state['values']['nid']);
+  webform_results_clear(webform_translation_supported_type($node) ? $node->tnid : $node->nid);
   $title = $node->title;
 
   $message = t('Webform %title entries cleared.', array('%title' => $title));
@@ -307,6 +321,10 @@ function webform_results_download_form(&
   module_load_include('inc', 'webform', 'includes/webform.export');
   module_load_include('inc', 'webform', 'includes/webform.components');
 
+  if (webform_translation_supported_type($node)) {
+    $node = node_load($node->tnid);
+  }
+
   $form = array();
 
   $form['node'] = array(
@@ -619,6 +637,10 @@ function webform_results_download($node,
  *   "Other" values within a select list.
  */
 function webform_results_analysis($node, $sids = array(), $analysis_component = NULL) {
+  if (webform_translation_supported_type($node)) {
+    $node = node_load($node->tnid);
+  }
+
   if (!is_array($sids)) {
     $sids = array();
   }
