diff --git a/core/modules/field/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php b/core/modules/field/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
index c3c696a..4213e4b 100644
--- a/core/modules/field/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
+++ b/core/modules/field/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
@@ -43,7 +43,7 @@ class TextTranslationTest extends WebTestBase {
       'bypass node access',
       filter_permission_name($full_html_format),
     ));
-    $this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content'));
+    $this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate all content'));
 
     // Enable an additional language.
     $this->drupalLogin($this->admin);
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
index 09518ab..f9aa0de 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
@@ -31,7 +31,7 @@ class PathLanguageTest extends PathTestBase {
     parent::setUp();
 
     // Create and login user.
-    $this->web_user = $this->drupalCreateUser(array('edit any page content', 'create page content', 'administer url aliases', 'create url aliases', 'administer languages', 'translate content', 'access administration pages'));
+    $this->web_user = $this->drupalCreateUser(array('edit any page content', 'create page content', 'administer url aliases', 'create url aliases', 'administer languages', 'translate all content', 'access administration pages'));
     $this->drupalLogin($this->web_user);
 
     // Enable French language.
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollTranslateTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollTranslateTest.php
index 819b5f7..84cf03f 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollTranslateTest.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollTranslateTest.php
@@ -34,7 +34,7 @@ class PollTranslateTest extends PollTestBase {
    * the vote count values are set to 0.
    */
   function testPollTranslate() {
-    $admin_user = $this->drupalCreateUser(array('administer content types', 'administer languages', 'edit any poll content', 'create poll content', 'administer nodes', 'translate content'));
+    $admin_user = $this->drupalCreateUser(array('administer content types', 'administer languages', 'edit any poll content', 'create poll content', 'administer nodes', 'translate all content'));
 
     // Set up a poll with two choices.
     $title = $this->randomName();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
index f9f76a7..7a30cb0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
@@ -159,4 +159,24 @@ class LanguageUpgradePathTest extends UpgradePathTestBase {
     // whether index 'plural' has been removed.
     $this->assertFalse(db_index_exists('locales_target', 'plural'), t('Translations without plurals upgraded.'));
   }
+
+  /**
+   * Tests upgrading translations permissions.
+   */
+  public function testLanguagePermissionsUpgrade() {
+    db_insert('role_permission')->fields(array(
+      'rid' => 2,
+      'permission' => 'translate content',
+      'module' => 'translation',
+    ))->execute();
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // Check that translate content role doesn't exist on database.
+    $old_permission_exists = db_query('SELECT * FROM {role_permission} WHERE permission LIKE ?', array('translate content'))->fetchObject();
+    $this->assertFalse($old_permission_exists, t('No translate content role left on database.'));
+    // Check that translate content has been renamed to translate all content.
+    $new_permission_exists = db_query('SELECT * FROM {role_permission} WHERE permission LIKE ?', array('translate all content'))->fetchObject();
+    $this->assertTrue($new_permission_exists, t('Rename role translate content to translate all content was completed successfully.'));
+  }
 }
diff --git a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
index a409150..b4f2b6c 100644
--- a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
+++ b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
@@ -38,8 +38,9 @@ class TranslationTest extends WebTestBase {
     parent::setUp();
 
     // Setup users.
-    $this->admin_user = $this->drupalCreateUser(array('bypass node access', 'administer nodes', 'administer languages', 'administer content types', 'administer blocks', 'access administration pages', 'translate content'));
-    $this->translator = $this->drupalCreateUser(array('create page content', 'edit own page content', 'translate content'));
+    $this->admin_user = $this->drupalCreateUser(array('bypass node access', 'administer nodes', 'administer languages', 'administer content types', 'administer blocks', 'access administration pages', 'translate all content'));
+    $this->translator = $this->drupalCreateUser(array('create page content', 'edit own page content', 'translate all content'));
+    $this->limited_translator = $this->drupalCreateUser(array('create page content', 'edit own page content', 'translate own content'));
 
     $this->drupalLogin($this->admin_user);
 
@@ -250,6 +251,35 @@ class TranslationTest extends WebTestBase {
   }
 
   /**
+   * Checks that users with "translate own content" role only can translate own content.
+   */
+  function testTranslateOwnContentRole() {
+    // Create a Basic page in English and its translation in Spanish with user
+    // that has "translate own content" role.
+    $this->drupalLogin($this->limited_translator);
+    $node = $this->createPage($this->randomName(), $this->randomName(), 'en');
+    $this->assertLinkByHref('node/' . $node->nid . '/translate', 0, t('User with "translate own content" role can see translate link'));
+    $this->drupalGet('node/' . $node->nid . '/translate');
+    $this->assertResponse(200, t('User with "translate own content" role can get translate page'));
+    $translation_es = $this->createTranslation($node, $this->randomName(), $this->randomName(), 'es');
+
+    // Create a page as translator user.
+    $this->drupalLogin($this->translator);
+    $node = $this->createPage($this->randomName(), $this->randomName(), 'en');
+    // Change to limited_translator and check that translate links aren't shown.
+    $this->drupalLogin($this->limited_translator);
+    $this->assertNoLinkByHref('node/' . $node->nid . '/translate', t('User with "translate own content" role can\'t see translate link'));
+    // Check if user with "translate own content" role can see translate page
+    // from other user's node.
+    $this->drupalGet('node/' . $node->nid . '/translate');
+    $this->assertResponse(403, t('User with "translate own content" role can\'t get translate page'));
+
+    // Try to change to translate with "brute force".
+    $this->drupalGet('node/add/page', array('query' => array('translation' => $node->nid, 'target' => 'es')));
+    $this->assertResponse(403, t('User with "translate own content" role can\'t get create translate page'));
+  }
+
+  /**
    * Resets static caches to make the test code match the client-side behavior.
    */
   function resetCaches() {
diff --git a/core/modules/translation/translation.install b/core/modules/translation/translation.install
new file mode 100644
index 0000000..d0c5157
--- /dev/null
+++ b/core/modules/translation/translation.install
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Update function for the translation module.
+ */
+
+
+/**
+ * Rename the translate content permission.
+ */
+function translation_update_8000() {
+  db_update('role_permission')
+    ->fields(array('permission' => 'translate all content'))
+    ->condition('permission', 'translate content')
+    ->execute();
+}
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index 909117f..66f1e2d 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -37,7 +37,7 @@ function translation_help($path, $arg) {
       $output .= '<dt>' . t('Assigning a language to content') . '</dt>';
       $output .= '<dd>' . t('Use the <em>Language</em> drop down to select the appropriate language when creating or editing content.') . '</dd>';
       $output .= '<dt>' . t('Translating content') . '</dt>';
-      $output .= '<dd>' . t('Users with the <em>translate content</em> permission can translate content, if the content type has been configured to allow translations. To translate content, select the <em>Translations</em> tab when viewing the content, select the language for which you wish to provide content, and then enter the content.') . '</dd>';
+      $output .= '<dd>' . t('Users with the <em>translate all content</em> permission can translate all content, if the content type has been configured to allow translations. To translate content, select the <em>Translations</em> tab when viewing the content, select the language for which you wish to provide content, and then enter the content.') . '</dd>';
       $output .= '<dt>' . t('Maintaining translations') . '</dt>';
       $output .= '<dd>' . t('If editing content in one language requires that translated versions also be updated to reflect the change, use the <em>Flag translations as outdated</em> check box to mark the translations as outdated and in need of revision. Individual translations may also be marked for revision by selecting the <em>This translation needs to be updated</em> check box on the translation editing form.') . '</dd>';
       $output .= '</dl>';
@@ -67,7 +67,9 @@ function translation_menu() {
 }
 
 /**
- * Access callback: Checks that the user has permission to 'translate content'.
+ * Access callback: Checks that the user has permission to 'translate
+ * all content' or to 'translate own content' and has created the node
+ * being translated.
  *
  * Only displays the translation tab for nodes that are not language-neutral
  * of types that have translation enabled.
@@ -81,8 +83,10 @@ function translation_menu() {
  * @see translation_menu()
  */
 function _translation_tab_access($node) {
+  global $user;
+
   if ($node->langcode != LANGUAGE_NOT_SPECIFIED && translation_supported_type($node->type) && node_access('view', $node)) {
-    return user_access('translate content');
+    return translation_user_can_translate_node($node, $user);
   }
   return FALSE;
 }
@@ -104,13 +108,46 @@ function translation_admin_paths() {
  */
 function translation_permission() {
   return array(
-    'translate content' => array(
-      'title' => t('Translate content'),
+    'translate all content' => array(
+      'title' => t('Translate all content'),
+    ),
+    'translate own content' => array(
+      'title' => t('Translate own content'),
     ),
   );
 }
 
 /**
+ * Implements hook_node_access().
+ */
+function translation_node_access($node, $op, $account, $langcode) {
+  $request_has_translation_arg = isset($_GET['translation']) && isset($_GET['target']) && is_numeric($_GET['translation']);
+  if ($op == 'create' && $request_has_translation_arg) {
+    $source_node = node_load($_GET['translation']);
+    if (empty($source_node) || !translation_user_can_translate_node($source_node, $account)){
+      return NODE_ACCESS_DENY;
+    }
+  }
+
+  return NODE_ACCESS_IGNORE;
+}
+
+/**
+ * Check if the user has permissions to translate a node.
+ *
+ * @param $node
+ *   Node being checked.
+ * @param $account
+ *   User object to check translation permissions.
+ *
+ * @return
+ *   TRUE if the user can translate a node, FALSE otherwise.
+ */
+function translation_user_can_translate_node($node, $account) {
+  return node_access('view', $node, $account) && (user_access('translate all content', $account) || ($node->uid == $account->uid && user_access('translate own content', $account)));
+}
+
+/**
  * Implements hook_form_FORM_ID_alter() for node_type_form().
  */
 function translation_form_node_type_form_alter(&$form, &$form_state) {
@@ -155,6 +192,7 @@ function translation_node_type_language_translation_enabled_validate($element, &
 function translation_form_node_form_alter(&$form, &$form_state) {
   $node = $form_state['controller']->getEntity($form_state);
   if (translation_supported_type($node->type)) {
+    global $user;
     if (!empty($node->translation_source)) {
       // We are creating a translation. Add values and lock language field.
       $form['translation_source'] = array('#type' => 'value', '#value' => $node->translation_source);
@@ -175,7 +213,7 @@ function translation_form_node_form_alter(&$form, &$form_state) {
       $form['translation'] = array(
         '#type' => 'fieldset',
         '#title' => t('Translation settings'),
-        '#access' => user_access('translate content'),
+        '#access' => translation_user_can_translate_node($node, $user),
         '#collapsible' => TRUE,
         '#collapsed' => !$node->translate,
         '#tree' => TRUE,
@@ -265,24 +303,17 @@ function translation_node_view(Node $node, $view_mode) {
  * Implements hook_node_prepare().
  */
 function translation_node_prepare(Node $node) {
+  global $user;
   // Only act if we are dealing with a content type supporting translations.
   if (translation_supported_type($node->type) &&
     // And it's a new node.
     empty($node->nid) &&
-    // And the user has permission to translate content.
-    user_access('translate content') &&
     // And the $_GET variables are set properly.
     isset($_GET['translation']) &&
     isset($_GET['target']) &&
     is_numeric($_GET['translation'])) {
 
     $source_node = node_load($_GET['translation']);
-    if (empty($source_node) || !node_access('view', $source_node)) {
-      // Source node not found or no access to view. We should not check
-      // for edit access, since the translator might not have permissions
-      // to edit the source node but should still be able to translate.
-      return;
-    }
 
     $language_list = language_list();
     $langcode = $_GET['target'];
