Commit 5d2c8253 authored by catch's avatar catch

Issue #1952062 by vijaycs85, willyk, pfrenssen, vasi1186, CMS Dude,...

Issue #1952062 by vijaycs85, willyk, pfrenssen, vasi1186, CMS Dude, manningpete, penyaskito, kfritsche, Gábor Hojtsy: Remove legacy translation module in favor of content translation.
parent 1aeee1cd
......@@ -130,7 +130,6 @@
* 'promote' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
* 'moderate' => array('type' => 'int', 'not null' => TRUE,'default' => 0),
* 'sticky' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
* 'tnid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
* 'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
* ),
* 'indexes' => array(
......@@ -142,7 +141,6 @@
* 'node_title_type' => array('title', array('type', 4)),
* 'node_type' => array(array('type', 4)),
* 'uid' => array('uid'),
* 'tnid' => array('tnid'),
* 'translate' => array('translate'),
* ),
* 'unique keys' => array(
......
......@@ -396,11 +396,6 @@ public static function baseFieldDefinitions($entity_type) {
'description' => t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'),
'type' => 'boolean_field',
);
$properties['tnid'] = array(
'label' => t('Translation set ID'),
'description' => t('The translation set id for this node, which equals the node id of the source post in each set.'),
'type' => 'integer_field',
);
$properties['translate'] = array(
'label' => t('Translate'),
'description' => t('A boolean indicating whether this translation page needs to be updated.'),
......
......@@ -33,9 +33,6 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
// Don't add the additional fields to groupby
if (!empty($this->options['link_to_node'])) {
$this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
if (module_exists('translation')) {
$this->additional_fields['langcode'] = array('table' => 'node', 'field' => 'langcode');
}
}
}
......
......@@ -31,9 +31,6 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
if (!empty($this->options['link_to_node_revision'])) {
$this->additional_fields['vid'] = 'vid';
$this->additional_fields['nid'] = 'nid';
if (module_exists('translation')) {
$this->additional_fields['langcode'] = array('table' => 'node', 'field' => 'langcode');
}
}
}
protected function defineOptions() {
......@@ -66,13 +63,6 @@ protected function renderLink($data, ResultRow $values) {
$nid = $this->getValue($values, 'nid');
$vid = $this->getValue($values, 'vid');
$this->options['alter']['path'] = "node/" . $nid . '/revisions/' . $vid . '/view';
if (module_exists('translation')) {
$langcode = $this->getValue($values, 'langcode');
$languages = language_list();
if (isset($languages[$langcode])) {
$this->options['alter']['langcode'] = $languages[$langcode];
}
}
}
else {
return parent::renderLink($data, $values);
......
......@@ -50,7 +50,6 @@ function testNodeTokenReplacement() {
$tests = array();
$tests['[node:nid]'] = $node->id();
$tests['[node:vid]'] = $node->getRevisionId();
$tests['[node:tnid]'] = $node->tnid->value;
$tests['[node:type]'] = 'article';
$tests['[node:type-name]'] = 'Article';
$tests['[node:title]'] = check_plain($node->getTitle());
......
......@@ -50,15 +50,6 @@ function node_schema() {
'not null' => TRUE,
'default' => '',
),
// @todo Remove the following columns when removing the legacy Content
// Translation module. See http://drupal.org/node/1952062.
'tnid' => array(
'description' => 'The translation set ID for this node, which equals the node ID of the source post in each set.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'translate' => array(
'description' => 'A boolean indicating whether this translation page needs to be updated.',
'type' => 'int',
......@@ -68,7 +59,6 @@ function node_schema() {
),
'indexes' => array(
'node_type' => array(array('type', 4)),
'tnid' => array('tnid'),
'translate' => array('translate'),
),
'unique keys' => array(
......
......@@ -2188,22 +2188,6 @@ function node_library_info() {
return $libraries;
}
/**
* Implements hook_system_info_alter().
*
* The Content Translation module is deprecated in Drupal 8 in favor of the
* Entity Translation and is planned for removal. Until an upgrade path is
* available, it will still be possible to enable it, if necessary, through the
* module API or by tweaking the system module list configuration by hand.
* Morever every D8 site where Content Translation is installed (not necessarily
* enabled) will still be able to see it as usual in the module page.
*/
function node_system_info_alter(&$info, $file, $type) {
if ($type == 'module' && $file->name == 'translation') {
$info['hidden'] = !module_exists('translation');
}
}
/**
* Marks a node to be re-indexed by the node_search plugin.
*
......
......@@ -26,10 +26,6 @@ function node_token_info() {
'name' => t("Revision ID"),
'description' => t("The unique ID of the node's latest revision."),
);
$node['tnid'] = array(
'name' => t("Translation set ID"),
'description' => t("The unique ID of the original-language version of this node, if one exists."),
);
$node['type'] = array(
'name' => t("Content type"),
'description' => t("The type of the node."),
......@@ -118,10 +114,6 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
$replacements[$original] = $node->getRevisionId();
break;
case 'tnid':
$replacements[$original] = $node->tnid->value;
break;
case 'type':
$replacements[$original] = $sanitize ? check_plain($node->getType()) : $node->getType();
break;
......
......@@ -17,7 +17,7 @@ class PathLanguageTest extends PathTestBase {
*
* @var array
*/
public static $modules = array('path', 'locale', 'translation');
public static $modules = array('path', 'locale', 'content_translation');
public static function getInfo() {
return array(
......@@ -30,8 +30,20 @@ public static function getInfo() {
function setUp() {
parent::setUp();
$permissions = array(
'access administration pages',
'administer content translation',
'administer content types',
'administer languages',
'administer url aliases',
'create content translations',
'create page content',
'create url aliases',
'edit any page content',
'translate any entity',
);
// 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 all content', 'access administration pages', 'administer content types'));
$this->web_user = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->web_user);
// Enable French language.
......@@ -43,6 +55,16 @@ function setUp() {
// Enable URL language detection and selection.
$edit = array('language_interface[enabled][language-url]' => 1);
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Enable translation for page node.
$edit = array(
'entity_types[node]' => 1,
'settings[node][page][translatable]' => 1,
'settings[node][page][fields][body]' => 1,
'settings[node][page][settings][language][language_show]' => 1,
);
$this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save'));
}
/**
......@@ -57,12 +79,11 @@ function testAliasTranslation() {
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), 'Basic page content type has been updated.');
variable_set('node_type_language_translation_enabled_page', TRUE);
$english_node = $this->drupalCreateNode(array('type' => 'page'));
$english_node = $this->drupalCreateNode(array('type' => 'page', 'langcode' => 'en'));
$english_alias = $this->randomName();
// Edit the node to set language and path.
$edit = array();
$edit['langcode'] = 'en';
$edit['path[alias]'] = $english_alias;
$this->drupalPostForm('node/' . $english_node->id() . '/edit', $edit, t('Save'));
......@@ -71,8 +92,9 @@ function testAliasTranslation() {
$this->assertText($english_node->label(), 'Alias works.');
// Translate the node into French.
$this->drupalGet('node/' . $english_node->id() . '/translate');
$this->clickLink(t('Add translation'));
$this->drupalGet('node/' . $english_node->id() . '/translations');
$this->clickLink(t('Add'));
$edit = array();
$edit['title'] = $this->randomName();
$edit['body[0][value]'] = $this->randomName();
......@@ -89,7 +111,7 @@ function testAliasTranslation() {
$languages = language_list();
// Ensure the node was created.
$french_node = $this->drupalGetNodeByTitle($edit["title"]);
$french_node = $english_node->getTranslation('fr');
$this->assertTrue(($french_node), 'Node found in database.');
// Confirm that the alias works.
......@@ -97,7 +119,7 @@ function testAliasTranslation() {
$this->assertText($french_node->label(), 'Alias for French translation works.');
// Confirm that the alias is returned by url().
$url = $this->container->get('url_generator')->generateFromPath('node/' . $french_node->id(), array('language' => $languages[$french_node->language()->id]));
$url = $this->container->get('url_generator')->generateFromPath('node/' . $french_node->id(), array('language' => $languages['fr']));
$this->assertTrue(strpos($url, $edit['path[alias]']), 'URL contains the path alias.');
......@@ -148,17 +170,17 @@ function testAliasTranslation() {
// The alias manager has an internal path lookup cache. Check to see that
// it has the appropriate contents at this point.
$this->container->get('path.alias_manager')->cacheClear();
$french_node_path = $this->container->get('path.alias_manager')->getSystemPath($french_alias, $french_node->language()->id);
$french_node_path = $this->container->get('path.alias_manager')->getSystemPath($french_alias, 'fr');
$this->assertEqual($french_node_path, 'node/' . $french_node->id(), 'Normal path works.');
// Second call should return the same path.
$french_node_path = $this->container->get('path.alias_manager')->getSystemPath($french_alias, $french_node->language()->id);
$french_node_path = $this->container->get('path.alias_manager')->getSystemPath($french_alias, 'fr');
$this->assertEqual($french_node_path, 'node/' . $french_node->id(), 'Normal path is the same.');
// Confirm that the alias works.
$french_node_alias = $this->container->get('path.alias_manager')->getPathAlias('node/' . $french_node->id(), $french_node->language()->id);
$french_node_alias = $this->container->get('path.alias_manager')->getPathAlias('node/' . $french_node->id(), 'fr');
$this->assertEqual($french_node_alias, $french_alias, 'Alias works.');
// Second call should return the same alias.
$french_node_alias = $this->container->get('path.alias_manager')->getPathAlias('node/' . $french_node->id(), $french_node->language()->id);
$french_node_alias = $this->container->get('path.alias_manager')->getPathAlias('node/' . $french_node->id(), 'fr');
$this->assertEqual($french_node_alias, $french_alias, 'Alias is the same.');
}
}
......@@ -82,18 +82,10 @@ public function testLanguageUpgrade() {
// Test that the 'language' property was properly renamed to 'langcode'.
$language_none_nid = 50;
$spanish_nid = 51;
$translation_source_nid = 52;
$translation_nid = 53;
// Check directly for the node langcode.
$this->assertEqual(node_load($language_none_nid)->language()->id, Language::LANGCODE_NOT_SPECIFIED, "'language' property was renamed to 'langcode' for Language::LANGCODE_NOT_SPECIFIED node.");
$this->assertEqual(node_load($spanish_nid)->language()->id, 'ca', "'language' property was renamed to 'langcode' for Catalan node.");
// Check that the translation table works correctly.
$this->drupalGet("node/$translation_source_nid/translate");
$this->assertResponse(200, 'The translated node has a proper translation table.');
$this->assertRaw('<td><strong>English</strong> (source)</td>', 'English is the source node of the translation.');
$this->assertRaw('<td>Chuvash</td>', 'There is a Chuvash translation of the node.');
$this->assertLinkByHref("node/$translation_nid", 0, 'The translation table links to the Chuvash translation.');
$this->assertRaw('<td>Catalan</td><td>n/a</td><td>Not translated</td>', 'There is no Catalan translation of this node.');
// Check for node content type settings upgrade.
$this->drupalGet('node/add/article');
$this->assertField('langcode', 'There is a language selector.');
......@@ -201,21 +193,4 @@ public function testLanguageNoPluralsUpgrade() {
$this->assertFalse(db_index_exists('locales_target', 'plural'), 'Translations without plurals upgraded.');
}
/**
* Tests upgrading translations permissions.
*/
public function testLanguagePermissionsUpgrade() {
// Insert a permission into the Drupal 7 database before running the
// upgrade.
db_insert('role_permission')->fields(array(
'rid' => 2,
'permission' => 'translate content',
'module' => 'translation',
))->execute();
$this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
$this->assertFalse(user_roles(FALSE, 'translate content'), 'No translate content role left in config.');
// Check that translate content has been renamed to translate all content.
$this->assertTrue(user_roles(FALSE, 'translate all content'), 'Rename role translate content to translate all content was completed successfully.');
}
}
# Schema for the configuration files of the translation module.
translation.settings:
type: mapping
label: 'Translation settings'
mapping:
language_type:
type: string
label: 'Language type'
<?php
/**
* @file
* Contains \Drupal\translation\Access\TranslationNodeOverviewAccessCheck.
*/
namespace Drupal\translation\Access;
use Drupal\Core\Access\StaticAccessCheckInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
* Provides an access checker for the node translation tab.
*/
class TranslationNodeOverviewAccessCheck implements StaticAccessCheckInterface {
/**
* {@inheritdoc}
*/
public function appliesTo() {
return array('_access_translation_tab');
}
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
$key = $route->getRequirement('_access_translation_tab');
if ($request->attributes->has($key)) {
// @todo Remove _translation_tab_access().
return _translation_tab_access($request->attributes->get($key)) ? static::ALLOW : static::DENY;
}
return static::DENY;
}
}
<?php
/**
* @file
* Contains \Drupal\translation\Controller\TranslationController.
*/
namespace Drupal\translation\Controller;
use Drupal\node\NodeInterface;
/**
* Controller routines for translation routes.
*/
class TranslationController {
/**
* @todo Remove translation_node_overview().
*/
public function nodeOverview(NodeInterface $node) {
module_load_include('pages.inc', 'translation');
return translation_node_overview($node);
}
}
name: 'Content Translation Test'
type: module
description: 'Support module for the content translation tests.'
core: 8.x
package: Testing
version: VERSION
hidden: true
<?php
/**
* @file
* Mock module for content translation tests.
*/
use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_node_insert().
*/
function translation_test_node_insert(EntityInterface $node) {
$node->save();
}
name: 'Content Translation (deprecated)'
type: module
description: 'Allows content to be translated into different languages.'
dependencies:
- node
- language
package: Multilingual
version: VERSION
core: 8.x
hidden: true
<?php
/**
* @file
* Update function for the translation module.
*/
/**
* Rename the translate content permission.
*/
function translation_update_8000() {
update_replace_permissions(array(
'translate content' => array('translate all content'),
));
}
/**
* Moves "translation_language_type" from variable to config.
*
* @ingroup config_upgrade
*/
function translation_update_8001() {
update_variables_to_config('translation.settings', array(
'translation_language_type' => 'language_type',
));
}
(function ($) {
"use strict";
Drupal.behaviors.TranslationEnable = {
attach: function (context) {
$('#edit-node-type-language-default, #edit-node-type-language-hidden', context).change(function(context) {
var default_language = $('#edit-node-type-language-default').val();
if ((default_language === 'und' || default_language === 'zxx' || default_language === 'mul') && $('#edit-node-type-language-hidden').prop('checked')) {
$('.form-item-node-type-language-translation-enabled').hide();
$('#edit-node-type-language-translation-enabled').prop('checked', false);
} else {
$('.form-item-node-type-language-translation-enabled').show();
}
});
$('#edit-node-type-language-default', context).trigger('change');
}
};
})(jQuery);
This diff is collapsed.
<?php
/**
* @file
* User page callbacks for the Translation module.
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface;
/**
* Page callback: Displays a list of a node's translations.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* A node entity.
*
* @return
* A render array for a page containing a list of content.
*
* @see translation_menu()
*
* @deprecated Use \Drupal\translation\Controller\TranslationController::nodeOverview()
*/
function translation_node_overview(EntityInterface $node) {
include_once DRUPAL_ROOT . '/core/includes/language.inc';
if ($node->tnid->value) {
// Already part of a set, grab that set.
$tnid = $node->tnid->value;
$translations = translation_node_get_translations($node->tnid->value);
}
else {
// We have no translation source nid, this could be a new set, emulate that.
$tnid = $node->id();
$translations = array($node->language()->id => $node);
}
$type = \Drupal::config('translation.settings')->get('language_type');
$header = array(t('Language'), t('Title'), t('Status'), t('Operations'));
foreach (language_list() as $langcode => $language) {
$options = array();
$language_name = $language->name;
if (isset($translations[$langcode])) {
// Existing translation in the translation set: display status.
// We load the full node to check whether the user can edit it.
$nid = $translations[$langcode] instanceof EntityInterface ? $translations[$langcode]->id() : $translations[$langcode]->nid;
$translation_node = node_load($nid);
$path = 'node/' . $translation_node->id();
$links = language_negotiation_get_switch_links($type, $path);
$title = empty($links->links[$langcode]['href']) ? l($translation_node->label(), $path) : l($translation_node->label(), $links->links[$langcode]['href'], $links->links[$langcode]);
if (node_access('update', $translation_node)) {
$path = 'node/' . $translation_node->id() . '/edit';
$links = language_negotiation_get_switch_links($type, $path);
if (!empty($links->links[$langcode]['href'])) {
$options['edit'] = array(
'title' => t('edit'),
) + $links->links[$langcode];
}
}
$status = $translation_node->isPublished() ? t('Published') : t('Not published');
$status .= $translation_node->translate->value ? ' - <span class="marker">' . t('outdated') . '</span>' : '';
if ($translation_node->id() == $tnid) {
$language_name = t('<strong>@language_name</strong> (source)', array('@language_name' => $language_name));
}
}
else {
// No such translation in the set yet: help user to create it.
$title = t('n/a');
if (node_access('create', $node)) {
$path = 'node/add/' . $node->getType();
$links = language_negotiation_get_switch_links($type, $path);
$query = array('query' => array('translation' => $node->id(), 'target' => $langcode));
if (!empty($links->links[$langcode]['href'])) {
$options['add'] = array(
'title' => t('Add translation'),
) + $links->links[$langcode];
$options['add'] = NestedArray::mergeDeep($options['add'], $query);
}
}
$status = t('Not translated');
}
$row = array();
$row[] = $language_name;
$row[] = $title;
$row[] = $status;
$row[] = array(
'data' => array(
'#type' => 'operations',
'#links' => $options,
),
);
$rows[] = $row;
}
$build['#title'] = t('Translations of %title', array('%title' => $node->label()));
$build['translation_node_overview'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
);
return $build;
}
translation.node_overview:
path: '/node/{node}/translate'
defaults:
_title: 'Translate'
_content: '\Drupal\translation\Controller\TranslationController::nodeOverview'
requirements:
_access_translation_tab: 'node'
services:
access_check.translation.node_overview:
class: Drupal\translation\Access\TranslationNodeOverviewAccessCheck
tags:
- { name: access_check }
......@@ -38,7 +38,6 @@ class HandlerAllTest extends HandlerTestBase {
'search',
'statistics',
'taxonomy',
'translation',
'user',
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment