diff --git a/workflow.features.inc b/workflow.features.inc
index 38b6f33..b3ce9c0 100644
--- a/workflow.features.inc
+++ b/workflow.features.inc
@@ -1,5 +1,11 @@
 <?php
-// $Id$
+
+/**
+ * @file
+ * Intergrates workflow with features.
+ */
+
+define('WORKFLOW_FEATURES_AUTHOR_NAME', 'workflow_features_author_name');
 
 /**
  * Workflows are a **faux-exportable** component.
@@ -24,20 +30,25 @@ function workflow_features_export($data, &$export, $module_name = '') {
  * Implements hook_features_export_render().
  */
 function workflow_features_export_render($module, $data) {
-  $code = array();
+  $translatables = $code = array();
+  $code[] = '  $workflows = array();';
+  $code[] = '';
+
   $workflows = workflow_get_workflows();
   foreach ($data as $name) {
-    foreach ($workflows as $workflow) {
-      if ($workflow->name == $name) {
-        if ($this_workflow = workflow_get_workflows_full_object($workflow->name)) {
-          unset($this_workflow->wid);
-          $code[$name] = $this_workflow;
-        }
-      }
+    if ($workflow = workflow_get_workflows_full_object($name)) {
+      unset($workflow->wid);
+      $workflow_export = features_var_export($workflow, '  ');
+      $workflow_identifier = features_var_export($workflow->name);
+      $code[] = "  // Exported workflow: $name";
+      $code[] = "  \$workflows[{$workflow_identifier}] = {$workflow_export};";
+      $code[] = "";
     }
   }
-  $code = "  return " . features_var_export($code, '  ') . ";";
-  return array('workflow_features_default_workflow' => $code);
+
+  $code[] = '  return $workflows;';
+  $code = implode("\n", $code);
+  return array('workflow_default_workflows' => $code);
 }
 
 /**
@@ -55,9 +66,8 @@ function workflow_features_export_options() {
  * Implements hook_features_revert().
  */
 function workflow_features_revert($module) {
-  $saved_workflows = module_invoke($module, 'workflow_features_default_workflow');
-  foreach ($saved_workflows as $key => $workflow) {
-    $saved = workflow_update_workflows_full_object($workflow);
+  foreach (features_get_default('workflow', $module) as $key => $workflow) {
+    workflow_update_workflows_full_object($workflow);
   }
 }
 
@@ -74,34 +84,36 @@ function workflow_features_export_rebuild($module) {
 
 /**
  * For use by CRUD only, save everything from the CRUD formed object.
+ *
+ * @see workflow_get_workflows_full_object
+ *
+ * @param $workflow
+ *   A fully loaded workflow object to save the states of.
+ *
+ * @return
+ *   Returns whether the workflow was saved fully.
  */
 function workflow_update_workflows_full_object($workflow) {
   $workflow = (object) $workflow;
   // Given a workflow in the format returned from export.
   // First we grab the states, transitions and node_maps out.
-  $states = array();
-  if (isset($workflow->states)) {
-    $states = $workflow->states;
-    unset($workflow->states);
-  }
-  $transitions = array();
-  if (isset($workflow->transitions)) {
-    $transitions = $workflow->transitions;
-    unset($workflow->transitions);
-  }
-  $node_types = array();
-  if (isset($workflow->node_types)) {
-    $node_types = $workflow->node_types;
-    unset($workflow->node_types);
-  }
+  $states = isset($workflow->states) ? $workflow->states : array();
+  $transitions = isset($workflow->transitions) ? $workflow->transitions : array();
+  $node_types = isset($workflow->node_types) ? $workflow->node_types : array();
+  unset($workflow->states, $workflow->transitions, $workflow->node_types);
+
   // Then make a workflow so we can track by wid.
-  if ($orig_workflow = workflow_get_workflows_full_object($workflow->name)) {
+  if ($orig_workflow = workflow_get_workflows_by_name($workflow->name)) {
     $workflow->wid = $orig_workflow->wid;
   }
+
   workflow_update_workflows($workflow, FALSE);
+
+  // Cancel out if workflow failed to save.
   if (!isset($workflow->wid) || empty($workflow->wid)) {
     return FALSE;
   }
+
   // Workflow is now a fully vetted workflow object. We have NOT created a creation state with this.
   // Then make states, marking state name to state sid.
   $active_states = array();
@@ -114,35 +126,45 @@ function workflow_update_workflows_full_object($workflow) {
     workflow_update_workflow_states($state);
     $active_states[$state->state] = $state->sid;
   }
+
   // Delete any states *not* in our original construction.
   foreach (workflow_get_workflow_states_by_wid($workflow->wid) as $state) {
-    if(!in_array($state->sid, $active_states)) {
+    if (!in_array($state->sid, $active_states)) {
       workflow_delete_workflow_states_by_sid($state->sid);
     }
   }
+
   // Then make transitions with the state mapping.
   foreach ($transitions as $transition) {
     $transition = (object) $transition;
-    $transition->sid = $active_states[$transition->sid];
-    $transition->target_sid = $active_states[$transition->target_sid];
-    // NOTE: There is an assumption here with roles, that the rids are the same between installs.
-    // This is rather unavoidable at current configs. SO: either roles need to be exported too, or
-    // The installers should check role states with additional code.
-    // workflow_update_workflow_transitions checks preexisting transitions by sid, target_sid.
+    $transition->sid = $active_states[$transition->state];
+    $transition->target_sid = $active_states[$transition->target_state];
+    // Roles are exported by rolename, so need to translate to RID.
+    $transition->roles = !empty($transition->roles) ? _workflow_roles_to_rids($transition->roles) : '';
     workflow_update_workflow_transitions($transition);
   }
+
   // Then add the node_type mapping.
   foreach ($node_types as $node_type) {
-    $node_type = (object) $node_type;
-    $node_type->wid = $workflow->wid;
+    $node_type = (object) array(
+      'type' => $node_type,
+      'wid' => $workflow->wid
+    );
     // Insert, nodes only have one workflow. Insert will delete any prior workflow assoc.
     workflow_insert_workflow_type_map($node_type);
   }
+
   return TRUE;
 }
 
 /**
  * For use by CRUD only, gather everything into the CRUD formed object.
+ *
+ * @param $name
+ *   A string corresponding to a workflow object.
+ *
+ * @return
+ *   A fully loaded workflow object with type and statue mappings.
  */
 function workflow_get_workflows_full_object($name) {
   if ($workflow = workflow_get_workflows_by_name($name)) {
@@ -156,6 +178,7 @@ function workflow_get_workflows_full_object($name) {
       unset($state->wid);
       $workflow->states[] = $state;
     }
+
     // Now we need to add data to the export for each transition, an array of sub-objects.
     // Same goes for transitions, see above re: states.
     foreach ($active_states as $sid => $state) {
@@ -163,18 +186,76 @@ function workflow_get_workflows_full_object($name) {
       foreach (workflow_get_workflow_transitions_by_sid($sid, $options) as $transition) {
         // And to get the target state (by name) we need to look it up too.
         $target_state = workflow_get_workflow_states_by_sid($transition->target_sid);
-        $transition->sid = $state;
-        $transition->target_sid = $target_state->state;
+        $transition->state = $state;
+        $transition->target_state = $target_state->state;
+        unset($transition->sid, $transition->target_sid);
+        // Translate to role names so works cross install.
+        $transition->roles = !empty($transition->roles) ? _workflow_rids_to_roles($transition->roles) : '';
         // Remove what we don't need to export.
         unset($transition->tid);
         $workflow->transitions[] = $transition;
       }
     }
+
     // Now we need to add data to the export for each type map, an array of sub-objects.
     // Same goes for node mappings, see above re: states.
     foreach (workflow_get_workflow_type_map_by_wid($workflow->wid) as $index => $type_map) {
-      $workflow->node_types[] = $type_map;
+      $workflow->node_types[] = $type_map->type;
     }
   }
   return $workflow;
-}
\ No newline at end of file
+}
+
+/**
+ * Internally cache the user roles as core doesn't.
+ */
+function _workflow_user_roles($reset = FALSE) {
+  $roles = &drupal_static(__FUNCTION__);
+  if ($reset || !isset($roles)) {
+    $roles = user_roles();
+  }
+  return $roles;
+}
+
+/**
+ * Translates a role string to RIDs for importing.
+ *
+ * @param $role_string
+ *   A string of roles or fake 'author' role.
+ *
+ * @return
+ *   A string of RIDs seperated by commas.
+ */
+function _workflow_roles_to_rids($role_string) {
+  $roles = _workflow_user_roles();
+  $rid_array = array();
+  foreach (explode(',', $role_string) as $role_name) {
+    if ($role_name === WORKFLOW_FEATURES_AUTHOR_NAME) {
+      $rid_array[] = 'author';
+    }
+    elseif ($role_name && in_array($role_name, $roles)) {
+      $rid_array[] = array_search($role_name, $roles);
+    }
+  }
+  return implode(',', $rid_array);
+}
+
+/**
+ * Translates a string of rids to role names for exporting.
+ *
+ * @param $rid_string
+ *   A string of rids or fake 'author' role.
+ *
+ * @return
+ *   A string of role names seperated by commas.
+ */
+function _workflow_rids_to_roles($rid_string) {
+  $roles = _workflow_user_roles();
+  $rid_array = explode(',', $rid_string);
+  // There may be a role named 'author', so make 'author' distinct.
+  $return = in_array('author', $rid_array) ? WORKFLOW_FEATURES_AUTHOR_NAME . ',' : '';
+  // Translate RIDs to rolenames.
+  $return .= implode(',', array_intersect_key($roles, array_flip($rid_array)));
+  return trim($return, ',');
+}
+
diff --git a/workflow.module b/workflow.module
index 8a11f9d..efec4be 100644
--- a/workflow.module
+++ b/workflow.module
@@ -424,7 +424,7 @@ function workflow_features_api() {
     'workflow' => array(
       'name' => t('Workflow'),
       'file' => drupal_get_path('module', 'workflow') . '/workflow.features.inc',
-      'default_hook' => 'workflow_features_default_workflow',
+      'default_hook' => 'workflow_default_workflows',
       'feature_source' => TRUE,
     ),
   );
