diff --git a/entity_translation.module b/entity_translation.module
index 4a512d5..2d02bb2 100644
--- a/entity_translation.module
+++ b/entity_translation.module
@@ -1129,10 +1129,9 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
     if (!$handler->isNewEntity() && ($new_translation || count($translations->data) > 1)) {
       list(, , $bundle) = entity_extract_ids($entity_type, $entity);
 
-      // Shared fields are visible if we are either editing the source node, or
-      // if the user has the respective permission.
-      $is_source = $langcode == $handler->getLanguage();
-      $shared_fields_visible = $is_source || user_access('edit translation shared fields');
+      // Shared fields are only visible if the user has the respective
+      // permission.
+      $shared_fields_visible = user_access('edit translation shared fields') || user_access("edit $entity_type translation shared fields");
 
       foreach (field_info_instances($entity_type, $bundle) as $instance) {
         $field_name = $instance['field_name'];
@@ -1140,11 +1139,8 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
 
         if ($shared_fields_visible) {
           // Add visual clues about translatability.
-          if (!isset($form[$field_name]['#process'])) {
-            $form[$field_name]['#process'] = array();
-          }
-          $form[$field_name]['#field_name'] = $field_name;
-          array_unshift($form[$field_name]['#process'], 'entity_translation_element_translatability_clue');
+          $form[$field_name]['#translatable'] = $field['translatable'];
+          _entity_translation_element_add_callback($form[$field_name], '#process', 'entity_translation_element_translatability_clue');
         }
         // Hide shared fields.
         elseif (!$field['translatable']) {
@@ -1236,14 +1232,10 @@ function entity_translation_form_element_language_replace(&$element, $source, $l
  * shared between different translations. Moreover fields receive a CSS class to
  * distinguish between translatable and shared fields.
  */
-function entity_translation_element_translatability_clue($element, &$form_state, $form) {
-  $field_name = $element['#field_name'];
-  $field = field_info_field($field_name);
-
+function entity_translation_element_translatability_clue($element) {
   // Append language to element title.
-  if (variable_get('entity_translation_shared_labels', TRUE)) {
-    $suffix = $field['translatable'] ? '' : ' (' . t('shared field') . ')';
-    _entity_translation_element_title_append($element, $suffix);
+  if (variable_get('entity_translation_shared_labels', TRUE) && !$element['#translatable']) {
+    _entity_translation_element_title_append($element, ' (' . t('shared field') . ')');
   }
 
   // Add CSS class names.
@@ -1253,12 +1245,43 @@ function entity_translation_element_translatability_clue($element, &$form_state,
   if (!isset($element['#attributes']['class'])) {
     $element['#attributes']['class'] = array();
   }
-  $element['#attributes']['class'][] = 'entity-translation-' . ($field['translatable'] ? 'field-translatable' : 'field-shared');
+  $element['#attributes']['class'][] = 'entity-translation-' . ($element['#translatable'] ? 'field-translatable' : 'field-shared');
 
   return $element;
 }
 
 /**
+ * Adds a callback function to the given FAPI element.
+ *
+ * Drupal core only adds default element callbacks if the respective handler
+ * type is not defined yet. This function ensures that our callback is only
+ * prepended/appended to the default set of callbacks instead of replacing it.
+ *
+ * @param $element
+ *   The FAPI element.
+ * @param $type
+ *   The callback type, e.g. '#pre_render' or '#process'.
+ * @param $function
+ *   The name of the callback to add.
+ * @param $prepend
+ *   Set to TRUE to add the new callback to the beginning of the existing set of
+ *   callbacks, and set it to FALSE to append it at the end.
+ */
+function _entity_translation_element_add_callback(&$element, $type, $function, $prepend = TRUE) {
+  // If handler type has not been set, add defaults from element_info().
+  if (!isset($element[$type])) {
+    $element_info = element_info($element['#type']);
+    $element[$type] = isset($element_info[$type]) ? $element_info[$type] : array();
+  }
+  if ($prepend) {
+    array_unshift($element[$type], $function);
+  }
+  else {
+    $element[$type][] = $function;
+  }
+}
+
+/**
  * Appends the given $suffix string to the title of the given form element.
  *
  * If the given element does not have a #title attribute, the function is
diff --git a/includes/translation.handler.inc b/includes/translation.handler.inc
index 502787e..cb44acb 100644
--- a/includes/translation.handler.inc
+++ b/includes/translation.handler.inc
@@ -1075,20 +1075,37 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
       $form['actions']['delete']['#submit'][] = 'entity_translation_entity_form_submit';
     }
 
-    // Hide shared fields if the user is not allowed to edit them.
-    $this->entityFormAccess($form, user_access('edit translation shared fields') || user_access("edit $this->entityType translation shared fields"));
+    // Hide shared form elements if the user is not allowed to edit them.
+    $this->entityFormSharedElements($form);
   }
 
   /**
-   * Assign the given access to the form elements not defining one yet.
+   * Handle shared form elements (e.g. entity properties).
+   *
+   * Either remove access or add a translatability clue depending on the current
+   * user's "edit translation shared fields" permissions.
+   *
+   * Fields are handled separately in entity_translation_field_attach_form().
    */
-  protected function entityFormAccess(&$form, $access) {
-    if (!$access) {
-      $allowed_types = array_flip(array('actions', 'container', 'value', 'hidden', 'vertical_tabs'));
-      foreach (element_children($form) as $key) {
-        if (!isset($form[$key]['#access']) && !isset($allowed_types[$form[$key]['#type']])) {
-          $form[$key]['#access'] = $access;
-        }
+  private function entityFormSharedElements(&$form) {
+    $access = user_access('edit translation shared fields') || user_access("edit $this->entityType translation shared fields");
+    $ignored_types = array_flip(array('actions', 'container', 'value', 'hidden', 'vertical_tabs', 'token'));
+    $ignored_elements = array_flip(array('language', 'translation'));
+
+    foreach (element_children($form) as $key) {
+      // Ignore certain form elements.
+      if (isset($ignored_types[$form[$key]['#type']]) || isset($ignored_elements[$key])) {
+        continue;
+      }
+      // Update #access only if it has not been set already.
+      if (!isset($form[$key]['#access'])) {
+        $form[$key]['#access'] = $access;
+      }
+      // Add translatability clue for visible elements.
+      if ($access) {
+        // Properties are NOT translatable by default.
+        $form[$key]['#translatable'] = FALSE;
+        _entity_translation_element_add_callback($form[$key], '#process', 'entity_translation_element_translatability_clue');
       }
     }
   }
