diff --git a/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php b/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php index 4650bad..f6c5b69 100644 --- a/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php +++ b/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php @@ -20,7 +20,7 @@ class MultiStepNodeFormBasicOptionsTest extends NodeTestBase { * * @var string */ - protected $field_name; + protected $fieldName; /** * Tests changing the default values of basic options to ensure they persist. @@ -31,9 +31,9 @@ function testMultiStepNodeFormBasicOptions() { $this->drupalLogin($web_user); // Create an unlimited cardinality field. - $this->field_name = Unicode::strtolower($this->randomMachineName()); + $this->fieldName = Unicode::strtolower($this->randomMachineName()); entity_create('field_storage_config', array( - 'field_name' => $this->field_name, + 'field_name' => $this->fieldName, 'entity_type' => 'node', 'type' => 'text', 'cardinality' => -1, @@ -41,13 +41,13 @@ function testMultiStepNodeFormBasicOptions() { // Attach an instance of the field to the page content type. entity_create('field_config', array( - 'field_name' => $this->field_name, + 'field_name' => $this->fieldName, 'entity_type' => 'node', 'bundle' => 'page', 'label' => $this->randomMachineName() . '_label', ))->save(); entity_get_form_display('node', 'page', 'default') - ->setComponent($this->field_name, array( + ->setComponent($this->fieldName, array( 'type' => 'text_textfield', )) ->save(); @@ -56,7 +56,7 @@ function testMultiStepNodeFormBasicOptions() { 'title[0][value]' => 'a', 'promote[value]' => FALSE, 'sticky[value]' => 1, - "{$this->field_name}[0][value]" => $this->randomString(32), + "{$this->fieldName}[0][value]" => $this->randomString(32), ); $this->drupalPostForm('node/add/page', $edit, t('Add another item')); $this->assertNoFieldChecked('edit-promote-value', 'Promote stayed unchecked'); diff --git a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php index d5e4dd4..342ee77 100644 --- a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php +++ b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php @@ -30,6 +30,22 @@ class NodeAccessBaseTableTest extends NodeTestBase { */ protected $profile = 'standard'; + /** + * An array (keyed by uid and nid) to track which nodes are 'private'. + * + * For each user ID/node ID, $nodes[$uid][$nid] = $is_private. + * + * @var array + */ + protected $nodesByUser = array(); + + /** + * An array of nids that are found to be visible while testing. + * + * @var array + */ + protected $nidsVisible = array(); + protected function setUp() { parent::setUp(); @@ -57,8 +73,7 @@ function testNodeAccessBasic() { $num_simple_users = 2; $simple_users = array(); - // nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private; - $this->nodesByUser = array(); + $titles = array(); // Titles keyed by nid $private_nodes = array(); // Array of nids marked private. for ($i = 0; $i < $num_simple_users; $i++) { @@ -147,11 +162,11 @@ function testNodeAccessBasic() { protected function assertTaxonomyPage($is_admin) { foreach (array($this->publicTid, $this->privateTid) as $tid_is_private => $tid) { $this->drupalGet("taxonomy/term/$tid"); - $this->nids_visible = array(); + $this->nidsVisible = array(); foreach ($this->xpath("//a[text()='Read more']") as $link) { // See also testTranslationRendering() in NodeTranslationUITest. $this->assertTrue(preg_match('|node/(\d+)$|', (string) $link['href'], $matches), 'Read more points to a node'); - $this->nids_visible[$matches[1]] = TRUE; + $this->nidsVisible[$matches[1]] = TRUE; } foreach ($this->nodesByUser as $uid => $data) { foreach ($data as $nid => $is_private) { @@ -163,10 +178,10 @@ protected function assertTaxonomyPage($is_admin) { if (!$is_admin && $tid_is_private) { $should_be_visible = $should_be_visible && $uid == $this->webUser->id(); } - $this->assertIdentical(isset($this->nids_visible[$nid]), $should_be_visible, strtr('A %private node by user %uid is %visible for user %current_uid on the %tid_is_private page.', array( + $this->assertIdentical(isset($this->nidsVisible[$nid]), $should_be_visible, strtr('A %private node by user %uid is %visible for user %current_uid on the %tid_is_private page.', array( '%private' => $is_private ? 'private' : 'public', '%uid' => $uid, - '%visible' => isset($this->nids_visible[$nid]) ? 'visible' : 'not visible', + '%visible' => isset($this->nidsVisible[$nid]) ? 'visible' : 'not visible', '%current_uid' => $this->webUser->id(), '%tid_is_private' => $tid_is_private ? 'private' : 'public', ))); diff --git a/core/modules/node/src/Tests/NodeAdminTest.php b/core/modules/node/src/Tests/NodeAdminTest.php index 616538c..52542c0 100644 --- a/core/modules/node/src/Tests/NodeAdminTest.php +++ b/core/modules/node/src/Tests/NodeAdminTest.php @@ -21,6 +21,33 @@ class NodeAdminTest extends NodeTestBase { protected $adminUser; /** + * A regular user with the 'access content overview' permission. + * + * @var \Drupal\user\UserInterface + */ + protected $baseUser1; + + /** + * A regular user with permission to view their own unpublished content. + * + * This user has both 'access content overview' and 'view own unpublished + * content' permissions. + * + * @var \Drupal\user\UserInterface + */ + protected $baseUser2; + + /** + * A regular user with permission to bypass node access rules. + * + * This user has both 'access content overview' and 'bypass node access' + * permissions. + * + * @var \Drupal\user\UserInterface + */ + protected $baseUser3; + + /** * Modules to enable. * * @var array @@ -36,9 +63,9 @@ protected function setUp() { user_role_revoke_permissions(DRUPAL_AUTHENTICATED_RID, array('view own unpublished content')); $this->adminUser = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access')); - $this->base_user_1 = $this->drupalCreateUser(array('access content overview')); - $this->base_user_2 = $this->drupalCreateUser(array('access content overview', 'view own unpublished content')); - $this->base_user_3 = $this->drupalCreateUser(array('access content overview', 'bypass node access')); + $this->baseUser1 = $this->drupalCreateUser(array('access content overview')); + $this->baseUser2 = $this->drupalCreateUser(array('access content overview', 'view own unpublished content')); + $this->baseUser3 = $this->drupalCreateUser(array('access content overview', 'bypass node access')); } /** @@ -97,8 +124,8 @@ function testContentAdminPages() { $nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page')); $nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article')); - $nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_1->id(), 'status' => 0)); - $nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_2->id(), 'status' => 0)); + $nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser1->id(), 'status' => 0)); + $nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->baseUser2->id(), 'status' => 0)); // Verify view, edit, and delete links for any content. $this->drupalGet('admin/content'); @@ -124,7 +151,7 @@ function testContentAdminPages() { // Verify no operation links are displayed for regular users. $this->drupalLogout(); - $this->drupalLogin($this->base_user_1); + $this->drupalLogin($this->baseUser1); $this->drupalGet('admin/content'); $this->assertResponse(200); $this->assertLinkByHref('node/' . $nodes['published_page']->id()); @@ -144,7 +171,7 @@ function testContentAdminPages() { // Verify unpublished content is displayed with permission. $this->drupalLogout(); - $this->drupalLogin($this->base_user_2); + $this->drupalLogin($this->baseUser2); $this->drupalGet('admin/content'); $this->assertResponse(200); $this->assertLinkByHref('node/' . $nodes['unpublished_page_2']->id()); @@ -162,7 +189,7 @@ function testContentAdminPages() { // Verify node access can be bypassed. $this->drupalLogout(); - $this->drupalLogin($this->base_user_3); + $this->drupalLogin($this->baseUser3); $this->drupalGet('admin/content'); $this->assertResponse(200); foreach ($nodes as $node) { diff --git a/core/modules/node/src/Tests/NodeQueryAlterTest.php b/core/modules/node/src/Tests/NodeQueryAlterTest.php index a26dcd0..ea0ce7b 100644 --- a/core/modules/node/src/Tests/NodeQueryAlterTest.php +++ b/core/modules/node/src/Tests/NodeQueryAlterTest.php @@ -23,14 +23,25 @@ class NodeQueryAlterTest extends NodeTestBase { /** * User with permission to view content. + * + * @var \Drupal\user\UserInterface */ protected $accessUser; /** - * User without permission to view content. + * A first user without permission to view content. + * + * @var \Drupal\user\UserInterface */ protected $noAccessUser; + /** + * A second user without permission to view content. + * + * @var \Drupal\user\UserInterface + */ + protected $noAccessUser2; + protected function setUp() { parent::setUp(); diff --git a/core/modules/node/src/Tests/NodeRevisionPermissionsTest.php b/core/modules/node/src/Tests/NodeRevisionPermissionsTest.php index cd65dba..b3b3ecd 100644 --- a/core/modules/node/src/Tests/NodeRevisionPermissionsTest.php +++ b/core/modules/node/src/Tests/NodeRevisionPermissionsTest.php @@ -13,7 +13,21 @@ * @group node */ class NodeRevisionPermissionsTest extends NodeTestBase { - protected $node_revisions = array(); + /** + * An array containing multiple revisions of multiple types of nodes. + * + * Each element of this array (whose key specifies a type of node) points + * to an array containing one node and four revisions of the same node. + * + * @var array + */ + protected $nodeRevisions = array(); + + /** + * An array containing user accounts for testing purposes. + * + * @var array (of \Drupal\user\Entity\UserInterface) + */ protected $accounts = array(); // Map revision permission names to node revision access ops. @@ -24,7 +38,7 @@ class NodeRevisionPermissionsTest extends NodeTestBase { ); // Map revision permission names to node type revision access ops. - protected $type_map = array( + protected $typeMap = array( 'view' => 'view page revisions', 'update' => 'revert page revisions', 'delete' => 'delete page revisions', @@ -38,7 +52,7 @@ protected function setUp() { foreach ($types as $type) { // Create a node with several revisions. $nodes[$type] = $this->drupalCreateNode(array('type' => $type)); - $this->node_revisions[$type][] = $nodes[$type]; + $this->nodeRevisions[$type][] = $nodes[$type]; for ($i = 0; $i < 3; $i++) { // Create a revision for the same nid and settings with a random log. @@ -46,7 +60,7 @@ protected function setUp() { $revision->setNewRevision(); $revision->revision_log = $this->randomMachineName(32); $revision->save(); - $this->node_revisions[$type][] = $revision; + $this->nodeRevisions[$type][] = $revision; } } } @@ -81,7 +95,7 @@ function testNodeRevisionAccessAnyType() { $normal_account->op = FALSE; $this->accounts[] = $normal_account; $accounts[] = $normal_account; - $revision = $this->node_revisions['page'][1]; + $revision = $this->nodeRevisions['page'][1]; $parameters = array( 'op' => array_keys($this->map), @@ -114,7 +128,7 @@ function testNodeRevisionAccessAnyType() { */ function testNodeRevisionAccessPerType() { // Create three users, one with each revision permission. - foreach ($this->type_map as $op => $permission) { + foreach ($this->typeMap as $op => $permission) { // Create the user. $account = $this->drupalCreateUser( array( @@ -129,32 +143,32 @@ function testNodeRevisionAccessPerType() { } $parameters = array( - 'op' => array_keys($this->type_map), + 'op' => array_keys($this->typeMap), 'account' => $accounts, ); // Test that the accounts have access to the correspoding page revision permissions. - $revision = $this->node_revisions['page'][1]; + $revision = $this->nodeRevisions['page'][1]; $permutations = $this->generatePermutations($parameters); $node_revision_access = \Drupal::service('access_check.node.revision'); foreach ($permutations as $case) { // Skip this test if there are no revisions for the node. if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $revision->id()))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) { - if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->type_map[$case['op']], $case['account'])) { - $this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->type_map[$case['op']]} granted."); + if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->typeMap[$case['op']], $case['account'])) { + $this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} granted."); } else { - $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->type_map[$case['op']]} not granted."); + $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} not granted."); } } } // Test that the accounts have no access to the article revisions. - $revision = $this->node_revisions['article'][1]; + $revision = $this->nodeRevisions['article'][1]; foreach ($permutations as $case) { - $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->type_map[$case['op']]} did not grant revision permission for articles."); + $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} did not grant revision permission for articles."); } } } diff --git a/core/modules/node/src/Tests/PageEditTest.php b/core/modules/node/src/Tests/PageEditTest.php index b2d818b..41aad7b 100644 --- a/core/modules/node/src/Tests/PageEditTest.php +++ b/core/modules/node/src/Tests/PageEditTest.php @@ -13,7 +13,18 @@ * @group node */ class PageEditTest extends NodeTestBase { + /** + * A user with 'edit own page content' and 'create page content' permissions. + * + * @var \Drupal\user\UserInterface + */ protected $webUser; + + /** + * A user with permission to bypass node access and administer nodes. + * + * @var \Drupal\user\UserInterface + */ protected $adminUser; protected function setUp() { diff --git a/core/modules/node/src/Tests/PagePreviewTest.php b/core/modules/node/src/Tests/PagePreviewTest.php index 5fc64d3..c02a8ec 100644 --- a/core/modules/node/src/Tests/PagePreviewTest.php +++ b/core/modules/node/src/Tests/PagePreviewTest.php @@ -30,7 +30,7 @@ class PagePreviewTest extends NodeTestBase { * * @var string */ - protected $field_name; + protected $fieldName; protected function setUp() { parent::setUp(); @@ -62,9 +62,9 @@ protected function setUp() { $this->term = $term; // Create a field. - $this->field_name = Unicode::strtolower($this->randomMachineName()); + $this->fieldName = Unicode::strtolower($this->randomMachineName()); entity_create('field_storage_config', array( - 'field_name' => $this->field_name, + 'field_name' => $this->fieldName, 'entity_type' => 'node', 'type' => 'taxonomy_term_reference', 'settings' => array( @@ -78,25 +78,25 @@ protected function setUp() { 'cardinality' => '-1', ))->save(); entity_create('field_config', array( - 'field_name' => $this->field_name, + 'field_name' => $this->fieldName, 'entity_type' => 'node', 'bundle' => 'page', ))->save(); entity_get_form_display('node', 'page', 'default') - ->setComponent($this->field_name, array( + ->setComponent($this->fieldName, array( 'type' => 'taxonomy_autocomplete', )) ->save(); // Show on default display and teaser. entity_get_display('node', 'page', 'default') - ->setComponent($this->field_name, array( + ->setComponent($this->fieldName, array( 'type' => 'taxonomy_term_reference_link', )) ->save(); entity_get_display('node', 'page', 'teaser') - ->setComponent($this->field_name, array( + ->setComponent($this->fieldName, array( 'type' => 'taxonomy_term_reference_link', )) ->save(); @@ -108,7 +108,7 @@ protected function setUp() { function testPagePreview() { $title_key = 'title[0][value]'; $body_key = 'body[0][value]'; - $term_key = $this->field_name; + $term_key = $this->fieldName; // Fill in node creation form and preview node. $edit = array(); @@ -202,7 +202,7 @@ function testPagePreview() { function testPagePreviewWithRevisions() { $title_key = 'title[0][value]'; $body_key = 'body[0][value]'; - $term_key = $this->field_name; + $term_key = $this->fieldName; // Force revision on "Basic page" content. $node_type = NodeType::load('page'); $node_type->setNewRevision(TRUE); diff --git a/core/modules/node/src/Tests/Views/NodeFieldFilterTest.php b/core/modules/node/src/Tests/Views/NodeFieldFilterTest.php index 599b126..2fa9bec 100644 --- a/core/modules/node/src/Tests/Views/NodeFieldFilterTest.php +++ b/core/modules/node/src/Tests/Views/NodeFieldFilterTest.php @@ -34,7 +34,7 @@ class NodeFieldFilterTest extends NodeTestBase { * * @var array */ - public $node_titles = array(); + public $nodeTitles = array(); function setUp() { parent::setUp(); @@ -55,17 +55,17 @@ function setUp() { $field_storage->save(); // Set up node titles. - $this->node_titles = array( + $this->nodeTitles = array( 'en' => 'Food in Paris', 'es' => 'Comida en Paris', 'fr' => 'Nouriture en Paris', ); // Create node with translations. - $node = $this->drupalCreateNode(array('title' => $this->node_titles['en'], 'langcode' => 'en', 'type' => 'page', 'body' => array(array('value' => $this->node_titles['en'])))); + $node = $this->drupalCreateNode(array('title' => $this->nodeTitles['en'], 'langcode' => 'en', 'type' => 'page', 'body' => array(array('value' => $this->nodeTitles['en'])))); foreach (array('es', 'fr') as $langcode) { - $translation = $node->addTranslation($langcode, array('title' => $this->node_titles[$langcode])); - $translation->body->value = $this->node_titles[$langcode]; + $translation = $node->addTranslation($langcode, array('title' => $this->nodeTitles[$langcode])); + $translation->body->value = $this->nodeTitles[$langcode]; } $node->save(); } @@ -114,7 +114,7 @@ protected function assertPageCounts($path, $counts, $message) { // page, and they are the same. So the title/body string should appear on // the page twice as many times as the input count. foreach ($counts as $langcode => $count) { - $this->assertEqual(substr_count($text, $this->node_titles[$langcode]), 2 * $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message); + $this->assertEqual(substr_count($text, $this->nodeTitles[$langcode]), 2 * $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message); } } } diff --git a/core/modules/node/src/Tests/Views/NodeLanguageTest.php b/core/modules/node/src/Tests/Views/NodeLanguageTest.php index b4d9891..ac35bb9 100644 --- a/core/modules/node/src/Tests/Views/NodeLanguageTest.php +++ b/core/modules/node/src/Tests/Views/NodeLanguageTest.php @@ -35,7 +35,7 @@ class NodeLanguageTest extends NodeTestBase { * * @var array */ - public $node_titles = array(); + public $nodeTitles = array(); /** * {@inheritdoc} @@ -61,7 +61,7 @@ protected function setUp() { // Set up node titles. They should not include the words "French", // "English", or "Spanish", as there is a language field in the view // that prints out those words. - $this->node_titles = array( + $this->nodeTitles = array( 'es' => array( 'Primero nodo es', 'Segundo nodo es', @@ -77,11 +77,11 @@ protected function setUp() { ); // Create nodes with translations. - foreach ($this->node_titles['es'] as $index => $title) { + foreach ($this->nodeTitles['es'] as $index => $title) { $node = $this->drupalCreateNode(array('title' => $title, 'langcode' => 'es', 'type' => 'page', 'promote' => 1)); foreach (array('en', 'fr') as $langcode) { - if (isset($this->node_titles[$langcode][$index])) { - $translation = $node->addTranslation($langcode, array('title' => $this->node_titles[$langcode][$index])); + if (isset($this->nodeTitles[$langcode][$index])) { + $translation = $node->addTranslation($langcode, array('title' => $this->nodeTitles[$langcode][$index])); $translation->body->value = $this->randomMachineName(32); } } @@ -102,7 +102,7 @@ public function testLanguages() { $message = 'French/Spanish page'; // Test that the correct nodes are shown. - foreach ($this->node_titles as $langcode => $list) { + foreach ($this->nodeTitles as $langcode => $list) { foreach ($list as $title) { if ($langcode == 'en') { $this->assertNoText($title, $title . ' does not appear on ' . $message); @@ -123,10 +123,10 @@ public function testLanguages() { $page = $this->getTextContent(); $pos_es_max = 0; $pos_fr_min = 10000; - foreach ($this->node_titles['es'] as $title) { + foreach ($this->nodeTitles['es'] as $title) { $pos_es_max = max($pos_es_max, strpos($page, $title)); } - foreach ($this->node_titles['fr'] as $title) { + foreach ($this->nodeTitles['fr'] as $title) { $pos_fr_min = min($pos_fr_min, strpos($page, $title)); } $this->assertTrue($pos_es_max < $pos_fr_min, 'Spanish translations appear before French on ' . $message); @@ -141,12 +141,12 @@ public function testLanguages() { // Test the front page view filter. Only node titles in the current language // should be displayed on the front page by default. - foreach ($this->node_titles as $langcode => $titles) { + foreach ($this->nodeTitles as $langcode => $titles) { $this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node'); foreach ($titles as $title) { $this->assertText($title); } - foreach ($this->node_titles as $control_langcode => $control_titles) { + foreach ($this->nodeTitles as $control_langcode => $control_titles) { if ($langcode != $control_langcode) { foreach ($control_titles as $title) { $this->assertNoText($title); @@ -157,18 +157,18 @@ public function testLanguages() { // Test the node admin view filter. By default all translations should show. $this->drupalGet('admin/content'); - foreach ($this->node_titles as $titles) { + foreach ($this->nodeTitles as $titles) { foreach ($titles as $title) { $this->assertText($title); } } // When filtered, only the specific languages should show. - foreach ($this->node_titles as $langcode => $titles) { + foreach ($this->nodeTitles as $langcode => $titles) { $this->drupalGet('admin/content', array('query' => array('langcode' => $langcode))); foreach ($titles as $title) { $this->assertText($title); } - foreach ($this->node_titles as $control_langcode => $control_titles) { + foreach ($this->nodeTitles as $control_langcode => $control_titles) { if ($langcode != $control_langcode) { foreach ($control_titles as $title) { $this->assertNoText($title); @@ -183,9 +183,9 @@ public function testLanguages() { $config = \Drupal::config('views.view.frontpage'); $config->set('display.default.display_options.filters.langcode.value', array(PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT => PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT)); $config->save(); - foreach ($this->node_titles as $langcode => $titles) { + foreach ($this->nodeTitles as $langcode => $titles) { $this->drupalGet(($langcode == 'en' ? '' : "$langcode/") . 'node'); - foreach ($this->node_titles as $control_langcode => $control_titles) { + foreach ($this->nodeTitles as $control_langcode => $control_titles) { foreach ($control_titles as $title) { if ($control_langcode == 'en') { $this->assertText($title, 'English title is shown when filtering is site default'); @@ -213,7 +213,7 @@ public function testLanguages() { // With a fixed language selected, there is no language-based URL. $this->drupalGet('node'); - foreach ($this->node_titles as $control_langcode => $control_titles) { + foreach ($this->nodeTitles as $control_langcode => $control_titles) { foreach ($control_titles as $title) { if ($control_langcode == 'es') { $this->assertText($title, 'Spanish title is shown when filtering is fixed UI language');