diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index a7c6663..b8054a7 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -11,84 +11,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** - * User interface for the language overview screen. - */ -function language_admin_overview_form($form, &$form_state) { - drupal_static_reset('language_list'); - $languages = language_list(); - $default = language_default(); - - $form['languages'] = array( - '#languages' => $languages, - '#language_default' => $default, - '#type' => 'table', - '#header' => array( - t('Name'), - t('Weight'), - t('Operations'), - ), - '#tabledrag' => array( - array('order', 'sibling', 'language-order-weight'), - ), - ); - - foreach ($languages as $langcode => $language) { - $form['languages'][$langcode]['#attributes']['class'][] = 'draggable'; - $form['languages'][$langcode]['name'] = array( - '#markup' => check_plain($language->name), - ); - $form['languages'][$langcode]['weight'] = array( - '#type' => 'weight', - '#title' => t('Weight for @title', array('@title' => $language->name)), - '#title_display' => 'invisible', - '#default_value' => $language->weight, - '#attributes' => array( - 'class' => array('language-order-weight'), - ), - '#delta' => 30, - ); - $links = array(); - $links['edit'] = array( - 'title' => t('edit'), - 'href' => 'admin/config/regional/language/edit/' . $langcode, - ); - if ($langcode != $default->id) { - $links['delete'] = array( - 'title' => t('delete'), - 'href' => 'admin/config/regional/language/delete/' . $langcode, - ); - } - $form['languages'][$langcode]['operations'] = array( - '#type' => 'operations', - '#links' => $links, - '#weight' => 100, - ); - } - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save configuration'), - ); - - return $form; -} - -/** - * Process language overview form submissions, updating existing languages. - */ -function language_admin_overview_form_submit($form, &$form_state) { - $languages = language_list(); - - foreach ($languages as $langcode => $language) { - $language->weight = $form_state['values']['languages'][$langcode]['weight']; - language_save($language); - } - - drupal_set_message(t('Configuration saved.')); -} - -/** * User interface for the language addition screen. */ function language_admin_add_form($form, &$form_state) { diff --git a/core/modules/language/language.module b/core/modules/language/language.module index bdbd15c..496ae60 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -70,10 +70,7 @@ function language_menu() { $items['admin/config/regional/language'] = array( 'title' => 'Languages', 'description' => 'Configure languages for content and the user interface.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('language_admin_overview_form'), - 'access arguments' => array('administer languages'), - 'file' => 'language.admin.inc', + 'route_name' => 'language_admin_overview', 'weight' => -10, ); $items['admin/config/regional/language/list'] = array( @@ -88,20 +85,20 @@ function language_menu() { 'type' => MENU_LOCAL_ACTION, 'file' => 'language.admin.inc', ); - $items['admin/config/regional/language/edit/%language'] = array( + $items['admin/config/regional/language/%language/edit'] = array( 'title' => 'Edit language', 'page callback' => 'drupal_get_form', - 'page arguments' => array('language_admin_edit_form', 5), + 'page arguments' => array('language_admin_edit_form', 4), 'access callback' => 'language_access_language_edit_or_delete', - 'access arguments' => array(5), + 'access arguments' => array(4), 'file' => 'language.admin.inc', ); - $items['admin/config/regional/language/delete/%language'] = array( + $items['admin/config/regional/language/%language/delete'] = array( 'title' => 'Confirm delete', 'page callback' => 'drupal_get_form', - 'page arguments' => array('language_admin_delete_form', 5), + 'page arguments' => array('language_admin_delete_form', 4), 'access callback' => 'language_access_language_edit_or_delete', - 'access arguments' => array(5), + 'access arguments' => array(4), 'file' => 'language.admin.inc', ); diff --git a/core/modules/language/language.routing.yml b/core/modules/language/language.routing.yml index 4a2fc8c..e75e1ce 100644 --- a/core/modules/language/language.routing.yml +++ b/core/modules/language/language.routing.yml @@ -18,3 +18,10 @@ language_negotiation_selected: _form: 'Drupal\language\Form\NegotiationSelectedForm' requirements: _permission: 'administer languages' + +language_admin_overview: + pattern: '/admin/config/regional/language' + defaults: + _entity_list: 'language_entity' + requirements: + _permission: 'administer languages' diff --git a/core/modules/language/lib/Drupal/language/LanguageListController.php b/core/modules/language/lib/Drupal/language/LanguageListController.php new file mode 100644 index 0000000..81239b2 --- /dev/null +++ b/core/modules/language/lib/Drupal/language/LanguageListController.php @@ -0,0 +1,157 @@ +storage->loadByProperties(array('locked' => '0')); + uasort($entities, array($this->entityInfo['class'], 'sort')); + return $entities; + } + + /** + * {@inheritdoc} + */ + public function render() { + return drupal_get_form($this); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'language_admin_overview_form'; + } + + /** + * {@inheritdoc} + */ + public function getOperations(EntityInterface $entity) { + $operations = parent::getOperations($entity); + // For configuration entities edit path is the MENU_DEFAULT_LOCAL_TASK but + // for languages we make an exception. + $operations['edit']['href'] = $operations['edit']['href'] . '/edit'; + $default = language_default(); + + if ($entity->id() == $default->id) { + unset($operations['delete']); + } + + return $operations; + } + + /** + * {@inheritdoc} + */ + public function buildHeader() { + $row = parent::buildHeader(); + $row['label'] = t('Name'); + unset($row['id']); + $row['weight'] = t('Weight'); + return $row; + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity) { + $row = parent::buildRow($entity); + unset($row['id']); + $row['#attributes']['class'][] = 'draggable'; + + $row['label'] = array( + '#markup' => String::checkPlain($entity->get('label')), + ); + + $row['#weight'] = $entity->get('weight'); + // Add weight column. + $row['weight'] = array( + '#type' => 'weight', + '#title' => t('Weight for @title', array('@title' => $entity->label())), + '#title_display' => 'invisible', + '#default_value' => $entity->get('weight'), + '#attributes' => array('class' => array('weight')), + '#delta' => 30, + ); + + return $row; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $languages = $this->load(); + + $form['languages'] = array( + '#languages' => $languages, + '#type' => 'table', + '#header' => $this->buildHeader(), + '#empty' => t('There are no languages'), + '#tabledrag' => array( + array('order', 'sibling', 'language-order-weight'), + ), + ); + + foreach ($languages as $entity) { + $form['languages'][$entity->id()] = $this->buildRow($entity); + } + + $form['actions']['#type'] = 'actions'; + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save configuration'), + '#button_type' => 'primary', + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + // No validation. + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $languages = $form_state['values']['languages']; + + $entities = $this->load(); + foreach ($languages as $id => $language) { + if (isset($entities[$id]) && $language['weight'] != $entities[$id]->get('weight')) { + // Update changed weight. + $entities[$id]->set('weight', $language['weight']); + $entities[$id]->save(); + } + } + + // Kill the static cache in language_list(). + drupal_static_reset('language_list'); + + // Update weight of locked system languages. + language_update_locked_weights(); + + drupal_set_message(t('Configuration saved.')); + } + +} diff --git a/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php index 4172e96..a3d28f2 100644 --- a/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Annotation\Translation; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Session\AccountInterface; use Drupal\language\LanguageInterface; /** @@ -20,7 +21,8 @@ * label = @Translation("Language"), * module = "language", * controllers = { - * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" + * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", + * "list" = "Drupal\language\LanguageListController", * }, * config_prefix = "language.entity", * entity_keys = { @@ -76,4 +78,24 @@ class Language extends ConfigEntityBase implements LanguageInterface { */ public $locked = FALSE; + /** + * {@inheritdoc} + */ + public function uri() { + return array( + 'path' => 'admin/config/regional/language/' . $this->id(), + 'options' => array( + 'entity_type' => $this->entityType, + 'entity' => $this, + ), + ); + } + + /** + * {@inheritdoc} + */ + public function access($operation = 'view', AccountInterface $account = NULL) { + return (user_access('administer languages')); + } + } diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php index fa718da..8d73aa8 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php @@ -75,19 +75,19 @@ function testLanguageList() { $this->assertEqual($this->getUrl(), url($path, array('absolute' => TRUE)), 'Correct page redirection.'); // Ensure we can't delete the default language. - $this->drupalGet('admin/config/regional/language/delete/' . $langcode); + $this->drupalGet('admin/config/regional/language/' . $langcode .'/delete'); $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); $this->assertText(t('The default language cannot be deleted.'), 'Failed to delete the default language.'); - // Ensure 'edit' link works. - $this->clickLink(t('edit')); + // Ensure 'Edit' link works. + $this->clickLink(t('Edit')); $this->assertTitle(t('Edit language | Drupal'), 'Page title is "Edit language".'); // Edit a language. $name = $this->randomName(16); $edit = array( 'name' => $name, ); - $this->drupalPost('admin/config/regional/language/edit/' . $langcode, $edit, t('Save language')); + $this->drupalPost('admin/config/regional/language/' . $langcode . '/edit', $edit, t('Save language')); $this->assertRaw($name, 'The language has been updated.'); $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); @@ -98,30 +98,30 @@ function testLanguageList() { $this->drupalPost($path, $edit, t('Save configuration')); // Ensure 'delete' link works. $this->drupalGet('admin/config/regional/language'); - $this->clickLink(t('delete')); - $this->assertText(t('Are you sure you want to delete the language'), '"delete" link is correct.'); + $this->clickLink(t('Delete')); + $this->assertText(t('Are you sure you want to delete the language'), '"Delete" link is correct.'); // Delete a language. - $this->drupalGet('admin/config/regional/language/delete/' . $langcode); + $this->drupalGet('admin/config/regional/language/' . $langcode . '/delete'); // First test the 'cancel' link. $this->clickLink(t('Cancel')); $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); $this->assertRaw($name, 'The language was not deleted.'); // Delete the language for real. This a confirm form, we do not need any // fields changed. - $this->drupalPost('admin/config/regional/language/delete/' . $langcode, array(), t('Delete')); + $this->drupalPost('admin/config/regional/language/' . $langcode . '/delete', 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), 'The test language has been removed.'); $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); // Verify that language is no longer found. - $this->drupalGet('admin/config/regional/language/delete/' . $langcode); + $this->drupalGet('admin/config/regional/language/' . $langcode . '/edit'); $this->assertResponse(404, 'Language no longer found.'); // Make sure the "language_count" variable has been updated correctly. drupal_static_reset('language_list'); $languages = language_list(); $this->assertEqual(variable_get('language_count', 1), count($languages), 'Language count is correct.'); // Delete French. - $this->drupalPost('admin/config/regional/language/delete/fr', array(), t('Delete')); + $this->drupalPost('admin/config/regional/language/fr/delete', array(), t('Delete')); // Get the count of languages. drupal_static_reset('language_list'); $languages = language_list(); @@ -130,7 +130,7 @@ function testLanguageList() { $this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'Disabled language has been removed.'); $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); // Verify that language is no longer found. - $this->drupalGet('admin/config/regional/language/delete/fr'); + $this->drupalGet('admin/config/regional/language/fr/delete'); $this->assertResponse(404, 'Language no longer found.'); // Make sure the "language_count" variable has not changed. $this->assertEqual(variable_get('language_count', 1), count($languages), 'Language count is correct.'); @@ -162,7 +162,7 @@ function testLanguageList() { $this->assertNoOptionSelected('edit-site-default-language', 'en', 'Default language updated.'); $this->assertEqual($this->getUrl(), url($path, array('absolute' => TRUE)), 'Correct page redirection.'); - $this->drupalPost('admin/config/regional/language/delete/en', array(), t('Delete')); + $this->drupalPost('admin/config/regional/language/en/delete', array(), t('Delete')); // We need raw here because %language and %langcode will add HTML. $t_args = array('%language' => 'English', '%langcode' => 'en'); $this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'The English language has been removed.'); diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 8d6ff20..6ea2302 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -761,11 +761,10 @@ function locale_form_language_admin_overview_form_alter(&$form, &$form_state) { '#markup' => t('not applicable'), ); } - // #type = link doesn't work with #weight on table. - // reset and set it back after locale_statistics to get it at the right end. - $operations = $form['languages'][$langcode]['operations']; - unset($form['languages'][$langcode]['operations']); - $form['languages'][$langcode]['operations'] = $operations; + // Ensure that weight is the last column. + $weight = $form['languages'][$langcode]['weight']; + unset($form['languages'][$langcode]['weight']); + $form['languages'][$langcode]['weight'] = $weight; } }