diff --git a/components/date.inc b/components/date.inc
index 1cfce87..85b6d9b 100644
--- a/components/date.inc
+++ b/components/date.inc
@@ -133,6 +133,7 @@ function _webform_render_date($component, $value = NULL, $filter = TRUE) {
     '#theme' => 'webform_date',
     '#theme_wrappers' => array('webform_element'),
     '#element_validate' => array('webform_validate_date'),
+    '#translatable' => array('title', 'description'),
   );
 
   if ($component['extra']['datepicker']) {
diff --git a/components/email.inc b/components/email.inc
index 4e5a632..0541d11 100644
--- a/components/email.inc
+++ b/components/email.inc
@@ -123,6 +123,7 @@ function _webform_render_email($component, $value = NULL, $filter = TRUE) {
     '#attributes' => $component['extra']['attributes'],
     '#element_validate'  => array('_webform_validate_email'),
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'description'),
   );
 
   // Add an e-mail class for identifying the difference from normal textfields.
diff --git a/components/fieldset.inc b/components/fieldset.inc
index cab1bff..416c242 100644
--- a/components/fieldset.inc
+++ b/components/fieldset.inc
@@ -61,6 +61,7 @@ function _webform_render_fieldset($component, $value = NULL, $filter = TRUE) {
     '#collapsed' => $component['extra']['collapsed'],
     '#attributes' => array('class' => array('webform-component-fieldset'), 'id' => 'webform-component-' . $component['form_key']),
     '#pre_render' => array('webform_fieldset_prerender'),
+    '#translatable' => array('title', 'description'),
   );
 
   // Hide the fieldset title if #title_display is 'none'.
diff --git a/components/file.inc b/components/file.inc
index 66a60d6..60fe241 100644
--- a/components/file.inc
+++ b/components/file.inc
@@ -366,6 +366,7 @@ function _webform_render_file($component, $value = NULL, $filter = TRUE) {
     '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
     '#weight' => $component['weight'],
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'description'),
   );
 
   return $element;
diff --git a/components/grid.inc b/components/grid.inc
index ec018f8..1ff43c0 100644
--- a/components/grid.inc
+++ b/components/grid.inc
@@ -156,6 +156,7 @@ function _webform_render_grid($component, $value = NULL, $filter = TRUE) {
     '#theme' => 'webform_grid',
     '#theme_wrappers' => array('webform_element'),
     '#process' => array('webform_expand_grid'),
+    '#translatable' => array('title', 'description', 'grid_options', 'grid_questions'),
   );
 
   if ($value) {
@@ -179,6 +180,7 @@ function webform_expand_grid($element) {
   if (!empty($element['#qrand'])) {
     _webform_shuffle_options($questions);
   }
+  $element['#options'] = $options;
 
   foreach ($questions as $key => $question) {
     if ($question != '') {
@@ -192,6 +194,7 @@ function webform_expand_grid($element) {
         // Webform handles validation manually.
         '#validated' => TRUE,
         '#webform_validated' => FALSE,
+        '#translatable' => array('title'),
       );
     }
   }
@@ -229,7 +232,7 @@ function _webform_display_grid($component, $value, $format = 'html') {
 
   foreach ($questions as $key => $question) {
     if ($question !== '') {
-      $element[$question] = array(
+      $element[$key] = array(
         '#title' => $question,
         '#value' => isset($value[$key]) ? $value[$key] : NULL,
       );
@@ -254,11 +257,11 @@ function theme_webform_display_grid($variables) {
     foreach ($element['#grid_options'] as $option) {
       $header[] = array('data' => _webform_filter_xss($option), 'class' => array('checkbox', 'webform-grid-option'));
     }
-    foreach (element_children($element) as $key) {
+    foreach ($element['#grid_questions'] as $question_key => $question) {
       $row = array();
-      $row[] = array('data' => _webform_filter_xss($element[$key]['#title']), 'class' => array('webform-grid-question'));
+      $row[] = array('data' => _webform_filter_xss($question), 'class' => array('webform-grid-question'));
       foreach ($element['#grid_options'] as $option_value => $option_label) {
-        if (strcmp($option_value, $element[$key]['#value']) == 0) {
+        if (strcmp($element[$question_key]['#value'], $option_value) == 0) {
           $row[] = array('data' => '<strong>X</strong>', 'class' => array('checkbox', 'webform-grid-option'));
         }
         else {
@@ -397,18 +400,13 @@ function theme_webform_grid($variables) {
 
   $rows = array();
   $header = array(array('data' => '', 'class' => array('webform-grid-question')));
-  $first = TRUE;
+  // Set the header for the table.
+  foreach ($element['#options'] as $option) {
+    $header[] = array('data' => _webform_filter_xss($option), 'class' => array('checkbox', 'webform-grid-option'));
+  }
   foreach (element_children($element) as $key) {
     $question_element = $element[$key];
 
-    // Set the header for the table.
-    if ($first) {
-      foreach ($question_element['#options'] as $option) {
-        $header[] = array('data' => _webform_filter_xss($option), 'class' => array('checkbox', 'webform-grid-option'));
-      }
-      $first = FALSE;
-    }
-
     // Create a row with the question title.
     $row = array(array('data' => _webform_filter_xss($question_element['#title']), 'class' => array('webform-grid-question')));
 
diff --git a/components/hidden.inc b/components/hidden.inc
index 02986f8..8a168de 100644
--- a/components/hidden.inc
+++ b/components/hidden.inc
@@ -62,6 +62,7 @@ function _webform_render_hidden($component, $value = NULL, $filter = TRUE) {
     '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
     '#default_value' => $filter ? _webform_filter_values($component['value']) : $component['value'],
     '#weight' => $component['weight'],
+    '#translatable' => array('title'),
   );
 
   if (isset($value[0])) {
diff --git a/components/markup.inc b/components/markup.inc
index af5674e..bdf6480 100644
--- a/components/markup.inc
+++ b/components/markup.inc
@@ -64,6 +64,7 @@ function _webform_render_markup($component, $value = NULL, $filter = TRUE) {
     '#markup' => $filter ? _webform_filter_values(check_markup($component['value'], $component['extra']['format'], '', TRUE), NULL, NULL, NULL, FALSE) : $component['value'],
     '#format' => $component['extra']['format'],
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'markup'),
   );
 
   // TODO: Remove when #markup becomes available in D7.
diff --git a/components/number.inc b/components/number.inc
index ff6286e..2eac88f 100644
--- a/components/number.inc
+++ b/components/number.inc
@@ -255,6 +255,7 @@ function _webform_render_number($component, $value = NULL, $filter = TRUE) {
     '#max' => $component['extra']['max'],
     '#step' => abs($component['extra']['step']),
     '#integer' => $component['extra']['integer'],
+    '#translatable' => array('title', 'description'),
   );
 
   // Flip the min and max properties to make min less than max if needed.
diff --git a/components/pagebreak.inc b/components/pagebreak.inc
index d4af46a..422f1b6 100644
--- a/components/pagebreak.inc
+++ b/components/pagebreak.inc
@@ -70,6 +70,7 @@ function _webform_display_pagebreak($component, $value = NULL, $format = 'html')
     '#title' => $component['name'],
     '#weight' => $component['weight'],
     '#format' => $format,
+    '#translatable' => array('title'),
   );
   return $element;
 }
diff --git a/components/select.inc b/components/select.inc
index 495051b..2e3052f 100644
--- a/components/select.inc
+++ b/components/select.inc
@@ -270,6 +270,7 @@ function _webform_render_select($component, $value = NULL, $filter = TRUE) {
     '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
     '#theme_wrappers' => array('webform_element'),
     '#pre_render' => array(), // Needed to disable double-wrapping of radios and checkboxes.
+    '#translatable' => array('title', 'description', 'options'),
   );
 
   // Convert the user-entered options list into an array.
@@ -502,8 +503,13 @@ function theme_webform_display_select($variables) {
   $element = $variables['element'];
   $component = $element['#webform_component'];
 
-  // Convert submitted 'safe' values to un-edited, original form.
-  $options = _webform_select_options($component, TRUE);
+  if (isset($element['#options'])) {
+    $options = $element['#options'];
+  }
+  else {
+    // Convert submitted 'safe' values to un-edited, original form.
+    $options = _webform_select_options($component,TRUE);
+  }
 
   $items = array();
   if ($component['extra']['multiple']) {
diff --git a/components/textarea.inc b/components/textarea.inc
index bd48d05..8a7fab2 100644
--- a/components/textarea.inc
+++ b/components/textarea.inc
@@ -111,6 +111,7 @@ function _webform_render_textarea($component, $value = NULL, $filter = TRUE) {
     '#attributes' => $component['extra']['attributes'],
     '#resizable' => (bool) $component['extra']['resizable'], // MUST be FALSE to disable.
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'description'),
   );
 
   if ($component['extra']['disabled']) {
diff --git a/components/textfield.inc b/components/textfield.inc
index fd2307e..43bd385 100644
--- a/components/textfield.inc
+++ b/components/textfield.inc
@@ -134,6 +134,7 @@ function _webform_render_textfield($component, $value = NULL, $filter = TRUE) {
     '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
     '#attributes' => $component['extra']['attributes'],
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'description'),
   );
 
   if ($component['extra']['disabled']) {
diff --git a/components/time.inc b/components/time.inc
index 5fa4c58..ec0c5db 100644
--- a/components/time.inc
+++ b/components/time.inc
@@ -98,6 +98,7 @@ function _webform_render_time($component, $value = NULL, $filter = TRUE) {
     '#process' => array('webform_expand_time'),
     '#theme' => 'webform_time',
     '#theme_wrappers' => array('webform_element'),
+    '#translatable' => array('title', 'description'),
   );
 
   // Set the value from Webform if available.
diff --git a/includes/webform.submissions.inc b/includes/webform.submissions.inc
index a377f99..8ea1358 100644
--- a/includes/webform.submissions.inc
+++ b/includes/webform.submissions.inc
@@ -110,7 +110,7 @@ function webform_submission_insert($node, $submission) {
 
     $submission->sid = db_insert('webform_submissions')
       ->fields(array(
-        'nid' => $node->nid,
+        'nid' => $node->webform['nid'],
         'uid' => $submission->uid,
         'submitted' => $submission->submitted,
         'remote_addr' => $submission->remote_addr,
@@ -124,7 +124,7 @@ function webform_submission_insert($node, $submission) {
     foreach ($values['value'] as $delta => $value) {
       db_insert('webform_submitted_data')
         ->fields(array(
-          'nid' => $node->nid,
+          'nid' => $node->webform['nid'],
           'sid' => $submission->sid,
           'cid' => $cid,
           'no' => $delta,
diff --git a/webform.module b/webform.module
index 2a8f6d7..c3b6532 100644
--- a/webform.module
+++ b/webform.module
@@ -1236,16 +1236,6 @@ function webform_node_prepare($node) {
   }
 }
 
-/**
- * Implements hook_node_prepare_translation().
- */
-function webform_node_prepare_translation(&$node) {
-  // Copy all Webform settings over to translated versions of this node.
-  if (isset($node->translation_source)) {
-    $source_node = node_load($node->translation_source->nid);
-    $node->webform = $source_node->webform;
-  }
-}
 
 /**
  * Implements hook_node_load().
@@ -2100,7 +2090,8 @@ function _webform_client_form_add_component($node, $component, $component_value,
     if ($display_element = webform_component_invoke($component['type'], 'display', $component, $data, $format)) {
       // Ensure the component is added as a property.
       $display_element['#webform_component'] = $component;
-
+      // Allow modules to modify a "display only" webform component.
+      drupal_alter('webform_display_component',$display_element, $component);
       // The form_builder() function usually adds #parents and #id for us, but
       // because these are not marked for #input, we need to add them manually.
       if (!isset($display_element['#parents'])) {
@@ -2120,7 +2111,8 @@ function _webform_client_form_add_component($node, $component, $component_value,
     if ($element = webform_component_invoke($component['type'], 'render', $component, $data, $filter)) {
       // Ensure the component is added as a property.
       $element['#webform_component'] = $component;
-
+      // Allow modules to modify a webform component that is going to be render in a form.
+      drupal_alter('webform_render_component',$element, $component);
       $parent_fieldset[$component['form_key']] = $element;
 
       // Override the value if one already exists in the form state.
@@ -2413,7 +2405,7 @@ function webform_client_form_submit($form, &$form_state) {
   }
   else {
     // To maintain time and user information, load the existing submission.
-    $submission = webform_get_submission($node->nid, $sid);
+    $submission = webform_get_submission($node->webform['nid'], $sid);
     $submission->is_draft = $is_draft;
 
     // Merge with new submission data. The + operator maintains numeric keys.
@@ -2451,7 +2443,7 @@ function webform_client_form_submit($form, &$form_state) {
 
   // Check if this form is sending an email.
   if (!$is_draft && !$form_state['values']['details']['finished']) {
-    $submission = webform_get_submission($node->nid, $sid, TRUE);
+    $submission = webform_get_submission($node->webform['nid'], $sid, TRUE);
     webform_submission_send_mail($node, $submission);
   }
 
@@ -3666,11 +3658,15 @@ function webform_strtotime($date) {
 }
 
 /**
- * Wrapper function for tt() if i18nstrings enabled.
+ * Wrapper function for i18n_string() if i18nstrings enabled.
  */
 function webform_tt($name, $string, $langcode = NULL, $update = FALSE) {
-  if (function_exists('tt')) {
-    return tt($name, $string, $langcode, $update);
+if (function_exists('i18n_string')) {
+    $options = array(
+      'langcode' => $langcode,
+      'update' => $update,
+    );
+    return i18n_string($name, $string, $options);
   }
   else {
     return $string;
