123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- <?php
- /**
- * @file
- * Test cases for the file translator module.
- */
- /**
- * Basic tests for the file translator.
- */
- class TMGMTFileTestCase extends TMGMTBaseTestCase {
- static function getInfo() {
- return array(
- 'name' => 'File Translator tests',
- 'description' => 'Tests the file translator plugin integration.',
- 'group' => 'Translation Management',
- );
- }
- function setUp() {
- parent::setUp(array('tmgmt_file', 'tmgmt_ui'));
- $this->loginAsAdmin();
- $this->setEnvironment('de');
- }
- /**
- * Test the content processing for XLIFF export and import.
- */
- function testXLIFFTextProcessing() {
- $translator = $this->createTranslator();
- $translator->plugin = 'file';
- $translator->settings = array(
- 'export_format' => 'xlf',
- 'xliff_processing' => TRUE,
- );
- $translator->save();
- // Get the source text.
- $source_text = trim(file_get_contents(drupal_get_path('module', 'tmgmt') . '/tests/testing_html/sample.html'));
- // Create the reader instance, it will be used through the tests.
- $reader = new XMLReader();
- $xliff_elements = array('bpt', 'ept', 'ph', 'x', '#text', '#cdata-section', 'content');
- // ==== First test the whole cycle ==== //
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_html_source', 'test', '1');
- // Requesting translation will mask the html.
- $job->requestTranslation();
- $content = $this->getTransUnitsContent($job);
- // Test that the exported trans unit contains only xliff elements.
- $reader->XML('<content>' . $content[0]['source'] . '</content>');
- while ($reader->read()) {
- if (!in_array($reader->name, $xliff_elements)) {
- $this->fail(t('The source contains unexpected element %element', array('%element' => $reader->name)));
- }
- }
- $reader->XML('<content>' . $content[0]['target'] . '</content>');
- while ($reader->read()) {
- if (!in_array($reader->name, $xliff_elements)) {
- $this->fail(t('The target contains unexpected element %element', array('%element' => $reader->name)));
- }
- }
- // Import the file, make sure all the html has been revealed and no xliff
- // elements are present in the job translation.
- $messages = $job->getMessages();
- $message = reset($messages);
- $translated_file = 'public://tmgmt_file/translated.xlf';
- $this->createTranslationFile($message->variables['!link'], 'one paragraph', 'one translated paragraph', $translated_file);
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- // Reset caches and reload job.
- entity_get_controller('tmgmt_job')->resetCache();
- entity_get_controller('tmgmt_job_item')->resetCache();
- $job = tmgmt_job_load($job->tjid);
- // Do the comparison of the translation text and the source. It must be the
- // same as there was no change done to the translation.
- $item_data = $job->getData(array(1, 'dummy', 'deep_nesting'));
- $this->assertEqual(trim($item_data[1]['#translation']['#text']), str_replace('one paragraph', 'one translated paragraph', $source_text));
- $job_items = $job->getItems();
- /** @var TMGMTJobItem $job_item */
- $job_item = array_shift($job_items);
- // Job item must be in review.
- $this->assertTrue($job_item->isNeedsReview());
- $this->assertIntegrityCheck($job, FALSE);
- // ==== Test integrity check ==== //
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_html_source', 'test', '1');
- $job->requestTranslation();
- $messages = $job->getMessages();
- $message = reset($messages);
- // Get the xml content and remove the element representing <br />. This will
- // result in different element counts in the source and target and should
- // trigger an error and not import the translation.
- $translated_file = 'public://tmgmt_file/translated.xlf';
- $this->createTranslationFile($message->variables['!link'], '<x id="tjiid2-4" ctype="lb"/>', '', $translated_file);
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- entity_get_controller('tmgmt_job')->resetCache();
- entity_get_controller('tmgmt_job_item')->resetCache();
- $job = tmgmt_job_load($job->tjid);
- $this->assertIntegrityCheck($job);
- // Set the XLIFF processing to FALSE and test it results in the source
- // text not being XLIFF processed.
- $translator->settings['xliff_processing'] = FALSE;
- $translator->save();
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_html_source', 'test', '1');
- $job->requestTranslation();
- $targets = $this->getTransUnitsContent($job);
- $this->assertEqual(trim(html_entity_decode($targets['0']['source'])), $source_text);
- }
- /**
- * Test the CDATA option for XLIFF export and import.
- */
- function testXLIFFCDATA() {
- $translator = $this->createTranslator();
- $translator->plugin = 'file';
- $translator->settings = array(
- 'export_format' => 'xlf',
- 'xliff_cdata' => TRUE,
- );
- $translator->save();
- // Get the source text.
- $source_text = trim(file_get_contents(drupal_get_path('module', 'tmgmt') . '/tests/testing_html/sample.html'));
- // Create a new job.
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_html_source', 'test', '1');
- $job->requestTranslation();
- $messages = $job->getMessages();
- $message = reset($messages);
- $download_url = $message->variables['!link'];
- // Get XLIFF content.
- $xliff = file_get_contents($download_url);
- $dom = new \DOMDocument();
- $dom->loadXML($xliff);
- $this->assertTrue($dom->schemaValidate(drupal_get_path('module', 'tmgmt_file') . '/xliff-core-1.2-strict.xsd'));
- // "Translate" items.
- $xml = simplexml_import_dom($dom);
- $translated_text = array();
- foreach ($xml->file->body->children() as $group) {
- foreach ($group->children() as $transunit) {
- if ($transunit->getName() == 'trans-unit') {
- // The target should be empty.
- $this->assertEqual($transunit->target, '');
- // Update translations using CDATA.
- $node = dom_import_simplexml($transunit->target);
- $owner = $node->ownerDocument;
- $node->appendChild($owner->createCDATASection($xml->file['target-language'] . '_' . (string) $transunit->source));
- // Store the text to allow assertions later on.
- $translated_text[(string) $group['id']][(string) $transunit['id']] = (string) $transunit->target;
- }
- }
- }
- $translated_file = 'public://tmgmt_file/translated file.xlf';
- $xml->asXML($translated_file);
- // Import the file and check translation for the "dummy" item.
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- $this->clickLink(t('review'));
- foreach ($translated_text[1] as $key => $value) {
- $this->assertText(htmlspecialchars($value));
- }
- }
- /**
- * Gets trans-unit content from the XLIFF file that has been exported for the
- * given job as last.
- */
- protected function getTransUnitsContent(TMGMTJob $job) {
- $messages = $job->getMessages();
- $message = reset($messages);
- $download_url = $message->variables['!link'];
- $xml_string = file_get_contents($download_url);
- $xml = simplexml_load_string($xml_string);
- // Register the xliff namespace, required for xpath.
- $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2');
- $reader = new XMLReader();
- $data = array();
- $i = 0;
- foreach ($xml->xpath('//xliff:trans-unit') as $unit) {
- $reader->XML($unit->source->asXML());
- $reader->read();
- $data[$i]['source'] = $reader->readInnerXML();
- $reader->XML($unit->target->asXML());
- $reader->read();
- $data[$i]['target'] = $reader->readInnerXML();
- $i++;
- }
- return $data;
- }
- /**
- * Tests export and import for the HTML format.
- */
- function testHTML() {
- $translator = $this->createTranslator();
- $translator->plugin = 'file';
- $translator->settings = array(
- 'export_format' => 'html',
- );
- $translator->save();
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_source', 'test', '1');
- $job->addItem('test_source', 'test', '2');
- $job->requestTranslation();
- $messages = $job->getMessages();
- $message = reset($messages);
- $download_url = $message->variables['!link'];
- // "Translate" items.
- $xml = simplexml_load_file($download_url);
- $translated_text = array();
- foreach ($xml->body->children() as $group) {
- for ($i = 0; $i < $group->count(); $i++) {
- // This does not actually override the whole object, just the content.
- $group->div[$i] = (string) $xml->head->meta[3]['content'] . '_' . (string) $group->div[$i];
- // Store the text to allow assertions later on.
- $translated_text[(string) $group['id']][(string) $group->div[$i]['id']] = (string) $group->div[$i];
- }
- }
- $translated_file = 'public://tmgmt_file/translated.html';
- $xml->asXML($translated_file);
- $this->importFile($translated_file, $translated_text, $job);
- }
- /**
- * Tests import and export for the XLIFF format.
- */
- function testXLIFF() {
- $translator = $this->createTranslator();
- $translator->plugin = 'file';
- $translator->settings = array(
- 'export_format' => 'xlf',
- );
- $translator->save();
- // Set multiple data items for the source.
- variable_set('tmgmt_test_source_data', array(
- 'dummy' => array(
- 'deep_nesting' => array(
- '#text' => file_get_contents(drupal_get_path('module', 'tmgmt') . '/tests/testing_html/sample.html') . ' @id.',
- '#label' => 'Label of deep nested item @id',
- ),
- ),
- 'another_item' => array(
- '#text' => 'Text of another item @id.',
- '#label' => 'Label of another item @id.',
- ),
- ));
- $job = $this->createJob();
- $job->translator = $translator->name;
- $first_item = $job->addItem('test_source', 'test', '1');
- // Keep the first item data for later use.
- $first_item_data = tmgmt_flatten_data($first_item->getData());
- $job->addItem('test_source', 'test', '2');
- $job->requestTranslation();
- $messages = $job->getMessages();
- $message = reset($messages);
- $download_url = $message->variables['!link'];
- $xliff = file_get_contents($download_url);
- $dom = new DOMDocument();
- $dom->loadXML($xliff);
- $this->assertTrue($dom->schemaValidate(drupal_get_path('module', 'tmgmt_file') . '/xliff-core-1.2-strict.xsd'));
- // "Translate" items.
- $xml = simplexml_import_dom($dom);
- $translated_text = array();
- foreach ($xml->file->body->children() as $group) {
- foreach ($group->children() as $transunit) {
- if ($transunit->getName() == 'trans-unit') {
- // The target should be empty.
- $this->assertEqual($transunit->target, '');
- $transunit->target = $xml->file['target-language'] . '_' . (string) $transunit->source;
- // Store the text to allow assertions later on.
- $translated_text[(string) $group['id']][(string) $transunit['id']] = (string) $transunit->target;
- }
- }
- }
- // Change the job id to a non-existing one and try to import it.
- $wrong_xml = clone $xml;
- $wrong_xml->file->header->{'phase-group'}->phase['job-id'] = 500;
- $wrong_file = 'public://tmgmt_file/wrong_file.xlf';
- $wrong_xml->asXML($wrong_file);
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $wrong_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- $this->assertText(t('Failed to validate file, import aborted.'));
- // Change the job id to a wrong one and try to import it.
- $wrong_xml = clone $xml;
- $second_job = $this->createJob();
- $second_job->translator = $translator->name;
- // We need to add the elements count value into settings, otherwise the
- // validation will fail on integrity check.
- $second_job->settings['xliff_validation'][1] = 0;
- $second_job->settings['xliff_validation'][2] = 0;
- $second_job->save();
- $wrong_xml->file->header->{'phase-group'}->phase['job-id'] = $second_job->tjid;
- $wrong_file = 'public://tmgmt_file/wrong_file.xlf';
- $wrong_xml->asXML($wrong_file);
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $wrong_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- $this->assertRaw(t('The imported file job id @file_tjid does not match the job id @job_tjid.', array(
- '@file_tjid' => $second_job->tjid,
- '@job_tjid' => $job->tjid,
- )));
- $translated_file = 'public://tmgmt_file/translated file.xlf';
- $xml->asXML($translated_file);
- // Import the file and accept translation for the "dummy" item.
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- $this->clickLink(t('review'));
- $this->drupalPostAJAX(NULL, NULL, array('reviewed-dummy|deep_nesting' => '✓'));
- // Update the translation for "another" item and import.
- $xml->file->body->group[0]->{'trans-unit'}[1]->target = $xml->file->body->group[0]->{'trans-unit'}[1]->target . ' updated';
- $xml->asXML($translated_file);
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- // At this point we must have the "dummy" item accepted and intact. The
- // "another" item must have updated translation.
- $this->clickLink(t('review'));
- $this->assertFieldByName('dummy|deep_nesting[translation]', 'de_' . $first_item_data['dummy][deep_nesting']['#text']);
- $this->assertFieldByName('another_item[translation]', 'de_' . $first_item_data['another_item']['#text'] . ' updated');
- // Now finish the import/save as completed process doing another extra
- // import. The extra import will test that a duplicate import of the same
- // file does not break the process.
- $this->importFile($translated_file, $translated_text, $job);
- $this->assertNoText(t('Import translated file'));
- // Create a job, assign to the file translator and delete before attaching
- // a file.
- $other_job = $this->createJob();
- $other_job->translator = $translator->name;
- $other_job->save();
- $other_job->delete();
- // Make sure the file of the other job still exists.
- $response = drupal_http_request($download_url);
- $this->assertEqual(200, $response->code);
- // Delete the job and then make sure that the file has been deleted.
- $job->delete();
- $response = drupal_http_request($download_url);
- $this->assertEqual(404, $response->code);
- }
- /**
- * Tests storing files in the private file system.
- */
- function testPrivate() {
- // Enable the private file system.
- variable_set('file_private_path', variable_get('file_public_path') . '/private');
- // Create a translator using the private file system.
- // @todo: Test the configuration UI.
- $translator = $this->createTranslator();
- $translator->plugin = 'file';
- $translator->settings = array(
- 'export_format' => 'xlf',
- 'scheme' => 'private',
- );
- $translator->save();
- $job = $this->createJob();
- $job->translator = $translator->name;
- $job->addItem('test_source', 'test', '1');
- $job->addItem('test_source', 'test', '2');
- $job->requestTranslation();
- $messages = $job->getMessages();
- $message = reset($messages);
- $download_url = $message->variables['!link'];
- $this->drupalGet($download_url);
- // Verify that the URL is served using the private file system and the
- // access checks work.
- $this->assertTrue(preg_match('|system/files|', $download_url));
- $this->assertResponse(200);
- $this->drupalLogout();
- // Verify that access is now protected.
- $this->drupalGet($download_url);
- $this->assertResponse(403);
- }
- protected function importFile($translated_file, $translated_text, TMGMTJob $job) {
- // To test the upload form functionality, navigate to the edit form.
- $uri = $job->uri();
- $edit = array(
- 'files[file]' => $translated_file,
- );
- $this->drupalPost($uri['path'] . '/manage', $edit, t('Import'));
- // Make sure the translations have been imported correctly.
- $this->assertNoText(t('In progress'));
- // @todo: Enable this assertion once new releases for views and entity
- // module are out.
- //$this->assertText(t('Needs review'));
- // Review both items.
- $this->clickLink(t('review'));
- foreach ($translated_text[1] as $key => $value) {
- $this->assertText(check_plain($value));
- }
- foreach ($translated_text[2] as $key => $value) {
- $this->assertNoText(check_plain($value));
- }
- $this->drupalPost(NULL, array(), t('Save as completed'));
- // Review both items.
- $this->clickLink(t('review'));
- foreach ($translated_text[1] as $key => $value) {
- $this->assertNoText(check_plain($value));
- }
- foreach ($translated_text[2] as $key => $value) {
- $this->assertText(check_plain($value));
- }
- $this->drupalPost(NULL, array(), t('Save as completed'));
- // @todo: Enable this assertion once new releases for views and entity
- // module are out.
- //$this->assertText(t('Accepted'));
- $this->assertText(t('Finished'));
- $this->assertNoText(t('Needs review'));
- }
- /**
- * Creates a translated XLIFF file based on the replacement definition.
- *
- * @param string $source_file
- * Source file name.
- * @param $search
- * String to search in the source.
- * @param $replace
- * String to replace it with in the target.
- * @param $translated_file
- * Name of the file to write.
- */
- protected function createTranslationFile($source_file, $search, $replace, $translated_file) {
- $xml_string = file_get_contents($source_file);
- preg_match('/<source xml:lang="en">(.+)<\/source>/s', $xml_string, $matches);
- $target = str_replace($search, $replace, $matches[1]);
- if ($replace) {
- $this->assertTrue(strpos($target, $replace) !== FALSE, 'String replaced in translation');
- }
- $translated_xml_string = str_replace('<target xml:lang="de"/>', '<target xml:lang="de">' . $target . '</target>', $xml_string);
- file_put_contents($translated_file, $translated_xml_string);
- }
- /**
- * Asserts import integrity for a job.
- *
- * @param TMGMTJob $job
- * The job to check.
- * @param bool $expected
- * (optional) If an integrity failed message is expected or not, defaults
- * to FALSE.
- */
- protected function assertIntegrityCheck(TMGMTJob $job, $expected = TRUE) {
- $integrity_check_failed = FALSE;
- /** @var TMGMTMessage $message */
- foreach ($job->getMessages() as $message) {
- if ($message->getMessage() == t('Failed to validate semantic integrity of %key element. Please check also the HTML code of the element in the review process.', array('%key' => 'dummy][deep_nesting'))) {
- $integrity_check_failed = TRUE;
- break;
- }
- }
- // Check if the message was found or not, based on the expected argument.
- if ($expected) {
- $this->assertTrue($integrity_check_failed, 'The validation of semantic integrity must fail.');
- }
- else {
- $this->assertFalse($integrity_check_failed, 'The validation of semantic integrity must not fail.');
- }
- }
- }
|