diff --git a/entity_translation.admin.inc b/entity_translation.admin.inc
index f1ccf6e..b7a7d5f 100644
--- a/entity_translation.admin.inc
+++ b/entity_translation.admin.inc
@@ -85,7 +85,6 @@ function entity_translation_overview($entity_type, $entity, $callback = NULL) {
   $header = array(t('Language'), t('Source language'), t('Translation'), t('Status'), t('Operations'));
   $languages = entity_translation_languages();
   $source = $translations->original;
-  $base_path = $handler->getBasePath();
   $path = $handler->getViewPath();
   $rows = array();
 
@@ -101,9 +100,9 @@ function entity_translation_overview($entity_type, $entity, $callback = NULL) {
       $language_name = $language->name;
       $langcode = $language->language;
       $edit_path = $handler->getEditPath($langcode);
-      $add_path = "$base_path/edit/add/$source/$langcode";
+      $add_path = "{$handler->getEditPath()}/add/$source/$langcode";
 
-      if ($base_path) {
+      if ($edit_path) {
         $add_links = EntityTranslationDefaultHandler::languageSwitchLinks($add_path);
         $edit_links = EntityTranslationDefaultHandler::languageSwitchLinks($edit_path);
       }
@@ -227,7 +226,7 @@ function entity_translation_delete_confirm($form, $form_state, $entity_type, $en
   return confirm_form(
     $form,
     t('Are you sure you want to delete the @language translation of %label?', array('@language' => $languages[$langcode]->name, '%label' => $handler->getLabel())),
-    "{$handler->getBasePath()}/edit/$langcode",
+    $handler->getEditPath($langcode),
     t('This action cannot be undone.'),
     t('Delete'),
     t('Cancel')
@@ -250,7 +249,7 @@ function entity_translation_delete_confirm_submit($form, &$form_state) {
   // Remove any existing path alias for the removed translation.
   path_delete(array('source' => $handler->getViewPath(), 'language' => $langcode));
 
-  $form_state['redirect'] = "{$handler->getBasePath()}/translate";
+  $form_state['redirect'] = $handler->getTranslatePath();
 }
 
 /*
diff --git a/entity_translation.api.php b/entity_translation.api.php
index c048d11..7176d65 100644
--- a/entity_translation.api.php
+++ b/entity_translation.api.php
@@ -16,11 +16,12 @@
  * To make Entity Translation automatically support an entity type some keys
  * may need to be defined, but none of them is required except the 'base path'
  * key if the entity path is different from ENTITY_TYPE/%ENTITY_TYPE (e.g.
- * taxonomy/term/1). The 'base path' key is used to attach the 'Translate' tab
- * and to reliably alter menu information to provide the translation UI. If the
- * entity path matches the default pattern above, and there is no need for a
- * dedicated translation handler class, Entity Translation will provide built-in
- * support for the entity.
+ * taxonomy/term/1). The 'base path' key is used to determine the view, edit and
+ * translate path if they follow the default path patterns  and to reliably
+ * alter menu information to provide the translation UI. If the entity path
+ * matches the default pattern above, and there is no need for a dedicated
+ * translation handler class, Entity Translation will provide built-in support
+ * for the entity.
  *
  * The entity translation info is an associative array that has to match the
  * following structure. Three nested sub-arrays keyed respectively by entity
@@ -39,8 +40,18 @@
  *   the base path.
  * - edit path: The menu router path to be used to edit the entity. Defaults to
  *   "$base_path/edit".
+ * - translate path: The menu router path to be used for attaching the
+ *   translation UI. Defaults to "$base_path/translate".
  * - path wildcard: The menu router path wildcard identifying the entity.
  *   Defaults to %ENTITY_TYPE.
+ * - path schemes: An array of menu router path schemes used for attaching the
+ *   entity translation UI. This element can be used to declare additional path
+ *   schemes, if an entity type uses multiple schemes for managing entities
+ *   (e.g. different schemes for different bundles). Each path scheme can define
+ *   the following elements (descriptions see above): 'base path', 'view path',
+ *   'edit path', 'translate path', and 'path wildcard'. All path elements that
+ *   are defined on the entity translation info array directly are automatically
+ *   added as a 'default' path scheme.
  * - theme callback: The callback to be used to determine the translation
  *   theme. Defaults to 'variable_get'.
  * - theme arguments: The arguments to be used to determine the translation
@@ -62,6 +73,26 @@ function hook_entity_info() {
     ),
   );
 
+  // Entity type which has multiple (e.g. bundle-specific) paths.
+  $info['custom_entity_2'] = array(
+    'translation' => array(
+      'entity_translation' => array(
+        'class' => 'EntityTranslationCustomEntityHandler',
+        'path sets' => array(
+          'default' => array(
+            'base path' => 'custom_entity_2/%custom_entity',
+            'path wildcard' => '%custom_entity',
+          ),
+          'fancy' => array(
+            // Base path is not required.
+            'edit path' => 'fancy/%entity/edit',
+            'path wildcard' => '%entity',
+          ),
+        ),
+      )
+    )
+  );
+
   return $info;
 }
 
diff --git a/entity_translation.module b/entity_translation.module
index 01934df..ee627b6 100644
--- a/entity_translation.module
+++ b/entity_translation.module
@@ -91,42 +91,65 @@ function entity_translation_entity_info() {
  * Implements hook_entity_info_alter().
  */
 function entity_translation_entity_info_alter(&$entity_info) {
-  $edit_form_info = array();
-
   // Provide defaults for translation info.
   foreach ($entity_info as $entity_type => $info) {
     if (!isset($entity_info[$entity_type]['translation']['entity_translation'])) {
       $entity_info[$entity_type]['translation']['entity_translation'] = array();
     }
+    $et_info = &$entity_info[$entity_type]['translation']['entity_translation'];
 
     // Every fieldable entity type must have a translation handler class, no
     // matter if it is enabled for translation or not. As a matter of fact we
     // might need it to correctly switch field translatability when a field is
     // shared accross different entities.
-    $entity_info[$entity_type]['translation']['entity_translation'] += array('class' => 'EntityTranslationDefaultHandler');
+    $et_info += array('class' => 'EntityTranslationDefaultHandler');
 
     if (entity_translation_enabled($entity_type, TRUE)) {
       $entity_info[$entity_type]['language callback'] = 'entity_translation_language';
 
+      // Insert the default path scheme into the 'path schemes' array and remove
+      // respective elements from the entity_translation info array.
+      static $path_scheme_keys = array('base path', 'view path', 'edit path', 'translate path', 'path wildcard');
+      $default_scheme = array_intersect_key($et_info, array_flip($path_scheme_keys));
+      if (!empty($default_scheme)) {
+        $et_info['path schemes']['default'] = $default_scheme;
+        $et_info = array_diff_key($et_info, array_flip($path_scheme_keys));
+      }
+
       // If no base path is provided we default to the common "node/%node"
       // pattern.
-      if (!isset($entity_info[$entity_type]['translation']['entity_translation']['base path'])) {
-        $path = "$entity_type/%$entity_type";
-        $entity_info[$entity_type]['translation']['entity_translation']['base path'] = $path;
+      if (empty($et_info['path schemes']['default']['base path'])) {
+        $et_info['path schemes']['default']['base path'] = "$entity_type/%$entity_type";
       }
 
-      $path = $entity_info[$entity_type]['translation']['entity_translation']['base path'];
+      foreach ($et_info['path schemes'] as $delta => $scheme) {
+        // If there is a base path, then we automatically create the other path
+        // elements based on the base path.
+        if (!empty($scheme['base path'])) {
+          $view_path = $scheme['base path'];
+          $edit_path = $scheme['base path'] . '/edit';
+          $translate_path = $scheme['base path'] . '/translate';
+
+          $et_info['path schemes'][$delta] += array(
+            'view path' => $view_path,
+            'edit path' => $edit_path,
+            'translate path' => $translate_path,
+          );
+        }
+
+        // Set default path wildcard if it hasn't been set.
+        $et_info['path schemes'][$delta] += array(
+          'path wildcard' => "%$entity_type",
+        );
+      }
 
-      $entity_info[$entity_type]['translation']['entity_translation'] += array(
-        'view path' => $path,
-        'edit path' => "$path/edit",
-        'path wildcard' => "%$entity_type",
+      // Merge in default values for remaining keys.
+      $et_info += array(
         'access callback' => 'entity_translation_tab_access',
         'access arguments' => array($entity_type),
       );
 
       // Interpret a TRUE value for the 'edit form' key as the default value.
-      $et_info = &$entity_info[$entity_type]['translation']['entity_translation'];
       if (!isset($et_info['edit form']) || $et_info['edit form'] === TRUE) {
         $et_info['edit form'] = $entity_type;
       }
@@ -167,126 +190,242 @@ function entity_translation_menu() {
 }
 
 /**
+ * Validate the given set of path schemes and remove invalid elements.
+ *
+ * Each path scheme needs to fulfill the following requirements:
+ * - The 'path wildcard' key needs to be specified.
+ * - Every path (base/view/edit/translate) needs to contain the path wildcard.
+ * - The following path definitions (if specified) need to match existing menu
+ *   items: 'base path', 'view path', 'edit path'.
+ * - The 'translate path' definition needs to have an existing parent menu item.
+ *
+ * This function needs to be called once with a list of menu items passed as the
+ * last parameter, before it can be used for validation.
+ *
+ * @param $schemes
+ *   The array of path schemes.
+ * @param $entity_type_label
+ *   The label of the current entity type. This is used in error messages.
+ * @param $items
+ *   A list of menu items.
+ */
+function _entity_translation_validate_path_schemes(&$schemes, $entity_type_label, $items = FALSE) {
+  $paths = &drupal_static(__FUNCTION__);
+  static $regex = '|%[^/]+|';
+
+  if (!empty($items)) {
+    // Some menu loaders in the item paths might have been altered: we need to
+    // replace any menu loader with a plain % to check if base paths are still
+    // compatible.
+    $paths = array();
+    foreach ($items as $path => $item) {
+      $path = preg_replace($regex, '%', $path);
+      $paths[$path] = $path;
+    }
+  }
+
+  if (empty($schemes)) return;
+
+  // Make sure we have a set of paths to validate the scheme against.
+  if (empty($paths)) {
+    // This should never happen.
+    throw new Exception('The ET path scheme validation function has not been initialized properly.');
+  }
+
+  foreach ($schemes as $delta => $scheme) {
+    // Every path scheme needs to declare a path wildcard for the entity id.
+    if (empty($scheme['path wildcard'])) {
+      drupal_set_message(t('ET path scheme %scheme for entities of type %entity_type does not declare a path wildcard.', array(
+        '%scheme' => $delta,
+        '%entity_type' => $entity_type_label,
+      )));
+      unset($schemes[$delta]);
+      continue;
+    }
+    $wildcard = $scheme['path wildcard'];
+
+    $validate_keys = array('base path' => FALSE, 'view path' => FALSE, 'edit path' => FALSE, 'translate path' => TRUE);
+    foreach ($validate_keys as $key => $check_parent) {
+      if (isset($scheme[$key])) {
+        $path = $scheme[$key];
+        $parts = explode('/', $path);
+        $schemes[$delta][$key . ' parts'] = $parts;
+
+        // Check that that the path contains the path wildcard.
+        if (!in_array($wildcard, $parts)) {
+          drupal_set_message(t('Invalid %path_key defined for entities of type %entity_type: entity wildcard %wildcard not found in %path.', array(
+            '%path_key' => $key, '%entity_type' => $entity_type_label, '%wildcard' => $wildcard, '%path' => $path,
+          )), 'warning');
+        }
+
+        // Check that the current element has a parent path which matches an
+        // existing menu path.
+        if ($check_parent) {
+          $parent_path = implode('/', array_slice($parts, 0, -1));
+          if (!isset($paths[preg_replace($regex, '%', $parent_path)])) {
+            drupal_set_message(t('Invalid %path_key defined for entities of type %entity_type: parent menu item not found for %path', array(
+              '%path_key' => $key, '%entity_type' => $entity_type_label, '%path' => $path,
+            )),'warning');
+            unset($schemes[$delta]['translate path']);
+          }
+        }
+        // Check that the current element matches an existing menu path.
+        else if (!isset($paths[preg_replace($regex, '%', $path)])) {
+          drupal_set_message(t('Invalid %path_key defined for entities of type %entity_type: matching menu item not found for %path', array(
+            '%path_key' => $key, '%entity_type' => $entity_type_label, '%path' => $path,
+          )), 'warning');
+          unset($schemes[$delta][$key]);
+        }
+      }
+    }
+  }
+}
+
+/**
  * Implements hook_menu_alter().
  */
 function entity_translation_menu_alter(&$items) {
   $backup = array();
   $languages = entity_translation_languages();
 
-  // Some menu loaders in the item paths might have been altered: we need to
-  // replace any menu loader with a plain % to check if base paths are still
-  // compatible.
-  $paths = array();
-  $regex = '|%[^/]+|';
-  foreach ($items as $path => $item) {
-    $path = preg_replace($regex, '%', $path);
-    $paths[$path] = $path;
-  }
+  // Initialise path schemes validation function with set of current menu items.
+  $_null = NULL;
+  _entity_translation_validate_path_schemes($_null, FALSE, $items);
 
   // Create tabs for all possible entity types.
   foreach (entity_get_info() as $entity_type => $info) {
     // Menu is rebuilt while determining entity translation base paths and
     // callbacks so we might not have them available yet.
     if (entity_translation_enabled($entity_type)) {
-      // Extract informations from the bundle description.
-      $path = $info['translation']['entity_translation']['base path'];
-
-      // If the base path is not defined or is not compatible with any defined
-      // one we cannot provide the translation UI for this entity type.
-      if (!isset($paths[preg_replace($regex, '%', $path)])) {
-        drupal_set_message(t('The entities of type %entity_type do not define a valid base path: it will not be possible to translate them.', array('%entity_type' => $info['label'])), 'warning');
-        continue;
-      }
+      $et_info = $info['translation']['entity_translation'];
 
-      $keys = array('theme callback', 'theme arguments', 'access callback', 'access arguments', 'load arguments');
-      $item = array_intersect_key($info['translation']['entity_translation'], drupal_map_assoc($keys));
+      // Flag for tracking whether we have managed to attach the translate UI
+      // successfully at least once.
+      $translate_ui_attached = FALSE;
 
-      $item += array(
-        'file' => 'entity_translation.admin.inc',
-        'module' => 'entity_translation',
-      );
+      // Validate path schemes for current entity type. Also removes invalid
+      // ones and adds '... path parts' elements.
+      _entity_translation_validate_path_schemes($et_info['path schemes'], $info['label']);
 
-      $entity_position = count(explode('/', $path)) - 1;
-      $source_position = $entity_position + 4;
-      $language_position = $entity_position + 3;
+      foreach ($et_info['path schemes'] as $delta => $scheme) {
+        $translate_item = NULL;
+        $edit_item = NULL;
 
-      // Backup existing values for the translate overview page.
-      if (isset($items["$path/translate"])) {
-        $backup[$entity_type] = $items["$path/translate"];
-      }
+        // If we have a translate path then attach the translation UI, and
+        // register the callback for deleting a translation.
+        if (isset($scheme['translate path'])) {
+          $translate_path = $scheme['translate path'];
 
-      $items["$path/translate"] = array(
-        'title' => 'Translate',
-        'page callback' => 'entity_translation_overview',
-        'page arguments' => array($entity_type, $entity_position),
-        'type' => MENU_LOCAL_TASK,
-        'weight' => 2,
-      ) + $item;
+          $keys = array('theme callback', 'theme arguments', 'access callback', 'access arguments', 'load arguments');
+          $item = array_intersect_key($info['translation']['entity_translation'], drupal_map_assoc($keys));
 
-      $et_info = $info['translation']['entity_translation'];
-      $edit_path = $et_info['edit path'];
-
-      if (isset($items[$edit_path])) {
-        // If the edit path is a default local task we need to find the parent
-        // item.
-        $edit_path_split = explode('/', $edit_path);
-        do {
-          $edit_form_item = &$items[implode('/', $edit_path_split)];
-          array_pop($edit_path_split);
+          $item += array(
+            'file' => 'entity_translation.admin.inc',
+            'module' => 'entity_translation',
+          );
+
+          $entity_position = array_search($scheme['path wildcard'], $scheme['translate path parts']);
+
+          // Backup existing values for the translate overview page.
+          if (isset($items[$translate_path])) {
+            $backup[$entity_type] = $items[$translate_path];
+          }
+
+          $items[$translate_path] = array(
+            'title' => 'Translate',
+            'page callback' => 'entity_translation_overview',
+            'page arguments' => array($entity_type, $entity_position),
+            'type' => MENU_LOCAL_TASK,
+            'weight' => 2,
+          ) + $item;
+
+          // Delete translation callback.
+          $language_position = count($scheme['translate path parts']) + 1;
+          $items["$translate_path/delete/%entity_translation_language"] = array(
+            'title' => 'Delete',
+            'page callback' => 'drupal_get_form',
+            'page arguments' => array('entity_translation_delete_confirm', $entity_type, $entity_position, $language_position),
+          ) + $item;
+
+          $translate_item = &$items[$translate_path];
         }
-        while (!empty($edit_form_item['type']) && $edit_form_item['type'] == MENU_DEFAULT_LOCAL_TASK);
 
-        // Make the "Translate" local task follow the "Edit" one when possibile.
-        if (isset($edit_form_item['weight'])) {
-          $items["$path/translate"]['weight'] = $edit_form_item['weight'] + 1;
+        // If we have an edit path, then replace the menu edit form with our
+        // proxy implementation, and register new callbacks for adding and
+        // editing a translation.
+        if (isset($scheme['edit path'])) {
+          $edit_path = $scheme['edit path'];
+          $edit_path_parts = $scheme['edit path parts'];
+
+          // If the edit path is a default local task we need to find the parent
+          // item.
+          do {
+            $edit_item = &$items[implode('/', $edit_path_parts)];
+            array_pop($edit_path_parts);
+          }
+          while (!empty($edit_item['type']) && $edit_item['type'] == MENU_DEFAULT_LOCAL_TASK);
+
+          // Reset edit path parts to ensure proper position calculations.
+          $edit_path_parts = $scheme['edit path parts'];
+
+          // Replace the main edit callback with our proxy implementation to set
+          // form language to the current language and check access.
+          $entity_position = array_search($scheme['path wildcard'], $edit_path_parts);
+          $original_item = $edit_item;
+          $args = array($entity_type, $entity_position, FALSE, $original_item);
+          $edit_item['page callback'] = 'entity_translation_edit_page';
+          $edit_item['page arguments'] = array_merge($args, $original_item['page arguments']);
+          $edit_item['access callback'] = 'entity_translation_edit_access';
+          $edit_item['access arguments'] = array_merge($args, $original_item['access arguments']);
+
+          // Edit translation callback.
+          $translation_position = count($edit_path_parts);
+          $args = array($entity_type, $entity_position, $translation_position, $original_item);
+          $items["$edit_path/%entity_translation_language"] = array(
+            'type' => MENU_DEFAULT_LOCAL_TASK,
+            'title callback' => 'entity_translation_edit_title',
+            'title arguments' => array($translation_position),
+            'page callback' => 'entity_translation_edit_page',
+            'page arguments' => array_merge($args, $original_item['page arguments']),
+            'access callback' => 'entity_translation_edit_access',
+            'access arguments' => array_merge($args, $original_item['access arguments']),
+          )
+          // We need to inherit the remaining menu item keys, mostly 'module' and
+          // 'file' to keep ajax callbacks working (see drupal_retrieve_form() and
+          // form_get_cache()).
+          + $original_item;
+
+          // Add translation callback.
+          $add_path = "$edit_path/add/%entity_translation_language/%entity_translation_language";
+          $source_position = count($edit_path_parts) + 1;
+          $target_position = count($edit_path_parts) + 2;
+          $args = array($entity_type, $entity_position, $source_position, $target_position, $original_item);
+          $items[$add_path] = array(
+            'title callback' => 'Add translation',
+            'page callback' => 'entity_translation_add_page',
+            'page arguments' => array_merge($args, $original_item['page arguments']),
+            'type' => MENU_LOCAL_TASK,
+            'access callback' => 'entity_translation_add_access',
+            'access arguments' => array_merge($args, $original_item['access arguments']),
+          ) + $original_item;
         }
 
-        // Replace the main edit callback with our proxy implementation to set
-        // form language to the current language and check access.
-        $entity_position = count(explode('/', $et_info['base path'])) - 1;
-        $edit_position = count(explode('/', $edit_path)) - 1;
-        $original_item = $edit_form_item;
-        $args = array($entity_type, $entity_position, FALSE, $original_item);
-        $edit_form_item['page callback'] = 'entity_translation_edit_page';
-        $edit_form_item['page arguments'] = array_merge($args, $original_item['page arguments']);
-        $edit_form_item['access callback'] = 'entity_translation_edit_access';
-        $edit_form_item['access arguments'] = array_merge($args, $original_item['access arguments']);
-
-        // Edit translation callback.
-        $translation_position = $edit_position + 1;
-        $args = array($entity_type, $entity_position, $translation_position, $original_item);
-        $items["$edit_path/%entity_translation_language"] = array(
-          'type' => MENU_DEFAULT_LOCAL_TASK,
-          'title callback' => 'entity_translation_edit_title',
-          'title arguments' => array($translation_position),
-          'page callback' => 'entity_translation_edit_page',
-          'page arguments' => array_merge($args, $original_item['page arguments']),
-          'access callback' => 'entity_translation_edit_access',
-          'access arguments' => array_merge($args, $original_item['access arguments']),
-        )
-        // We need to inherit the remaining menu item keys, mostly 'module' and
-        // 'file' to keep ajax callbacks working (see drupal_retrieve_form() and
-        // form_get_cache()).
-        + $original_item;
-
-        // Add translation callback.
-        $add_path = "$edit_path/add/%entity_translation_language/%entity_translation_language";
-        $source_position = $edit_position + 2;
-        $items[$add_path] = array(
-          'title callback' => 'Add translation',
-          'page callback' => 'entity_translation_add_page',
-          'page arguments' => array_merge(array($entity_type, $entity_position, $source_position, $source_position + 1, $original_item), $original_item['page arguments']),
-          'type' => MENU_LOCAL_TASK,
-          'access callback' => 'entity_translation_add_access',
-          'access arguments' => array_merge(array($entity_type, $entity_position, $source_position, $source_position + 1, $original_item), $original_item['access arguments']),
-        ) + $original_item;
-
-        // Delete translation callback.
-        $items["$path/translate/delete/%entity_translation_language"] = array(
-          'title' => 'Delete',
-          'page callback' => 'drupal_get_form',
-          'page arguments' => array('entity_translation_delete_confirm', $entity_type, $entity_position, $language_position),
-        ) + $item;
+        // Make the "Translate" tab follow the "Edit" tab if possible.
+        if ($translate_item && $edit_item && isset($edit_item['weight'])) {
+          $translate_item['weight'] = $edit_item['weight'] + 1;
+        }
+
+        // If we have both an edit item and a translate item, then we know that
+        // the translate UI has been attached properly (at least once).
+        $translate_ui_attached = $translate_ui_attached || ($translate_item && $edit_item);
+
+        // Cleanup reference variables, so we don't accidentially overwrite
+        // something in a later iteration.
+        unset($translate_item, $edit_item);
+      }
+
+      if ($translate_ui_attached == FALSE) {
+        drupal_set_message(t('The entities of type %entity_type do not define a valid path scheme: it will not be possible to translate them.', array('%entity_type' => $info['label'])), 'warning');
       }
     }
   }
@@ -458,13 +597,18 @@ function entity_translation_admin_paths() {
     if ($entity_type == 'node' && !variable_get('node_admin_theme')) {
       continue;
     }
-    if (entity_translation_enabled($entity_type, TRUE) && isset($info['translation']['entity_translation']['base path'])) {
-      $base_path = preg_replace('|%[^/]*|', '*', $info['translation']['entity_translation']['base path']);
-      $paths["$base_path/translate"] = TRUE;
-      $paths["$base_path/translate/*"] = TRUE;
-
-      $edit_path = preg_replace('|%[^/]*|', '*', $info['translation']['entity_translation']['edit path']);
-      $paths["$edit_path/*"] = TRUE;
+    if (entity_translation_enabled($entity_type, TRUE)) {
+      foreach ($info['translation']['entity_translation']['path schemes'] as $scheme) {
+        if (isset($scheme['translate path'])) {
+          $translate_path = preg_replace('|%[^/]*|', '*', $scheme['translate path']);
+          $paths[$translate_path] = TRUE;
+          $paths["$translate_path/*"] = TRUE;
+        }
+        if (isset($scheme['edit path'])) {
+          $edit_path = preg_replace('|%[^/]*|', '*', $scheme['edit path']);
+          $paths["$edit_path/*"] = TRUE;
+        }
+      }
     }
   }
   return $paths;
@@ -1068,7 +1212,7 @@ function entity_translation_entity_form_source_language_submit($form, &$form_sta
  */
 function entity_translation_entity_form_delete_translation_submit($form, &$form_state) {
   $handler = entity_translation_entity_form_get_handler($form, $form_state);
-  $form_state['redirect'] = "{$handler->getBasePath()}/translate/delete/{$handler->getFormLanguage()}";
+  $form_state['redirect'] = "{$handler->getTranslatePath()}/delete/{$handler->getFormLanguage()}";
 }
 
 /**
diff --git a/includes/translation.handler.inc b/includes/translation.handler.inc
index 5c64f3b..46579f2 100644
--- a/includes/translation.handler.inc
+++ b/includes/translation.handler.inc
@@ -139,11 +139,24 @@ interface EntityTranslationHandlerInterface {
   public function getEditPath($langcode = NULL);
 
   /**
+   * Returns the path of the translation overview page.
+   */
+  public function getTranslatePath();
+
+  /**
    * Returns the path of the entity view page.
    */
   public function getViewPath();
 
   /**
+   * Changes the active path scheme.
+   *
+   * @param $scheme
+   *   The new path scheme.
+   */
+  public function switchPathScheme($scheme);
+
+  /**
    * A string allowing the user to identify the entity.
    */
   public function getLabel();
@@ -231,8 +244,11 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
   private $formLanguage;
   private $sourceLanguage;
 
+  private $activePathScheme;
+  private $pathWildcard;
   private $basePath;
   private $editPath;
+  private $translatePath;
   private $viewPath;
 
   /**
@@ -257,11 +273,9 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
     $this->outdated = FALSE;
     $this->formLanguage = FALSE;
     $this->sourceLanguage = FALSE;
+    $this->activePathScheme = 'default';
 
-    $info = $entity_info['translation']['entity_translation'];
-    $this->basePath = $this->getPathInstance($info['base path']);
-    $this->editPath = isset($info['edit path']) ? $this->getPathInstance($info['edit path']) : FALSE;
-    $this->viewPath = isset($info['view path']) ? $this->getPathInstance($info['view path']) : FALSE;
+    $this->initPathVariables();
   }
 
   /**
@@ -629,7 +643,14 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
    * @see EntityTranslationHandlerInterface::getEditPath()
    */
   public function getEditPath($langcode = NULL) {
-    return empty($langcode) ? $this->editPath : $this->editPath . '/' . $langcode;
+    return empty($this->editPath) ? FALSE : empty($langcode) ? $this->editPath : $this->editPath . '/' . $langcode;
+  }
+
+  /**
+   * @see EntityTranslationHandlerInterface::getTranslatePath()
+   */
+  public function getTranslatePath() {
+    return $this->translatePath;
   }
 
   /**
@@ -640,6 +661,16 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
   }
 
   /**
+   * @see EntityTranslationHandlerInterface::switchPathScheme()
+   */
+  public function switchPathScheme($scheme) {
+    if ($scheme != $this->activePathScheme) {
+      $this->activePathScheme = $scheme;
+      $this->initPathVariables();
+    }
+  }
+
+  /**
    * @see EntityTranslationHandlerInterface::getLabel()
    */
   public function getLabel() {
@@ -1074,6 +1105,24 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
   }
 
   /**
+   * Initializes handler path variables based on the active path scheme.
+   *
+   * @throws Exception
+   */
+  private function initPathVariables() {
+    if (empty($this->activePathScheme) || !isset($this->entityInfo['translation']['entity_translation']['path schemes'][$this->activePathScheme])) {
+      throw new Exception("Cannot initialize entity translation path variables (invalid path scheme).");
+    }
+
+    $path_scheme = $this->entityInfo['translation']['entity_translation']['path schemes'][$this->activePathScheme];
+    $this->pathWildcard = $path_scheme['path wildcard'];
+    $this->basePath = isset($path_scheme['base path']) ? $this->getPathInstance($path_scheme['base path']) : FALSE;
+    $this->editPath = isset($path_scheme['edit path']) ? $this->getPathInstance($path_scheme['edit path']) : FALSE;
+    $this->translatePath = isset($path_scheme['translate path']) ? $this->getPathInstance($path_scheme['translate path']) : FALSE;
+    $this->viewPath = isset($path_scheme['view path']) ? $this->getPathInstance($path_scheme['view path']) : FALSE;
+  }
+
+  /**
    * Returns an instance of the given path.
    *
    * @param $path
@@ -1083,8 +1132,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
    *   The instantiated path.
    */
   protected function getPathInstance($path) {
-    $wildcard = $this->entityInfo['translation']['entity_translation']['path wildcard'];
-    return str_replace($wildcard, $this->getEntityId(), $path);
+    return str_replace($this->pathWildcard, $this->getEntityId(), $path);
   }
 
   /**
diff --git a/views/entity_translation_handler_field_translate_link.inc b/views/entity_translation_handler_field_translate_link.inc
index bc8d8b9..f41ffed 100644
--- a/views/entity_translation_handler_field_translate_link.inc
+++ b/views/entity_translation_handler_field_translate_link.inc
@@ -86,10 +86,10 @@ class entity_translation_handler_field_translate_link extends views_handler_fiel
     // We use the entity info here to avoid having to call entity_load() for all
     // the entities.
     $info = entity_get_info($entity_type);
-    $path = $info['translation']['entity_translation']['base path'];
-    $path = str_replace($info['translation']['entity_translation']['path wildcard'], $entity_id, $path);
+    $path = $info['translation']['entity_translation']['path schemes']['default']['translate path'];
+    $path = str_replace($info['translation']['entity_translation']['path schemes']['default']['path wildcard'], $entity_id, $path);
     $this->options['alter']['make_link'] = TRUE;
-    $this->options['alter']['path'] = $path . '/translate';
+    $this->options['alter']['path'] = $path;
     $this->options['alter']['query'] = drupal_get_destination();
     $text = !empty($this->options['text']) ? $this->options['text'] : t('translate');
     return $text;
