diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php index b9fe6e3..882dc28 100644 --- a/core/modules/user/lib/Drupal/user/AccountFormController.php +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php @@ -2,13 +2,15 @@ /** * @file - * Definition of Drupal\user\AccountFormController. + * Contains \Drupal\user\AccountFormController. */ namespace Drupal\user; use Drupal\Core\Entity\ContentEntityFormController; use Drupal\Core\Language\Language; +use Drupal\Core\Language\LanguageManager; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Form controller for the user account forms. @@ -16,6 +18,32 @@ abstract class AccountFormController extends ContentEntityFormController { /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManager + */ + protected $languageManager; + + /** + * Constructs a new EntityFormController object. + * + * @param \Drupal\Core\Language\LanguageManager $language_manager + * The language manager. + */ + public function __construct(LanguageManager $language_manager) { + $this->languageManager = $language_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('language_manager') + ); + } + + /** * {@inheritdoc} */ public function form(array $form, array &$form_state) { @@ -185,7 +213,7 @@ public function form(array $form, array &$form_state) { include_once DRUPAL_ROOT . '/core/includes/language.inc'; $interface_language_is_default = language_negotiation_method_get_first(Language::TYPE_INTERFACE) != LANGUAGE_NEGOTIATION_SELECTED; $form['language'] = array( - '#type' => language_multilingual() ? 'details' : 'container', + '#type' => $this->languageManager->isMultilingual() ? 'details' : 'container', '#title' => $this->t('Language settings'), // Display language selector when either creating a user on the admin // interface or editing a user account. @@ -200,14 +228,24 @@ public function form(array $form, array &$form_state) { '#description' => $interface_language_is_default ? $this->t("This account's preferred language for e-mails and site presentation.") : $this->t("This account's preferred language for e-mails."), ); + // Only show the account setting for Administration pages language to users + // if one of the detection and selection methods uses it. + $show_admin_language = FALSE; + if ($this->moduleHandler->moduleExists('language') && $this->languageManager->isMultilingual()) { + foreach (language_types_info() as $type_key => $language_type) { + $negotiation_settings = variable_get("language_negotiation_{$type_key}", array()); + if ($show_admin_language = isset($negotiation_settings[LANGUAGE_NEGOTIATION_USER_ADMIN])) { + break; + } + } + } $form['language']['preferred_admin_langcode'] = array( '#type' => 'language_select', '#title' => $this->t('Administration pages language'), '#languages' => Language::STATE_CONFIGURABLE, '#default_value' => $user_preferred_admin_langcode, - '#access' => user_access('access administration pages', $account), + '#access' => $show_admin_language && user_access('access administration pages', $account), ); - // User entities contain both a langcode property (for identifying the // language of the entity data) and a preferred_langcode property (see // above). Rather than provide a UI forcing the user to choose both diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAdminLanguageTest.php b/core/modules/user/lib/Drupal/user/Tests/UserAdminLanguageTest.php new file mode 100644 index 0000000..7737624 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Tests/UserAdminLanguageTest.php @@ -0,0 +1,145 @@ + 'User administration pages language settings', + 'description' => "Tests user's ability to change their administration pages language.", + 'group' => 'User', + ); + } + + public function setUp() { + parent::setUp(); + // User to add and remove language. + $this->adminUser = $this->drupalCreateUser(array('administer languages', 'access administration pages')); + // User to check non-admin access. + $this->regularUser = $this->drupalCreateUser(); + } + + /** + * Tests that admin language is not configurable in single language sites. + */ + function testUserAdminLanguageConfigurationNotAvailableWithOnlyOneLanguage() { + $this->drupalLogin($this->adminUser); + $this->setLanguageNegotiation(); + $path = 'user/' . $this->adminUser->id() . '/edit'; + $this->drupalGet($path); + // Ensure administration pages language settings widget is not available. + $this->assertNoFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector not available.'); + } + + /** + * Tests that admin language negotiation is configurable only if enabled. + */ + function testUserAdminLanguageConfigurationAvailableWithAdminLanguageNegotiation() { + $this->drupalLogin($this->adminUser); + $this->addCustomLanguage(); + $path = 'user/' . $this->adminUser->id() . '/edit'; + + // Checks with user administration pages language negotiation disabled. + $this->drupalGet($path); + // Ensure administration pages language settings widget is not available. + $this->assertNoFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector not available.'); + + // Checks with user administration pages language negotiation enabled. + $this->setLanguageNegotiation(); + $this->drupalGet($path); + // Ensure administration pages language settings widget is available. + $this->assertFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector is available.'); + } + + /** + * Tests that the admin language is configurable only for administrators. + * + * If a user has the permission "access administration pages", they should + * be able to see the setting to pick the language they want those pages in. + * + * If a user does not have that permission, it would confusing for them to + * have a setting for pages they cannot access, so they should not be able to + * set a language for those pages. + */ + function testUserAdminLanguageConfigurationAvailableIfAdminLanguageNegotiationIsEnabled() { + $this->drupalLogin($this->adminUser); + // Adds a new language, because with only one language, setting won't show. + $this->addCustomLanguage(); + $this->setLanguageNegotiation(); + $path = 'user/' . $this->adminUser->id() . '/edit'; + $this->drupalGet($path); + // Ensure administration pages language setting is visible for admin. + $this->assertFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector available for admins.'); + + // Ensure administration pages language setting is hidden for non-admins. + $this->drupalLogin($this->regularUser); + $path = 'user/' . $this->regularUser->id() . '/edit'; + $this->drupalGet($path); + $this->assertNoFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector not available for regular user.'); + } + + /** + * Sets the User interface negotiation detection method. + * + * Enables the "Account preference for administration pages" language + * detection method for the User interface language negotiation type. + */ + function setLanguageNegotiation() { + $edit = array( + 'language_interface[enabled][language-user-admin]' => TRUE, + 'language_interface[enabled][language-url]' => TRUE, + 'language_interface[weight][language-user-admin]' => -8, + 'language_interface[weight][language-url]' => -10, + ); + $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); + } + + /** + * Helper method for adding a custom language. + */ + function addCustomLanguage() { + $langcode = 'xx'; + // The English name for the language. + $name = $this->randomName(16); + $edit = array( + 'predefined_langcode' => 'custom', + 'langcode' => $langcode, + 'name' => $name, + 'direction' => '0', + ); + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); + } + +}