Issue #1591950 by aspilicious: Convert locale tests to PSR-0.
parent
1f4736c156
commit
2f35944ad3
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleCommentLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for comment language.
|
||||
*/
|
||||
class LocaleCommentLanguageTest extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment language',
|
||||
'description' => 'Tests for comment language.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
// We also use language_test module here to be able to turn on content
|
||||
// language negotiation. Drupal core does not provide a way in itself
|
||||
// to do that.
|
||||
parent::setUp('locale', 'language_test');
|
||||
|
||||
// Create and login user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages', 'administer content types', 'create article content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add language.
|
||||
$edit = array('predefined_langcode' => 'fr');
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Set "Article" content type to use multilingual support.
|
||||
$edit = array('node_type_language' => 1);
|
||||
$this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
|
||||
// Enable content language negotiation UI.
|
||||
variable_set('language_test_content_language_type', TRUE);
|
||||
|
||||
// Set interface language detection to user and content language detection
|
||||
// to URL. Disable inheritance from interface language to ensure content
|
||||
// language will fall back to the default language if no URL language can be
|
||||
// detected.
|
||||
$edit = array(
|
||||
'language_interface[enabled][language-user]' => TRUE,
|
||||
'language_content[enabled][language-url]' => TRUE,
|
||||
'language_content[enabled][language-interface]' => FALSE,
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
|
||||
// Change user language preference, this way interface language is always
|
||||
// French no matter what path prefix the URLs have.
|
||||
$edit = array('preferred_langcode' => 'fr');
|
||||
$this->drupalPost("user/{$admin_user->uid}/edit", $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that comment language is properly set.
|
||||
*/
|
||||
function testCommentLanguage() {
|
||||
drupal_static_reset('language_list');
|
||||
|
||||
// Create two nodes, one for english and one for french, and comment each
|
||||
// node using both english and french as content language by changing URL
|
||||
// language prefixes. Meanwhile interface language is always French, which
|
||||
// is the user language preference. This way we can ensure that node
|
||||
// language and interface language do not influence comment language, as
|
||||
// only content language has to.
|
||||
foreach (language_list() as $node_langcode => $node_language) {
|
||||
$langcode_not_specified = LANGUAGE_NOT_SPECIFIED;
|
||||
|
||||
// Create "Article" content.
|
||||
$title = $this->randomName();
|
||||
$edit = array(
|
||||
"title" => $title,
|
||||
"body[$langcode_not_specified][0][value]" => $this->randomName(),
|
||||
"langcode" => $node_langcode,
|
||||
);
|
||||
$this->drupalPost("node/add/article", $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
|
||||
$prefixes = language_negotiation_url_prefixes();
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
// Post a comment with content language $langcode.
|
||||
$prefix = empty($prefixes[$langcode]) ? '' : $prefixes[$langcode] . '/';
|
||||
$edit = array("comment_body[$langcode_not_specified][0][value]" => $this->randomName());
|
||||
$this->drupalPost("{$prefix}node/{$node->nid}", $edit, t('Save'));
|
||||
|
||||
// Check that comment language matches the current content language.
|
||||
$comment = db_select('comment', 'c')
|
||||
->fields('c')
|
||||
->condition('nid', $node->nid)
|
||||
->orderBy('cid', 'DESC')
|
||||
->execute()
|
||||
->fetchObject();
|
||||
$args = array('%node_language' => $node_langcode, '%comment_language' => $comment->langcode, '%langcode' => $langcode);
|
||||
$this->assertEqual($comment->langcode, $langcode, t('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleContentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for multilingual support on nodes.
|
||||
*/
|
||||
class LocaleContentTest extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Content language settings',
|
||||
'description' => 'Checks you can enable multilingual support on content types and configure a language for a node.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that machine name fields are always LTR.
|
||||
*/
|
||||
function testMachineNameLTR() {
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages'));
|
||||
|
||||
// Log in as admin.
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Verify that the machine name field is LTR for a new content type.
|
||||
$this->drupalGet('admin/structure/types/add');
|
||||
$this->assertFieldByXpath('//input[@name="type" and @dir="ltr"]', NULL, 'The machine name field is LTR when no additional language is configured.');
|
||||
|
||||
// Install the Arabic language (which is RTL) and configure as the default.
|
||||
$edit = array();
|
||||
$edit['predefined_langcode'] = 'ar';
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
$edit = array();
|
||||
$edit['site_default'] = 'ar';
|
||||
$this->drupalPost(NULL, $edit, t('Save configuration'));
|
||||
|
||||
// Verify that the machine name field is still LTR for a new content type.
|
||||
$this->drupalGet('admin/structure/types/add');
|
||||
$this->assertFieldByXpath('//input[@name="type" and @dir="ltr"]', NULL, 'The machine name field is LTR when the default language is RTL.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a content type can be set to multilingual and language is present.
|
||||
*/
|
||||
function testContentTypeLanguageConfiguration() {
|
||||
global $base_url;
|
||||
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages'));
|
||||
// User to create a node.
|
||||
$web_user = $this->drupalCreateUser(array('create article content', 'create page content', 'edit any page content'));
|
||||
|
||||
// Add custom language.
|
||||
$this->drupalLogin($admin_user);
|
||||
// Code for the language.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language.
|
||||
$name = $this->randomName(16);
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
|
||||
// Set "Basic page" content type to use multilingual support.
|
||||
$this->drupalGet('admin/structure/types/manage/page');
|
||||
$this->assertText(t('Multilingual support'), t('Multilingual support fieldset present on content type configuration form.'));
|
||||
$edit = array(
|
||||
'node_type_language' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Verify language selection is not present on add article form.
|
||||
$this->drupalLogin($web_user);
|
||||
$this->drupalGet('node/add/article');
|
||||
// Verify language select list is not present.
|
||||
$this->assertNoFieldByName('language', NULL, t('Language select not present on add article form.'));
|
||||
|
||||
// Verify language selection appears on add "Basic page" form.
|
||||
$this->drupalGet('node/add/page');
|
||||
// Verify language select list is present.
|
||||
$this->assertFieldByName('langcode', NULL, t('Language select present on add Basic page form.'));
|
||||
// Ensure language appears.
|
||||
$this->assertText($name, t('Language present.'));
|
||||
|
||||
// Create "Basic page" content.
|
||||
$node_title = $this->randomName();
|
||||
$node_body = $this->randomName();
|
||||
$edit = array(
|
||||
'type' => 'page',
|
||||
'title' => $node_title,
|
||||
'body' => array($langcode => array(array('value' => $node_body))),
|
||||
'langcode' => $langcode,
|
||||
);
|
||||
$node = $this->drupalCreateNode($edit);
|
||||
// Edit the content and ensure correct language is selected.
|
||||
$path = 'node/' . $node->nid . '/edit';
|
||||
$this->drupalGet($path);
|
||||
$this->assertRaw('<option value="' . $langcode . '" selected="selected">' . $name . '</option>', t('Correct language selected.'));
|
||||
// Ensure we can change the node language.
|
||||
$edit = array(
|
||||
'langcode' => 'en',
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save'));
|
||||
$this->assertRaw(t('%title has been updated.', array('%title' => $node_title)), t('Basic page content updated.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a dir and lang tags exist in node's attributes.
|
||||
*/
|
||||
function testContentTypeDirLang() {
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages'));
|
||||
// User to create a node.
|
||||
$web_user = $this->drupalCreateUser(array('create article content', 'edit own article content'));
|
||||
|
||||
// Login as admin.
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Install Arabic language.
|
||||
$edit = array();
|
||||
$edit['predefined_langcode'] = 'ar';
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Install Spanish language.
|
||||
$edit = array();
|
||||
$edit['predefined_langcode'] = 'es';
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Set "Article" content type to use multilingual support.
|
||||
$this->drupalGet('admin/structure/types/manage/article');
|
||||
$edit = array(
|
||||
'node_type_language' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Article')), t('Article content type has been updated.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Login as web user to add new article.
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create three nodes: English, Arabic and Spanish.
|
||||
$node_en = $this->createNodeArticle('en');
|
||||
$node_ar = $this->createNodeArticle('ar');
|
||||
$node_es = $this->createNodeArticle('es');
|
||||
|
||||
$this->drupalGet('node');
|
||||
|
||||
// Check if English node does not have lang tag.
|
||||
$pattern = '|id="node-' . $node_en->nid . '"[^<>]*lang="en"|';
|
||||
$this->assertNoPattern($pattern, t('The lang tag has not been assigned to the English node.'));
|
||||
|
||||
// Check if English node does not have dir tag.
|
||||
$pattern = '|id="node-' . $node_en->nid . '"[^<>]*dir="ltr"|';
|
||||
$this->assertNoPattern($pattern, t('The dir tag has not been assigned to the English node.'));
|
||||
|
||||
// Check if Arabic node has lang="ar" & dir="rtl" tags.
|
||||
$pattern = '|id="node-' . $node_ar->nid . '"[^<>]*lang="ar" dir="rtl"|';
|
||||
$this->assertPattern($pattern, t('The lang and dir tags have been assigned correctly to the Arabic node.'));
|
||||
|
||||
// Check if Spanish node has lang="es" tag.
|
||||
$pattern = '|id="node-' . $node_es->nid . '"[^<>]*lang="es"|';
|
||||
$this->assertPattern($pattern, t('The lang tag has been assigned correctly to the Spanish node.'));
|
||||
|
||||
// Check if Spanish node does not have dir="ltr" tag.
|
||||
$pattern = '|id="node-' . $node_es->nid . '"[^<>]*lang="es" dir="ltr"|';
|
||||
$this->assertNoPattern($pattern, t('The dir tag has not been assigned to the Spanish node.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create node in a specific language.
|
||||
*/
|
||||
protected function createNodeArticle($langcode) {
|
||||
$this->drupalGet('node/add/article');
|
||||
$node_title = $this->randomName();
|
||||
$node_body = $this->randomName();
|
||||
$edit = array(
|
||||
'type' => 'article',
|
||||
'title' => $node_title,
|
||||
'body' => array($langcode => array(array('value' => $node_body))),
|
||||
'langcode' => $langcode,
|
||||
'promote' => 1,
|
||||
);
|
||||
return $this->drupalCreateNode($edit);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleDateFormatsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for localizing date formats.
|
||||
*/
|
||||
class LocaleDateFormatsTest extends WebTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Localize date formats',
|
||||
'description' => 'Tests for the localization of date formats.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'locale'));
|
||||
|
||||
// Create Article node type.
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
|
||||
// Create and login user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages', 'create article content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional tests for localizing date formats.
|
||||
*/
|
||||
function testLocalizeDateFormats() {
|
||||
// Add language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Set language negotiation.
|
||||
$language_type = LANGUAGE_TYPE_INTERFACE;
|
||||
$edit = array(
|
||||
"{$language_type}[enabled][language-url]" => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
|
||||
// Configure date formats.
|
||||
$this->drupalGet('admin/config/regional/date-time/locale');
|
||||
$this->assertText('French', 'Configured languages appear.');
|
||||
$edit = array(
|
||||
'date_format_long' => 'd.m.Y - H:i',
|
||||
'date_format_medium' => 'd.m.Y - H:i',
|
||||
'date_format_short' => 'd.m.Y - H:i',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/date-time/locale/fr/edit', $edit, t('Save configuration'));
|
||||
$this->assertText(t('Configuration saved.'), 'French date formats updated.');
|
||||
$edit = array(
|
||||
'date_format_long' => 'j M Y - g:ia',
|
||||
'date_format_medium' => 'j M Y - g:ia',
|
||||
'date_format_short' => 'j M Y - g:ia',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/date-time/locale/en/edit', $edit, t('Save configuration'));
|
||||
$this->assertText(t('Configuration saved.'), 'English date formats updated.');
|
||||
|
||||
// Create node content.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article'));
|
||||
|
||||
// Configure format for the node posted date changes with the language.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$english_date = format_date($node->created, 'custom', 'j M Y');
|
||||
$this->assertText($english_date, t('English date format appears'));
|
||||
$this->drupalGet('fr/node/' . $node->nid);
|
||||
$french_date = format_date($node->created, 'custom', 'd.m.Y');
|
||||
$this->assertText($french_date, t('French date format appears'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleExportTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests for the export of translation files.
|
||||
*/
|
||||
class LocaleExportTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Translation export',
|
||||
'description' => 'Tests the exportation of locale files.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A user able to create languages and export translations.
|
||||
*/
|
||||
protected $admin_user = NULL;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exportation of translations.
|
||||
*/
|
||||
function testExportTranslation() {
|
||||
// First import some known translations.
|
||||
// This will also automatically enable the 'fr' language.
|
||||
$name = tempnam('temporary://', "po_") . '.po';
|
||||
file_put_contents($name, $this->getPoFile());
|
||||
$this->drupalPost('admin/config/regional/translate/import', array(
|
||||
'langcode' => 'fr',
|
||||
'files[file]' => $name,
|
||||
), t('Import'));
|
||||
drupal_unlink($name);
|
||||
|
||||
// Get the French translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'fr',
|
||||
), t('Export'));
|
||||
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# French translation of Drupal', t('Exported French translation file.'));
|
||||
// Ensure our imported translations exist in the file.
|
||||
$this->assertRaw('msgstr "lundi"', t('French translations present in exported file.'));
|
||||
|
||||
// Import some more French translations which will be marked as customized.
|
||||
$name = tempnam('temporary://', "po2_") . '.po';
|
||||
file_put_contents($name, $this->getCustomPoFile());
|
||||
$this->drupalPost('admin/config/regional/translate/import', array(
|
||||
'langcode' => 'fr',
|
||||
'files[file]' => $name,
|
||||
'customized' => 1,
|
||||
), t('Import'));
|
||||
drupal_unlink($name);
|
||||
|
||||
// We can't import a string with an empty translation, but calling
|
||||
// locale() for an new string creates an entry in the locales_source table.
|
||||
locale('February', NULL, 'fr');
|
||||
|
||||
// Export only customized French translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'fr',
|
||||
'content_options[not_customized]' => FALSE,
|
||||
'content_options[customized]' => TRUE,
|
||||
'content_options[not_translated]' => FALSE,
|
||||
), t('Export'));
|
||||
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# French translation of Drupal', t('Exported French translation file with only customized strings.'));
|
||||
// Ensure the customized translations exist in the file.
|
||||
$this->assertRaw('msgstr "janvier"', t('French custom translation present in exported file.'));
|
||||
// Ensure no untranslated strings exist in the file.
|
||||
$this->assertNoRaw('msgid "February"', t('Untranslated string not present in exported file.'));
|
||||
|
||||
// Export only untranslated French translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'fr',
|
||||
'content_options[not_customized]' => FALSE,
|
||||
'content_options[customized]' => FALSE,
|
||||
'content_options[not_translated]' => TRUE,
|
||||
), t('Export'));
|
||||
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# French translation of Drupal', t('Exported French translation file with only untranslated strings.'));
|
||||
// Ensure no customized translations exist in the file.
|
||||
$this->assertNoRaw('msgstr "janvier"', t('French custom translation not present in exported file.'));
|
||||
// Ensure the untranslated strings exist in the file.
|
||||
$this->assertRaw('msgid "February"', t('Untranslated string present in exported file.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exportation of translation template file.
|
||||
*/
|
||||
function testExportTranslationTemplateFile() {
|
||||
// Get the translation template file.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(), t('Export'));
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# LANGUAGE translation of PROJECT', t('Exported translation template file.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a proper .po file.
|
||||
*/
|
||||
function getPoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "lundi"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a .po file which strings will be marked
|
||||
* as customized.
|
||||
*/
|
||||
function getCustomPoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "January"
|
||||
msgstr "janvier"
|
||||
EOF;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,487 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleImportFunctionalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for the import of translation files.
|
||||
*/
|
||||
class LocaleImportFunctionalTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Translation import',
|
||||
'description' => 'Tests the import of locale files.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A user able to create languages and import translations.
|
||||
*/
|
||||
protected $admin_user = NULL;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('locale', 'dblog'));
|
||||
|
||||
// Set the translation file directory.
|
||||
variable_set('locale_translate_file_directory', drupal_get_path('module', 'locale') . '/tests');
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test import of standalone .po files.
|
||||
*/
|
||||
function testStandalonePoFile() {
|
||||
// Try importing a .po file.
|
||||
$this->importPoFile($this->getPoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
));
|
||||
|
||||
// The import should automatically create the corresponding language.
|
||||
$this->assertRaw(t('The language %language has been created.', array('%language' => 'French')), t('The language has been automatically created.'));
|
||||
|
||||
// The import should have created 8 strings.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 8, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
|
||||
|
||||
// This import should have saved plural forms to have 2 variants.
|
||||
$locale_plurals = variable_get('locale_translation_plurals', array());
|
||||
$this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural number initialized.'));
|
||||
|
||||
// Ensure we were redirected correctly.
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
|
||||
|
||||
// Try importing a .po file with invalid tags.
|
||||
$this->importPoFile($this->getBadPoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
));
|
||||
|
||||
// The import should have created 1 string and rejected 2.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 1, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
|
||||
$skip_message = format_plural(2, 'A translation string was skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', '@count translation strings were skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', array('@url' => url('admin/reports/dblog')));
|
||||
$this->assertRaw($skip_message, t('Unsafe strings were skipped.'));
|
||||
|
||||
|
||||
// Try importing a .po file which doesn't exist.
|
||||
$name = $this->randomName(16);
|
||||
$this->drupalPost('admin/config/regional/translate/import', array(
|
||||
'langcode' => 'fr',
|
||||
'files[file]' => $name,
|
||||
), t('Import'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/import', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
$this->assertText(t('File to import not found.'), t('File to import not found message.'));
|
||||
|
||||
|
||||
// Try importing a .po file with overriding strings, and ensure existing
|
||||
// strings are kept.
|
||||
$this->importPoFile($this->getOverwritePoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
));
|
||||
|
||||
// The import should have created 1 string.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 1, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
|
||||
// Ensure string wasn't overwritten.
|
||||
$search = array(
|
||||
'string' => 'Montag',
|
||||
'language' => 'fr',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
|
||||
|
||||
// This import should not have changed number of plural forms.
|
||||
$locale_plurals = variable_get('locale_translation_plurals', array());
|
||||
$this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural numbers untouched.'));
|
||||
|
||||
// Try importing a .po file with overriding strings, and ensure existing
|
||||
// strings are overwritten.
|
||||
$this->importPoFile($this->getOverwritePoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
'overwrite_options[not_customized]' => TRUE,
|
||||
));
|
||||
|
||||
// The import should have updated 2 strings.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 0, '%update' => 2, '%delete' => 0)), t('The translation file was successfully imported.'));
|
||||
// Ensure string was overwritten.
|
||||
$search = array(
|
||||
'string' => 'Montag',
|
||||
'language' => 'fr',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
|
||||
// This import should have changed number of plural forms.
|
||||
$locale_plurals = variable_get('locale_translation_plurals', array());
|
||||
$this->assert($locale_plurals['fr']['plurals'] == 3, t('Plural numbers changed.'));
|
||||
|
||||
// Importing a .po file and mark its strings as customized strings.
|
||||
$this->importPoFile($this->getCustomPoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
'customized' => TRUE,
|
||||
));
|
||||
|
||||
// The import should have created 6 strings.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 6, '%update' => 0, '%delete' => 0)), t('The customized translation file was successfully imported.'));
|
||||
|
||||
// The database should now contain 6 customized strings (two imported
|
||||
// strings are not translated).
|
||||
$count = db_query('SELECT lid FROM {locales_target} WHERE customized = :custom', array(':custom' => 1))->rowCount();
|
||||
$this->assertEqual($count, 6, t('Customized translations succesfully imported.'));
|
||||
|
||||
// Try importing a .po file with overriding strings, and ensure existing
|
||||
// customized strings are kept.
|
||||
$this->importPoFile($this->getCustomOverwritePoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
'overwrite_options[not_customized]' => TRUE,
|
||||
'overwrite_options[customized]' => FALSE,
|
||||
));
|
||||
|
||||
// The import should have created 1 string.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 1, '%update' => 0, '%delete' => 0)), t('The customized translation file was successfully imported.'));
|
||||
// Ensure string wasn't overwritten.
|
||||
$search = array(
|
||||
'string' => 'januari',
|
||||
'language' => 'fr',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t('Customized string not overwritten by imported string.'));
|
||||
|
||||
// Try importing a .po file with overriding strings, and ensure existing
|
||||
// customized strings are overwritten.
|
||||
$this->importPoFile($this->getCustomOverwritePoFile(), array(
|
||||
'langcode' => 'fr',
|
||||
'overwrite_options[not_customized]' => FALSE,
|
||||
'overwrite_options[customized]' => TRUE,
|
||||
));
|
||||
|
||||
// The import should have updated 2 strings.
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 0, '%update' => 2, '%delete' => 0)), t('The customized translation file was successfully imported.'));
|
||||
// Ensure string was overwritten.
|
||||
$search = array(
|
||||
'string' => 'januari',
|
||||
'language' => 'fr',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('Customized string overwritten by imported string.'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test automatic import of a module's translation files.
|
||||
*/
|
||||
function testAutomaticModuleTranslationImportLanguageEnable() {
|
||||
// Code for the language - manually set to match the test translation file.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language.
|
||||
$name = $this->randomName(16);
|
||||
|
||||
// Create a custom language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
|
||||
// Ensure the translation file was automatically imported when language was
|
||||
// added.
|
||||
$this->assertText(t('One translation file imported.'), t('Language file automatically imported.'));
|
||||
|
||||
// Ensure strings were successfully imported.
|
||||
$search = array(
|
||||
'string' => 'lundi',
|
||||
'language' => $langcode,
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('String successfully imported.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test msgctxt context support.
|
||||
*/
|
||||
function testLanguageContext() {
|
||||
// Try importing a .po file.
|
||||
$this->importPoFile($this->getPoFileWithContext(), array(
|
||||
'langcode' => 'hr',
|
||||
));
|
||||
|
||||
$this->assertIdentical(t('May', array(), array('langcode' => 'hr', 'context' => 'Long month name')), 'Svibanj', t('Long month name context is working.'));
|
||||
$this->assertIdentical(t('May', array(), array('langcode' => 'hr')), 'Svi.', t('Default context is working.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test empty msgstr at end of .po file see #611786.
|
||||
*/
|
||||
function testEmptyMsgstr() {
|
||||
$langcode = 'hu';
|
||||
|
||||
// Try importing a .po file.
|
||||
$this->importPoFile($this->getPoFileWithMsgstr(), array(
|
||||
'langcode' => $langcode,
|
||||
));
|
||||
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 1, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
|
||||
$this->assertIdentical(t('Operations', array(), array('langcode' => $langcode)), 'Műveletek', t('String imported and translated.'));
|
||||
|
||||
// Try importing a .po file.
|
||||
$this->importPoFile($this->getPoFileWithEmptyMsgstr(), array(
|
||||
'langcode' => $langcode,
|
||||
'overwrite_options[not_customized]' => TRUE,
|
||||
));
|
||||
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 0, '%update' => 0, '%delete' => 1)), t('The translation file was successfully imported.'));
|
||||
// This is the language indicator on the translation search screen for
|
||||
// untranslated strings.
|
||||
$language_indicator = "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
$str = "Operations";
|
||||
$search = array(
|
||||
'string' => $str,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// assertText() seems to remove the input field where $str always could be
|
||||
// found, so this is not a false assert.
|
||||
$this->assertText($str, t('Search found the string.'));
|
||||
$this->assertRaw($language_indicator, t('String is untranslated again.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function: import a standalone .po file in a given language.
|
||||
*
|
||||
* @param $contents
|
||||
* Contents of the .po file to import.
|
||||
* @param $options
|
||||
* Additional options to pass to the translation import form.
|
||||
*/
|
||||
function importPoFile($contents, array $options = array()) {
|
||||
$name = tempnam('temporary://', "po_") . '.po';
|
||||
file_put_contents($name, $contents);
|
||||
$options['files[file]'] = $name;
|
||||
$this->drupalPost('admin/config/regional/translate/import', $options, t('Import'));
|
||||
drupal_unlink($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a proper .po file.
|
||||
*/
|
||||
function getPoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "One sheep"
|
||||
msgid_plural "@count sheep"
|
||||
msgstr[0] "un mouton"
|
||||
msgstr[1] "@count moutons"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "lundi"
|
||||
|
||||
msgid "Tuesday"
|
||||
msgstr "mardi"
|
||||
|
||||
msgid "Wednesday"
|
||||
msgstr "mercredi"
|
||||
|
||||
msgid "Thursday"
|
||||
msgstr "jeudi"
|
||||
|
||||
msgid "Friday"
|
||||
msgstr "vendredi"
|
||||
|
||||
msgid "Saturday"
|
||||
msgstr "samedi"
|
||||
|
||||
msgid "Sunday"
|
||||
msgstr "dimanche"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a bad .po file.
|
||||
*/
|
||||
function getBadPoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "Save configuration"
|
||||
msgstr "Enregistrer la configuration"
|
||||
|
||||
msgid "edit"
|
||||
msgstr "modifier<img SRC="javascript:alert(\'xss\');">"
|
||||
|
||||
msgid "delete"
|
||||
msgstr "supprimer<script>alert('xss');</script>"
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a proper .po file for testing.
|
||||
*/
|
||||
function getOverwritePoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\\n"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "Montag"
|
||||
|
||||
msgid "Day"
|
||||
msgstr "Jour"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a .po file which strings will be marked
|
||||
* as customized.
|
||||
*/
|
||||
function getCustomPoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "One dog"
|
||||
msgid_plural "@count dogs"
|
||||
msgstr[0] "un chien"
|
||||
msgstr[1] "@count chiens"
|
||||
|
||||
msgid "January"
|
||||
msgstr "janvier"
|
||||
|
||||
msgid "February"
|
||||
msgstr "février"
|
||||
|
||||
msgid "March"
|
||||
msgstr "mars"
|
||||
|
||||
msgid "April"
|
||||
msgstr "avril"
|
||||
|
||||
msgid "June"
|
||||
msgstr "juin"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a .po file for testing customized strings.
|
||||
*/
|
||||
function getCustomOverwritePoFile() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "January"
|
||||
msgstr "januari"
|
||||
|
||||
msgid "February"
|
||||
msgstr "februari"
|
||||
|
||||
msgid "July"
|
||||
msgstr "juillet"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a .po file with context.
|
||||
*/
|
||||
function getPoFileWithContext() {
|
||||
// Croatian (code hr) is one the the languages that have a different
|
||||
// form for the full name and the abbreviated name for the month May.
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\\n"
|
||||
|
||||
msgctxt "Long month name"
|
||||
msgid "May"
|
||||
msgstr "Svibanj"
|
||||
|
||||
msgid "May"
|
||||
msgstr "Svi."
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns a .po file with an empty last item.
|
||||
*/
|
||||
function getPoFileWithEmptyMsgstr() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "Operations"
|
||||
msgstr ""
|
||||
|
||||
EOF;
|
||||
}
|
||||
/**
|
||||
* Helper function that returns a .po file with an empty last item.
|
||||
*/
|
||||
function getPoFileWithMsgstr() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "Operations"
|
||||
msgstr "Műveletek"
|
||||
|
||||
msgid "Will not appear in Drupal core, so we can ensure the test passes"
|
||||
msgstr ""
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleInstallTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use ReflectionFunction;
|
||||
|
||||
/**
|
||||
* Tests for the st() function.
|
||||
*/
|
||||
class LocaleInstallTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'String translation using st()',
|
||||
'description' => 'Tests that st() works like t().',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
|
||||
// st() lives in install.inc, so ensure that it is loaded for all tests.
|
||||
require_once DRUPAL_ROOT . '/core/includes/install.inc';
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that function signatures of t() and st() are equal.
|
||||
*/
|
||||
function testFunctionSignatures() {
|
||||
$reflector_t = new ReflectionFunction('t');
|
||||
$reflector_st = new ReflectionFunction('st');
|
||||
$this->assertEqual($reflector_t->getParameters(), $reflector_st->getParameters(), t('Function signatures of t() and st() are equal.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleJavascriptTranslation.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for JavaScript parsing for translatable strings.
|
||||
*/
|
||||
class LocaleJavascriptTranslation extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Javascript translation',
|
||||
'description' => 'Tests parsing js files for translatable strings',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
}
|
||||
|
||||
function testFileParsing() {
|
||||
|
||||
$filename = drupal_get_path('module', 'locale') . '/tests/locale_test.js';
|
||||
|
||||
// Parse the file to look for source strings.
|
||||
_locale_parse_js_file($filename);
|
||||
|
||||
// Get all of the source strings that were found.
|
||||
$source_strings = db_select('locales_source', 's')
|
||||
->fields('s', array('source', 'context'))
|
||||
->condition('s.location', $filename)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
|
||||
// List of all strings that should be in the file.
|
||||
$test_strings = array(
|
||||
"Standard Call t" => '',
|
||||
"Whitespace Call t" => '',
|
||||
|
||||
"Single Quote t" => '',
|
||||
"Single Quote \\'Escaped\\' t" => '',
|
||||
"Single Quote Concat strings t" => '',
|
||||
|
||||
"Double Quote t" => '',
|
||||
"Double Quote \\\"Escaped\\\" t" => '',
|
||||
"Double Quote Concat strings t" => '',
|
||||
|
||||
"Context !key Args t" => "Context string",
|
||||
|
||||
"Context Unquoted t" => "Context string unquoted",
|
||||
"Context Single Quoted t" => "Context string single quoted",
|
||||
"Context Double Quoted t" => "Context string double quoted",
|
||||
|
||||
"Standard Call plural" => '',
|
||||
"Standard Call @count plural" => '',
|
||||
"Whitespace Call plural" => '',
|
||||
"Whitespace Call @count plural" => '',
|
||||
|
||||
"Single Quote plural" => '',
|
||||
"Single Quote @count plural" => '',
|
||||
"Single Quote \\'Escaped\\' plural" => '',
|
||||
"Single Quote \\'Escaped\\' @count plural" => '',
|
||||
|
||||
"Double Quote plural" => '',
|
||||
"Double Quote @count plural" => '',
|
||||
"Double Quote \\\"Escaped\\\" plural" => '',
|
||||
"Double Quote \\\"Escaped\\\" @count plural" => '',
|
||||
|
||||
"Context !key Args plural" => "Context string",
|
||||
"Context !key Args @count plural" => "Context string",
|
||||
|
||||
"Context Unquoted plural" => "Context string unquoted",
|
||||
"Context Unquoted @count plural" => "Context string unquoted",
|
||||
"Context Single Quoted plural" => "Context string single quoted",
|
||||
"Context Single Quoted @count plural" => "Context string single quoted",
|
||||
"Context Double Quoted plural" => "Context string double quoted",
|
||||
"Context Double Quoted @count plural" => "Context string double quoted",
|
||||
);
|
||||
|
||||
// Assert that all strings were found properly.
|
||||
foreach ($test_strings as $str => $context) {
|
||||
$args = array('%source' => $str, '%context' => $context);
|
||||
|
||||
// Make sure that the string was found in the file.
|
||||
$this->assertTrue(isset($source_strings[$str]), t("Found source string: %source", $args));
|
||||
|
||||
// Make sure that the proper context was matched.
|
||||
$this->assertTrue(isset($source_strings[$str]) && $source_strings[$str] === $context, strlen($context) > 0 ? t("Context for %source is %context", $args) : t("Context for %source is blank", $args));
|
||||
}
|
||||
|
||||
$this->assertEqual(count($source_strings), count($test_strings), t("Found correct number of source strings."));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleMultilingualFieldsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional test for multilingual fields.
|
||||
*/
|
||||
class LocaleMultilingualFieldsTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Multilingual fields',
|
||||
'description' => 'Test multilingual support for fields.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'locale'));
|
||||
|
||||
// Create Basic page node type.
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
// Setup users.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages', 'create page content', 'edit own page content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add a new language.
|
||||
$language = (object) array(
|
||||
'langcode' => 'it',
|
||||
'name' => 'Italian',
|
||||
);
|
||||
language_save($language);
|
||||
|
||||
// Enable URL language detection and selection.
|
||||
$edit = array('language_interface[enabled][language-url]' => '1');
|
||||
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
|
||||
// Set "Basic page" content type to use multilingual support.
|
||||
$edit = array(
|
||||
'node_type_language' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
|
||||
|
||||
// Make node body translatable.
|
||||
$field = field_info_field('body');
|
||||
$field['translatable'] = TRUE;
|
||||
field_update_field($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if field languages are correctly set through the node form.
|
||||
*/
|
||||
function testMultilingualNodeForm() {
|
||||
// Create "Basic page" content.
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$title_value = $this->randomName(8);
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$body_value = $this->randomName(16);
|
||||
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $title_value;
|
||||
$edit[$body_key] = $body_value;
|
||||
$edit['langcode'] = 'en';
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
$assert = isset($node->body['en']) && !isset($node->body[LANGUAGE_NOT_SPECIFIED]) && $node->body['en'][0]['value'] == $body_value;
|
||||
$this->assertTrue($assert, t('Field language correctly set.'));
|
||||
|
||||
// Change node language.
|
||||
$this->drupalGet("node/$node->nid/edit");
|
||||
$edit = array(
|
||||
$title_key => $this->randomName(8),
|
||||
'langcode' => 'it'
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
$assert = isset($node->body['it']) && !isset($node->body['en']) && $node->body['it'][0]['value'] == $body_value;
|
||||
$this->assertTrue($assert, t('Field language correctly changed.'));
|
||||
|
||||
// Enable content language URL detection.
|
||||
language_negotiation_set(LANGUAGE_TYPE_CONTENT, array(LANGUAGE_NEGOTIATION_URL => 0));
|
||||
|
||||
// Test multilingual field language fallback logic.
|
||||
$this->drupalGet("it/node/$node->nid");
|
||||
$this->assertRaw($body_value, t('Body correctly displayed using Italian as requested language'));
|
||||
|
||||
$this->drupalGet("node/$node->nid");
|
||||
$this->assertRaw($body_value, t('Body correctly displayed using English as requested language'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test multilingual field display settings.
|
||||
*/
|
||||
function testMultilingualDisplaySettings() {
|
||||
// Create "Basic page" content.
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$title_value = $this->randomName(8);
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$body_value = $this->randomName(16);
|
||||
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $title_value;
|
||||
$edit[$body_key] = $body_value;
|
||||
$edit['langcode'] = 'en';
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
// Check if node body is showed.
|
||||
$this->drupalGet("node/$node->nid");
|
||||
$body = $this->xpath('//article[@id=:id]//div[@class=:class]/descendant::p', array(
|
||||
':id' => 'node-' . $node->nid,
|
||||
':class' => 'content',
|
||||
));
|
||||
$this->assertEqual(current($body), $node->body['en'][0]['value'], 'Node body found.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocalePathTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for configuring a different path alias per language.
|
||||
*/
|
||||
class LocalePathTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Path language settings',
|
||||
'description' => 'Checks you can configure a language for individual url aliases.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'locale', 'path'));
|
||||
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
variable_set('site_frontpage', 'node');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a language can be associated with a path alias.
|
||||
*/
|
||||
function testPathLanguageConfiguration() {
|
||||
global $base_url;
|
||||
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'create page content', 'administer url aliases', 'create url aliases', 'access administration pages'));
|
||||
|
||||
// Add custom language.
|
||||
$this->drupalLogin($admin_user);
|
||||
// Code for the language.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language.
|
||||
$name = $this->randomName(16);
|
||||
// The domain prefix.
|
||||
$prefix = $langcode;
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
|
||||
// Set path prefix.
|
||||
$edit = array( "prefix[$langcode]" => $prefix );
|
||||
$this->drupalPost('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
|
||||
|
||||
// Check that the "xx" front page is readily available because path prefix
|
||||
// negotiation is pre-configured.
|
||||
$this->drupalGet($prefix);
|
||||
$this->assertText(t('Welcome to Drupal'), t('The "xx" front page is readibly available.'));
|
||||
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode(array('type' => 'page'));
|
||||
|
||||
// Create a path alias in default language (English).
|
||||
$path = 'admin/config/search/path/add';
|
||||
$english_path = $this->randomName(8);
|
||||
$edit = array(
|
||||
'source' => 'node/' . $node->nid,
|
||||
'alias' => $english_path,
|
||||
'langcode' => 'en',
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save'));
|
||||
|
||||
// Create a path alias in new custom language.
|
||||
$custom_language_path = $this->randomName(8);
|
||||
$edit = array(
|
||||
'source' => 'node/' . $node->nid,
|
||||
'alias' => $custom_language_path,
|
||||
'langcode' => $langcode,
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save'));
|
||||
|
||||
// Confirm English language path alias works.
|
||||
$this->drupalGet($english_path);
|
||||
$this->assertText($node->title, t('English alias works.'));
|
||||
|
||||
// Confirm custom language path alias works.
|
||||
$this->drupalGet($prefix . '/' . $custom_language_path);
|
||||
$this->assertText($node->title, t('Custom language alias works.'));
|
||||
|
||||
// Create a custom path.
|
||||
$custom_path = $this->randomName(8);
|
||||
|
||||
// Check priority of language for alias by source path.
|
||||
$edit = array(
|
||||
'source' => 'node/' . $node->nid,
|
||||
'alias' => $custom_path,
|
||||
'langcode' => LANGUAGE_NOT_SPECIFIED,
|
||||
);
|
||||
path_save($edit);
|
||||
$lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, 'en');
|
||||
$this->assertEqual($english_path, $lookup_path, t('English language alias has priority.'));
|
||||
// Same check for language 'xx'.
|
||||
$lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, $prefix);
|
||||
$this->assertEqual($custom_language_path, $lookup_path, t('Custom language alias has priority.'));
|
||||
path_delete($edit);
|
||||
|
||||
// Create language nodes to check priority of aliases.
|
||||
$first_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
|
||||
$second_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
|
||||
|
||||
// Assign a custom path alias to the first node with the English language.
|
||||
$edit = array(
|
||||
'source' => 'node/' . $first_node->nid,
|
||||
'alias' => $custom_path,
|
||||
'langcode' => 'en',
|
||||
);
|
||||
path_save($edit);
|
||||
|
||||
// Assign a custom path alias to second node with LANGUAGE_NOT_SPECIFIED.
|
||||
$edit = array(
|
||||
'source' => 'node/' . $second_node->nid,
|
||||
'alias' => $custom_path,
|
||||
'langcode' => LANGUAGE_NOT_SPECIFIED,
|
||||
);
|
||||
path_save($edit);
|
||||
|
||||
// Test that both node titles link to our path alias.
|
||||
$this->drupalGet('<front>');
|
||||
$custom_path_url = base_path() . $GLOBALS['script_path'] . $custom_path;
|
||||
$elements = $this->xpath('//a[@href=:href and .=:title]', array(':href' => $custom_path_url, ':title' => $first_node->title));
|
||||
$this->assertTrue(!empty($elements), t('First node links to the path alias.'));
|
||||
$elements = $this->xpath('//a[@href=:href and .=:title]', array(':href' => $custom_path_url, ':title' => $second_node->title));
|
||||
$this->assertTrue(!empty($elements), t('Second node links to the path alias.'));
|
||||
|
||||
// Confirm that the custom path leads to the first node.
|
||||
$this->drupalGet($custom_path);
|
||||
$this->assertText($first_node->title, t('Custom alias returns first node.'));
|
||||
|
||||
// Confirm that the custom path with prefix leads to the second node.
|
||||
$this->drupalGet($prefix . '/' . $custom_path);
|
||||
$this->assertText($second_node->title, t('Custom alias with prefix returns second node.'));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocalePluralFormatTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests plural format handling functionality.
|
||||
*/
|
||||
class LocalePluralFormatTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Plural handling',
|
||||
'description' => 'Tests plural handling for various languages.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests locale_get_plural() and format_plural() functionality.
|
||||
*/
|
||||
function testGetPluralFormat() {
|
||||
// Import some .po files with formulas to set up the environment.
|
||||
// These will also add the languages to the system and enable them.
|
||||
$this->importPoFile($this->getPoFileWithSimplePlural(), array(
|
||||
'langcode' => 'fr',
|
||||
));
|
||||
$this->importPoFile($this->getPoFileWithComplexPlural(), array(
|
||||
'langcode' => 'hr',
|
||||
));
|
||||
|
||||
// Attempt to import some broken .po files as well to prove that these
|
||||
// will not overwrite the proper plural formula imported above.
|
||||
$this->importPoFile($this->getPoFileWithMissingPlural(), array(
|
||||
'langcode' => 'fr',
|
||||
'overwrite_options[not_customized]' => TRUE,
|
||||
));
|
||||
$this->importPoFile($this->getPoFileWithBrokenPlural(), array(
|
||||
'langcode' => 'hr',
|
||||
'overwrite_options[not_customized]' => TRUE,
|
||||
));
|
||||
|
||||
// Reset static caches from locale_get_plural() to ensure we get fresh data.
|
||||
drupal_static_reset('locale_get_plural');
|
||||
drupal_static_reset('locale_get_plural:plurals');
|
||||
drupal_static_reset('locale');
|
||||
|
||||
// Expected plural translation strings for each plural index.
|
||||
$plural_strings = array(
|
||||
// English is not imported in this case, so we assume built-in text
|
||||
// and formulas.
|
||||
'en' => array(
|
||||
0 => '1 hour',
|
||||
1 => '@count hours',
|
||||
),
|
||||
'fr' => array(
|
||||
0 => '1 heure',
|
||||
1 => '@count heures',
|
||||
),
|
||||
'hr' => array(
|
||||
0 => '@count sat',
|
||||
1 => '@count sata',
|
||||
2 => '@count sati',
|
||||
),
|
||||
// Hungarian is not imported, so it should assume the same text as
|
||||
// English, but it will always pick the plural form as per the built-in
|
||||
// logic, so only index -1 is relevant with the plural value.
|
||||
'hu' => array(
|
||||
0 => '1 hour',
|
||||
-1 => '@count hours',
|
||||
),
|
||||
);
|
||||
|
||||
// Expected plural indexes precomputed base on the plural formulas with
|
||||
// given $count value.
|
||||
$plural_tests = array(
|
||||
'en' => array(
|
||||
1 => 0,
|
||||
0 => 1,
|
||||
5 => 1,
|
||||
),
|
||||
'fr' => array(
|
||||
1 => 0,
|
||||
0 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'hr' => array(
|
||||
1 => 0,
|
||||
21 => 0,
|
||||
0 => 2,
|
||||
2 => 1,
|
||||
8 => 2,
|
||||
),
|
||||
'hu' => array(
|
||||
1 => -1,
|
||||
21 => -1,
|
||||
0 => -1,
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($plural_tests as $langcode => $tests) {
|
||||
foreach ($tests as $count => $expected_plural_index) {
|
||||
// Assert that the we get the right plural index.
|
||||
$this->assertIdentical(locale_get_plural($count, $langcode), $expected_plural_index, 'Computed plural index for ' . $langcode . ' for count ' . $count . ' is ' . $expected_plural_index);
|
||||
// Assert that the we get the right translation for that. Change the
|
||||
// expected index as per the logic for translation lookups.
|
||||
$expected_plural_index = ($count == 1) ? 0 : $expected_plural_index;
|
||||
$expected_plural_string = str_replace('@count', $count, $plural_strings[$langcode][$expected_plural_index]);
|
||||
$this->assertIdentical(format_plural($count, '1 hour', '@count hours', array(), array('langcode' => $langcode)), $expected_plural_string, 'Plural translation of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests plural editing and export functionality.
|
||||
*/
|
||||
function testPluralEditExport() {
|
||||
// Import some .po files with formulas to set up the environment.
|
||||
// These will also add the languages to the system and enable them.
|
||||
$this->importPoFile($this->getPoFileWithSimplePlural(), array(
|
||||
'langcode' => 'fr',
|
||||
));
|
||||
$this->importPoFile($this->getPoFileWithComplexPlural(), array(
|
||||
'langcode' => 'hr',
|
||||
));
|
||||
|
||||
// Get the French translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'fr',
|
||||
), t('Export'));
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# French translation of Drupal', t('Exported French translation file.'));
|
||||
// Ensure our imported translations exist in the file.
|
||||
$this->assertRaw("msgid \"Monday\"\nmsgstr \"lundi\"", t('French translations present in exported file.'));
|
||||
// Check for plural export specifically.
|
||||
$this->assertRaw("msgid \"1 hour\"\nmsgid_plural \"@count hours\"\nmsgstr[0] \"1 heure\"\nmsgstr[1] \"@count heures\"", t('Plural translations exported properly.'));
|
||||
|
||||
// Get the Croatian translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'hr',
|
||||
), t('Export'));
|
||||
// Ensure we have a translation file.
|
||||
$this->assertRaw('# Croatian translation of Drupal', t('Exported Croatian translation file.'));
|
||||
// Ensure our imported translations exist in the file.
|
||||
$this->assertRaw("msgid \"Monday\"\nmsgstr \"Ponedjeljak\"", t('Croatian translations present in exported file.'));
|
||||
// Check for plural export specifically.
|
||||
$this->assertRaw("msgid \"1 hour\"\nmsgid_plural \"@count hours\"\nmsgstr[0] \"@count sat\"\nmsgstr[1] \"@count sata\"\nmsgstr[2] \"@count sati\"", t('Plural translations exported properly.'));
|
||||
|
||||
// Check if the source appears on the translation page.
|
||||
$this->drupalGet('admin/config/regional/translate');
|
||||
$this->assertText("1 hour, @count hours");
|
||||
|
||||
// Look up editing page for this plural string and check fields.
|
||||
$lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = ''", array(':source' => "1 hour" . LOCALE_PLURAL_DELIMITER . "@count hours"))->fetchField();
|
||||
$path = 'admin/config/regional/translate/edit/' . $lid;
|
||||
$this->drupalGet($path);
|
||||
// Labels for plural editing elements.
|
||||
$this->assertText('Singular form');
|
||||
$this->assertText('First plural form');
|
||||
$this->assertText('2. plural form');
|
||||
// Plural values for both languages.
|
||||
$this->assertFieldById('edit-translations-hr-0', '@count sat');
|
||||
$this->assertFieldById('edit-translations-hr-1', '@count sata');
|
||||
$this->assertFieldById('edit-translations-hr-2', '@count sati');
|
||||
$this->assertNoFieldById('edit-translations-hr-3');
|
||||
$this->assertFieldById('edit-translations-fr-0', '1 heure');
|
||||
$this->assertFieldById('edit-translations-fr-1', '@count heures');
|
||||
$this->assertNoFieldById('edit-translations-fr-2');
|
||||
|
||||
// Edit some translations and see if that took effect.
|
||||
$edit = array(
|
||||
'translations[fr][0]' => '1 heure edited',
|
||||
'translations[hr][1]' => '@count sata edited',
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save translations'));
|
||||
|
||||
// Inject a plural source string to the database. We need to use a specific
|
||||
// langcode here because the language will be English by default and will
|
||||
// not save our source string for performance optimization if we do not ask
|
||||
// specifically for a language.
|
||||
format_plural(1, '1 day', '@count days', array(), array('langcode' => 'fr'));
|
||||
// Look up editing page for this plural string and check fields.
|
||||
$lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = ''", array(':source' => "1 day" . LOCALE_PLURAL_DELIMITER . "@count days"))->fetchField();
|
||||
$path = 'admin/config/regional/translate/edit/' . $lid;
|
||||
|
||||
// Save complete translations for the string in both languages.
|
||||
$edit = array(
|
||||
'translations[fr][0]' => '1 jour',
|
||||
'translations[fr][1]' => '@count jours',
|
||||
'translations[hr][0]' => '@count dan',
|
||||
'translations[hr][1]' => '@count dana',
|
||||
'translations[hr][2]' => '@count dana',
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save translations'));
|
||||
|
||||
// Get the French translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'fr',
|
||||
), t('Export'));
|
||||
// Check for plural export specifically.
|
||||
$this->assertRaw("msgid \"1 hour\"\nmsgid_plural \"@count hours\"\nmsgstr[0] \"1 heure edited\"\nmsgstr[1] \"@count heures\"", t('Edited French plural translations for hours exported properly.'));
|
||||
$this->assertRaw("msgid \"1 day\"\nmsgid_plural \"@count days\"\nmsgstr[0] \"1 jour\"\nmsgstr[1] \"@count jours\"", t('Added French plural translations for days exported properly.'));
|
||||
|
||||
// Get the Croatian translations.
|
||||
$this->drupalPost('admin/config/regional/translate/export', array(
|
||||
'langcode' => 'hr',
|
||||
), t('Export'));
|
||||
// Check for plural export specifically.
|
||||
$this->assertRaw("msgid \"1 hour\"\nmsgid_plural \"@count hours\"\nmsgstr[0] \"@count sat\"\nmsgstr[1] \"@count sata edited\"\nmsgstr[2] \"@count sati\"", t('Edited Croatian plural translations exported properly.'));
|
||||
$this->assertRaw("msgid \"1 day\"\nmsgid_plural \"@count days\"\nmsgstr[0] \"@count dan\"\nmsgstr[1] \"@count dana\"\nmsgstr[2] \"@count dana\"", t('Added Croatian plural translations exported properly.'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Imports a standalone .po file in a given language.
|
||||
*
|
||||
* @param $contents
|
||||
* Contents of the .po file to import.
|
||||
* @param $options
|
||||
* Additional options to pass to the translation import form.
|
||||
*/
|
||||
function importPoFile($contents, array $options = array()) {
|
||||
$name = tempnam('temporary://', "po_") . '.po';
|
||||
file_put_contents($name, $contents);
|
||||
$options['files[file]'] = $name;
|
||||
$this->drupalPost('admin/config/regional/translate/import', $options, t('Import'));
|
||||
drupal_unlink($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a .po file with a simple plural formula.
|
||||
*/
|
||||
function getPoFileWithSimplePlural() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
||||
|
||||
msgid "1 hour"
|
||||
msgid_plural "@count hours"
|
||||
msgstr[0] "1 heure"
|
||||
msgstr[1] "@count heures"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "lundi"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a .po file with a complex plural formula.
|
||||
*/
|
||||
function getPoFileWithComplexPlural() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\\n"
|
||||
|
||||
msgid "1 hour"
|
||||
msgid_plural "@count hours"
|
||||
msgstr[0] "@count sat"
|
||||
msgstr[1] "@count sata"
|
||||
msgstr[2] "@count sati"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "Ponedjeljak"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a .po file with a missing plural formula.
|
||||
*/
|
||||
function getPoFileWithMissingPlural() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "lundi"
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a .po file with a broken plural formula.
|
||||
*/
|
||||
function getPoFileWithBrokenPlural() {
|
||||
return <<< EOF
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Drupal 8\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
"Plural-Forms: broken, will not parse\\n"
|
||||
|
||||
msgid "Monday"
|
||||
msgstr "Ponedjeljak"
|
||||
EOF;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,418 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleTranslationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional test for string translation and validation.
|
||||
*/
|
||||
class LocaleTranslationTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'String translate, search and validate',
|
||||
'description' => 'Adds a new locale and translates its name. Checks the validation of translation strings and search results.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a language and tests string translation by users with the appropriate permissions.
|
||||
*/
|
||||
function testStringTranslation() {
|
||||
global $base_url;
|
||||
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages'));
|
||||
// User to translate and delete string.
|
||||
$translate_user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
|
||||
// Code for the language.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language. This will be translated.
|
||||
$name = $this->randomName(16);
|
||||
// This is the language indicator on the translation search screen for
|
||||
// untranslated strings.
|
||||
$language_indicator = "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
// This will be the translation of $name.
|
||||
$translation = $this->randomName(16);
|
||||
$translation_to_en = $this->randomName(16);
|
||||
|
||||
// Add custom language.
|
||||
$this->drupalLogin($admin_user);
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
// Add string.
|
||||
t($name, array(), array('langcode' => $langcode));
|
||||
// Reset locale cache.
|
||||
locale_reset();
|
||||
$this->assertRaw('"edit-site-default-' . $langcode .'"', t('Language code found.'));
|
||||
$this->assertText(t($name), t('Test language added.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Search for the name and translate it.
|
||||
$this->drupalLogin($translate_user);
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// assertText() seems to remove the input field where $name always could be
|
||||
// found, so this is not a false assert. See how assertNoText succeeds
|
||||
// later.
|
||||
$this->assertText($name, t('Search found the name.'));
|
||||
$this->assertRaw($language_indicator, t('Name is untranslated.'));
|
||||
// Assume this is the only result, given the random name.
|
||||
$this->clickLink(t('edit'));
|
||||
// We save the lid from the path.
|
||||
$matches = array();
|
||||
preg_match('!admin/config/regional/translate/edit/(\d+)!', $this->getUrl(), $matches);
|
||||
$lid = $matches[1];
|
||||
// No t() here, it's surely not translated yet.
|
||||
$this->assertText($name, t('name found on edit screen.'));
|
||||
$this->assertNoText('English', t('No way to translate the string to English.'));
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalPost('admin/config/regional/language/edit/en', array('locale_translate_english' => TRUE), t('Save language'));
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($translate_user);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// assertText() seems to remove the input field where $name always could be
|
||||
// found, so this is not a false assert. See how assertNoText succeeds
|
||||
// later.
|
||||
$this->assertText($name, t('Search found the name.'));
|
||||
$this->assertRaw($language_indicator, t('Name is untranslated.'));
|
||||
// Assume this is the only result, given the random name.
|
||||
$this->clickLink(t('edit'));
|
||||
$string_edit_url = $this->getUrl();
|
||||
$edit = array(
|
||||
"translations[$langcode][0]" => $translation,
|
||||
'translations[en][0]' => $translation_to_en,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save translations'));
|
||||
$this->assertText(t('The string has been saved.'), t('The string has been saved.'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
$this->drupalGet($string_edit_url);
|
||||
$this->assertRaw($translation, t('Non-English translation properly saved.'));
|
||||
$this->assertRaw($translation_to_en, t('English translation properly saved.'));
|
||||
$this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, t('t() works for non-English.'));
|
||||
// Refresh the locale() cache to get fresh data from t() below. We are in
|
||||
// the same HTTP request and therefore t() is not refreshed by saving the
|
||||
// translation above.
|
||||
locale_reset();
|
||||
// Now we should get the proper fresh translation from t().
|
||||
$this->assertTrue($name != $translation_to_en && t($name, array(), array('langcode' => 'en')) == $translation_to_en, t('t() works for English.'));
|
||||
$this->assertTrue(t($name, array(), array('langcode' => LANGUAGE_SYSTEM)) == $name, t('t() works for LANGUAGE_SYSTEM.'));
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// The indicator should not be here.
|
||||
$this->assertNoRaw($language_indicator, t('String is translated.'));
|
||||
|
||||
// Try to edit a non-existent string and ensure we're redirected correctly.
|
||||
// Assuming we don't have 999,999 strings already.
|
||||
$random_lid = 999999;
|
||||
$this->drupalGet('admin/config/regional/translate/edit/' . $random_lid);
|
||||
$this->assertText(t('String not found'), t('String not found.'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Delete the language.
|
||||
$this->drupalLogin($admin_user);
|
||||
$path = 'admin/config/regional/language/delete/' . $langcode;
|
||||
// This a confirm form, we do not need any fields changed.
|
||||
$this->drupalPost($path, array(), t('Delete'));
|
||||
// We need raw here because %language and %langcode will add HTML.
|
||||
$t_args = array('%language' => $name, '%langcode' => $langcode);
|
||||
$this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), t('The test language has been removed.'));
|
||||
// Reload to remove $name.
|
||||
$this->drupalGet($path);
|
||||
// Verify that language is no longer found.
|
||||
$this->assertResponse(404, t('Language no longer found.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Delete the string.
|
||||
$this->drupalLogin($translate_user);
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// Assume this is the only result, given the random name.
|
||||
$this->clickLink(t('delete'));
|
||||
$this->assertText(t('Are you sure you want to delete the string'), t('"delete" link is correct.'));
|
||||
// Delete the string.
|
||||
$path = 'admin/config/regional/translate/delete/' . $lid;
|
||||
$this->drupalGet($path);
|
||||
// First test the 'cancel' link.
|
||||
$this->clickLink(t('Cancel'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
$this->assertRaw($name, t('The string was not deleted.'));
|
||||
// Delete the name string.
|
||||
$this->drupalPost('admin/config/regional/translate/delete/' . $lid, array(), t('Delete'));
|
||||
$this->assertText(t('The string has been removed.'), t('The string has been removed message.'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText($name, t('Search now can not find the name.'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a language and checks that the JavaScript translation files are
|
||||
* properly created and rebuilt on deletion.
|
||||
*/
|
||||
function testJavaScriptTranslation() {
|
||||
$user = $this->drupalCreateUser(array('translate interface', 'administer languages', 'access administration pages'));
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$langcode = 'xx';
|
||||
// The English name for the language. This will be translated.
|
||||
$name = $this->randomName(16);
|
||||
|
||||
// Add custom language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
drupal_static_reset('language_list');
|
||||
|
||||
// Build the JavaScript translation file.
|
||||
$this->drupalGet('admin/config/regional/translate/translate');
|
||||
|
||||
// Retrieve the id of the first string available in the {locales_source}
|
||||
// table and translate it.
|
||||
$query = db_select('locales_source', 'l');
|
||||
$query->addExpression('min(l.lid)', 'lid');
|
||||
$result = $query->condition('l.location', '%.js%', 'LIKE')->execute();
|
||||
$url = 'admin/config/regional/translate/edit/' . $result->fetchObject()->lid;
|
||||
$edit = array('translations['. $langcode .'][0]' => $this->randomName());
|
||||
$this->drupalPost($url, $edit, t('Save translations'));
|
||||
|
||||
// Trigger JavaScript translation parsing and building.
|
||||
_locale_rebuild_js($langcode);
|
||||
|
||||
$locale_javascripts = variable_get('locale_translation_javascript', array());
|
||||
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/' . $langcode . '_' . $locale_javascripts[$langcode] . '.js';
|
||||
$this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('not found'))));
|
||||
|
||||
// Test JavaScript translation rebuilding.
|
||||
file_unmanaged_delete($js_file);
|
||||
$this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found'))));
|
||||
cache_clear_all();
|
||||
_locale_rebuild_js($langcode);
|
||||
$this->assertTrue($result = file_exists($js_file), t('JavaScript file rebuilt: %file', array('%file' => $result ? $js_file : t('not found'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the validation of the translation input.
|
||||
*/
|
||||
function testStringValidation() {
|
||||
global $base_url;
|
||||
|
||||
// User to add language and strings.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'translate interface'));
|
||||
$this->drupalLogin($admin_user);
|
||||
$langcode = 'xx';
|
||||
// The English name for the language. This will be translated.
|
||||
$name = $this->randomName(16);
|
||||
// This is the language indicator on the translation search screen for
|
||||
// untranslated strings.
|
||||
$language_indicator = "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
// These will be the invalid translations of $name.
|
||||
$key = $this->randomName(16);
|
||||
$bad_translations[$key] = "<script>alert('xss');</script>" . $key;
|
||||
$key = $this->randomName(16);
|
||||
$bad_translations[$key] = '<img SRC="javascript:alert(\'xss\');">' . $key;
|
||||
$key = $this->randomName(16);
|
||||
$bad_translations[$key] = '<<SCRIPT>alert("xss");//<</SCRIPT>' . $key;
|
||||
$key = $this->randomName(16);
|
||||
$bad_translations[$key] ="<BODY ONLOAD=alert('xss')>" . $key;
|
||||
|
||||
// Add custom language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
// Add string.
|
||||
t($name, array(), array('langcode' => $langcode));
|
||||
// Reset locale cache.
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// Find the edit path.
|
||||
$content = $this->drupalGetContent();
|
||||
$this->assertTrue(preg_match('@(admin/config/regional/translate/edit/[0-9]+)@', $content, $matches), t('Found the edit path.'));
|
||||
$path = $matches[0];
|
||||
foreach ($bad_translations as $key => $translation) {
|
||||
$edit = array(
|
||||
"translations[$langcode][0]" => $translation,
|
||||
);
|
||||
$this->drupalPost($path, $edit, t('Save translations'));
|
||||
// Check for a form error on the textarea.
|
||||
$form_class = $this->xpath('//form[@id="locale-translate-edit-form"]//textarea/@class');
|
||||
$this->assertNotIdentical(FALSE, strpos($form_class[0], 'error'), t('The string was rejected as unsafe.'));
|
||||
$this->assertNoText(t('The string has been saved.'), t('The string was not saved.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests translation search form.
|
||||
*/
|
||||
function testStringSearch() {
|
||||
global $base_url;
|
||||
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages'));
|
||||
// User to translate and delete string.
|
||||
$translate_user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
|
||||
|
||||
// Code for the language.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language. This will be translated.
|
||||
$name = $this->randomName(16);
|
||||
// This is the language indicator on the translation search screen for
|
||||
// untranslated strings.
|
||||
$language_indicator = "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
// This will be the translation of $name.
|
||||
$translation = $this->randomName(16);
|
||||
|
||||
// Add custom language.
|
||||
$this->drupalLogin($admin_user);
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'name' => $name,
|
||||
'direction' => '0',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
// Add string.
|
||||
t($name, array(), array('langcode' => $langcode));
|
||||
// Reset locale cache.
|
||||
locale_reset();
|
||||
$this->drupalLogout();
|
||||
|
||||
// Search for the name.
|
||||
$this->drupalLogin($translate_user);
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
// assertText() seems to remove the input field where $name always could be
|
||||
// found, so this is not a false assert. See how assertNoText succeeds
|
||||
// later.
|
||||
$this->assertText($name, t('Search found the string.'));
|
||||
|
||||
// Ensure untranslated string doesn't appear if searching on 'only
|
||||
// translated strings'.
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t("Search didn't find the string."));
|
||||
|
||||
// Ensure untranslated string appears if searching on 'only untranslated
|
||||
// strings'.
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'untranslated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('Search found the string.'));
|
||||
|
||||
// Add translation.
|
||||
// Assume this is the only result, given the random name.
|
||||
$this->clickLink(t('edit'));
|
||||
// We save the lid from the path.
|
||||
$matches = array();
|
||||
preg_match('!admin/config/regional/translate/edit/(\d)+!', $this->getUrl(), $matches);
|
||||
$lid = $matches[1];
|
||||
$edit = array(
|
||||
"translations[$langcode][0]" => $translation,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save translations'));
|
||||
|
||||
// Ensure translated string does appear if searching on 'only
|
||||
// translated strings'.
|
||||
$search = array(
|
||||
'string' => $translation,
|
||||
'language' => 'all',
|
||||
'translation' => 'translated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('Search found the translation.'));
|
||||
|
||||
// Ensure translated source string doesn't appear if searching on 'only
|
||||
// untranslated strings'.
|
||||
$search = array(
|
||||
'string' => $name,
|
||||
'language' => 'all',
|
||||
'translation' => 'untranslated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t("Search didn't find the source string."));
|
||||
|
||||
// Ensure translated string doesn't appear if searching on 'only
|
||||
// untranslated strings'.
|
||||
$search = array(
|
||||
'string' => $translation,
|
||||
'language' => 'all',
|
||||
'translation' => 'untranslated',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t("Search didn't find the translation."));
|
||||
|
||||
// Ensure translated string does appear if searching on the custom language.
|
||||
$search = array(
|
||||
'string' => $translation,
|
||||
'language' => $langcode,
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertNoText(t('No strings available.'), t('Search found the translation.'));
|
||||
|
||||
// Ensure translated string doesn't appear if searching in System (English).
|
||||
$search = array(
|
||||
'string' => $translation,
|
||||
'language' => LANGUAGE_SYSTEM,
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t("Search didn't find the translation."));
|
||||
|
||||
// Search for a string that isn't in the system.
|
||||
$unavailable_string = $this->randomName(16);
|
||||
$search = array(
|
||||
'string' => $unavailable_string,
|
||||
'language' => 'all',
|
||||
'translation' => 'all',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
|
||||
$this->assertText(t('No strings available.'), t("Search didn't find the invalid string."));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleUninstallFrenchTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
/**
|
||||
* Locale uninstall with French UI functional test.
|
||||
*
|
||||
* Because this class extends LocaleUninstallFunctionalTest, it doesn't require a new
|
||||
* test of its own. Rather, it switches the default UI language in setUp and then
|
||||
* runs the testUninstallProcess (which it inherits from LocaleUninstallFunctionalTest)
|
||||
* to test with this new language.
|
||||
*/
|
||||
class LocaleUninstallFrenchTest extends LocaleUninstallTest {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Locale uninstall (FR)',
|
||||
'description' => 'Tests the uninstall process using French as interface language.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
$this->langcode = 'fr';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\locale\Tests\LocaleUninstallTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\locale\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Locale uninstall with English UI functional test.
|
||||
*/
|
||||
class LocaleUninstallTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Locale uninstall (EN)',
|
||||
'description' => 'Tests the uninstall process using the built-in UI language.',
|
||||
'group' => 'Locale',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default language set for the UI before uninstall.
|
||||
*/
|
||||
protected $language;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'locale'));
|
||||
$this->langcode = 'en';
|
||||
|
||||
// Create Article node type.
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the values of the Locale variables are correct after uninstall.
|
||||
*/
|
||||
function testUninstallProcess() {
|
||||
$locale_module = array('locale', 'language');
|
||||
|
||||
$language = (object) array(
|
||||
'langcode' => 'fr',
|
||||
'name' => 'French',
|
||||
'default' => $this->langcode == 'fr',
|
||||
);
|
||||
language_save($language);
|
||||
|
||||
// Check the UI language.
|
||||
drupal_language_initialize();
|
||||
$this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode)));
|
||||
|
||||
// Enable multilingual workflow option for articles.
|
||||
variable_set('node_type_language_article', 1);
|
||||
|
||||
// Change JavaScript translations directory.
|
||||
variable_set('locale_js_directory', 'js_translations');
|
||||
|
||||
// Build the JavaScript translation file for French.
|
||||
$user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalGet('admin/config/regional/translate/translate');
|
||||
$string = db_query('SELECT min(lid) AS lid FROM {locales_source} WHERE location LIKE :location', array(
|
||||
':location' => '%.js%',
|
||||
))->fetchObject();
|
||||
$edit = array('translations[fr][0]' => 'french translation');
|
||||
$this->drupalPost('admin/config/regional/translate/edit/' . $string->lid, $edit, t('Save translations'));
|
||||
_locale_rebuild_js('fr');
|
||||
$locale_javascripts = variable_get('locale_translation_javascript', array());
|
||||
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $locale_javascripts['fr'] . '.js';
|
||||
$this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('none'))));
|
||||
|
||||
// Disable string caching.
|
||||
variable_set('locale_cache_strings', 0);
|
||||
|
||||
// Change language negotiation options.
|
||||
drupal_load('module', 'locale');
|
||||
variable_set('language_types', language_types_get_default() + array('language_custom' => TRUE));
|
||||
variable_set('language_negotiation_' . LANGUAGE_TYPE_INTERFACE, language_language_negotiation_info());
|
||||
variable_set('language_negotiation_' . LANGUAGE_TYPE_CONTENT, language_language_negotiation_info());
|
||||
variable_set('language_negotiation_' . LANGUAGE_TYPE_URL, language_language_negotiation_info());
|
||||
|
||||
// Change language negotiation settings.
|
||||
variable_set('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX);
|
||||
variable_set('language_negotiation_session_param', TRUE);
|
||||
|
||||
// Uninstall Locale.
|
||||
module_disable($locale_module);
|
||||
drupal_uninstall_modules($locale_module);
|
||||
|
||||
// Visit the front page.
|
||||
$this->drupalGet('');
|
||||
|
||||
// Check the init language logic.
|
||||
drupal_language_initialize();
|
||||
$this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, 'en', t('Language after uninstall: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode)));
|
||||
|
||||
// Check JavaScript files deletion.
|
||||
$this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found'))));
|
||||
|
||||
// Check language count.
|
||||
$language_count = variable_get('language_count', 1);
|
||||
$this->assertEqual($language_count, 1, t('Language count: %count', array('%count' => $language_count)));
|
||||
|
||||
// Check language negotiation.
|
||||
require_once DRUPAL_ROOT . '/core/includes/language.inc';
|
||||
$this->assertTrue(count(language_types_get_all()) == count(language_types_get_default()), t('Language types reset'));
|
||||
$language_negotiation = language_negotiation_method_get_first(LANGUAGE_TYPE_INTERFACE) == LANGUAGE_NEGOTIATION_DEFAULT;
|
||||
$this->assertTrue($language_negotiation, t('Interface language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
|
||||
$language_negotiation = language_negotiation_method_get_first(LANGUAGE_TYPE_CONTENT) == LANGUAGE_NEGOTIATION_DEFAULT;
|
||||
$this->assertTrue($language_negotiation, t('Content language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
|
||||
$language_negotiation = language_negotiation_method_get_first(LANGUAGE_TYPE_URL) == LANGUAGE_NEGOTIATION_DEFAULT;
|
||||
$this->assertTrue($language_negotiation, t('URL language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
|
||||
|
||||
// Check language negotiation method settings.
|
||||
$this->assertFalse(variable_get('language_negotiation_url_part', FALSE), t('URL language negotiation method indicator settings cleared.'));
|
||||
$this->assertFalse(variable_get('language_negotiation_session_param', FALSE), t('Visit language negotiation method settings cleared.'));
|
||||
|
||||
// Check JavaScript parsed.
|
||||
$javascript_parsed_count = count(variable_get('javascript_parsed', array()));
|
||||
$this->assertEqual($javascript_parsed_count, 0, t('JavaScript parsed count: %count', array('%count' => $javascript_parsed_count)));
|
||||
|
||||
// Check JavaScript translations directory.
|
||||
$locale_js_directory = variable_get('locale_js_directory', 'languages');
|
||||
$this->assertEqual($locale_js_directory, 'languages', t('JavaScript translations directory: %dir', array('%dir' => $locale_js_directory)));
|
||||
|
||||
// Check string caching.
|
||||
$locale_cache_strings = variable_get('locale_cache_strings', 1);
|
||||
$this->assertEqual($locale_cache_strings, 1, t('String caching: %status', array('%status' => t($locale_cache_strings ? 'enabled': 'disabled'))));
|
||||
}
|
||||
}
|
|
@ -4,4 +4,3 @@ package = Core
|
|||
version = VERSION
|
||||
core = 8.x
|
||||
dependencies[] = language
|
||||
files[] = locale.test
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue