diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php index 4eeab27..e8c461e 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuFormController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php @@ -8,6 +8,7 @@ namespace Drupal\menu; use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Language\Language; /** * Base form controller for menu edit forms. @@ -18,7 +19,6 @@ class MenuFormController extends EntityFormController { * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state) { - $form = parent::form($form, $form_state); $menu = $this->entity; $system_menus = menu_list_system_menus(); $form_state['menu'] = &$menu; @@ -35,6 +35,7 @@ public function form(array $form, array &$form_state) { '#default_value' => $menu->id(), '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI, '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'), + '#field_prefix' => 'menu-', '#machine_name' => array( 'exists' => 'menu_edit_menu_name_exists', 'source' => array('label'), @@ -63,7 +64,30 @@ public function form(array $form, array &$form_state) { $form['links'] = menu_overview_form($form['links'], $form_state); } - return $form; + $form['langcode'] = array( + '#type' => 'language_select', + '#title' => t('Menu language'), + '#languages' => Language::STATE_ALL, + '#default_value' => $menu->langcode, + ); + // Unlike the menu langcode, the default language configuration for menu + // links only works with language module installed. + if (\Drupal::moduleHandler()->moduleExists('language')) { + $form['default_menu_links_language'] = array( + '#type' => 'details', + '#title' => t('Menu links language'), + ); + $form['default_menu_links_language']['default_language'] = array( + '#type' => 'language_configuration', + '#entity_information' => array( + 'entity_type' => 'menu_link', + 'bundle' => $menu->id(), + ), + '#default_value' => language_get_default_configuration('menu_link', $menu->id()), + ); + } + + return parent::form($form, $form_state); } /** @@ -76,10 +100,35 @@ protected function actions(array $form, array &$form_state) { $system_menus = menu_list_system_menus(); $actions['delete']['#access'] = !$menu->isNew() && !isset($system_menus[$menu->id()]); + // Add the language configuration submit handler. This is needed because the + // submit button has custom submit handlers. + if (\Drupal::moduleHandler()->moduleExists('language')) { + array_unshift($actions['submit']['#submit'],'language_configuration_element_submit'); + array_unshift($actions['submit']['#submit'], array($this, 'languageConfigurationSubmit')); + } + // We cannot leverage the regular submit handler definition because we have + // button-specific ones here. Hence we need to explicitly set it for the + // submit action, otherwise it would be ignored. + if (\Drupal::moduleHandler()->moduleExists('translation_entity')) { + array_unshift($actions['submit']['#submit'], 'translation_entity_language_configuration_element_submit'); + } return $actions; } /** + * Submit handler to update the bundle for the default language configuration. + */ + public function languageConfigurationSubmit(array &$form, array &$form_state) { + // Since the machine name is not known yet, and it can be changed anytime, + // we have to also update the bundle property for the default language + // configuration in order to have the correct bundle value. + $form_state['language']['default_language']['bundle'] = $form_state['values']['id']; + // Clear cache so new menus (bundles) show on the language settings admin + // page. + entity_info_cache_clear(); + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { @@ -90,11 +139,6 @@ public function save(array $form, array &$form_state) { menu_overview_form_submit($form, $form_state); } - if ($menu->isNew()) { - // Add 'menu-' to the menu name to help avoid name-space conflicts. - $menu->set('id', 'menu-' . $menu->id()); - } - $status = $menu->save(); $uri = $menu->uri(); diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuLanguageTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuLanguageTest.php new file mode 100644 index 0000000..3c3b0fb --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuLanguageTest.php @@ -0,0 +1,157 @@ + 'Menu language', + 'description' => 'Create menu and menu links in non-English language, and edit language settings.', + 'group' => 'Menu' + ); + } + + function setUp() { + parent::setUp(); + + // Create user. + $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer menu')); + $this->drupalLogin($this->admin_user); + + // Add some custom languages. + foreach (array('aa', 'bb', 'cc') as $language_code) { + $language = new Language(array( + 'langcode' => $language_code, + 'name' => $this->randomName(), + )); + language_save($language); + } + } + + /** + * Tests menu language settings and the defaults for menu link items. + */ + function testMenuLanguage() { + // Create a test menu to decouple from other built in menus. + // Machine name has to be lowercase. + $menu_name = drupal_strtolower($this->randomName(16)); + $label = $this->randomName(16); + $edit = array( + 'id' => $menu_name, + 'description' => '', + 'label' => $label, + 'langcode' => 'aa', + 'default_language[langcode]' => 'bb', + 'default_language[language_show]' => TRUE, + ); + $this->drupalPost('admin/structure/menu/add', $edit, t('Save')); + // Check menu language and item language configuration. + $this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The menu language was correctly selected.'); + $this->assertOptionSelected('edit-default-language-langcode', $edit['default_language[langcode]'], 'The menu link default language was correctly selected.'); + $this->assertFieldChecked('edit-default-language-language-show'); + + // Check that the language settings were saved. + $language_settings = language_get_default_configuration('menu_link', $menu_name); + $this->assertEqual($language_settings['langcode'], 'bb'); + $this->assertEqual($language_settings['language_show'], TRUE); + + // Test menu link language. + $sample_link_path = ''; + + // Add a menu link. + $title = $this->randomName(16); + $edit = array( + 'link_title' => $title, + 'link_path' => $sample_link_path, + ); + $this->drupalPost('admin/structure/menu/manage/' . $menu_name . '/add', $edit, t('Save')); + // Check the link was added with the correct menu link default language. + $menu_links = entity_load_multiple_by_properties('menu_link', array('link_title' => $title)); + $menu_link = reset($menu_links); + $this->assertTrue($menu_link, 'Menu link was found in database.'); + $this->assertMenuLink($menu_link->id(), array('menu_name' => $menu_name, 'link_path' => $sample_link_path, 'langcode' => 'bb')); + + // Edit menu link default, changing it to cc. + $edit = array( + 'default_language[langcode]' => 'cc', + ); + $this->drupalPost('admin/structure/menu/manage/' . $menu_name, $edit, t('Save')); + + // Check cc is the menu link default. + $this->assertOptionSelected('edit-default-language-langcode', $edit['default_language[langcode]'], 'The menu link default language was correctly selected.'); + + // Add a menu link. + $title = $this->randomName(16); + $edit = array( + 'link_title' => $title, + 'link_path' => $sample_link_path, + ); + $this->drupalPost('admin/structure/menu/manage/' . $menu_name . '/add', $edit, t('Save')); + // Check the link was added with the correct new menu link default language. + $menu_links = entity_load_multiple_by_properties('menu_link', array('link_title' => $title)); + $menu_link = reset($menu_links); + $this->assertTrue($menu_link, 'Menu link was found in database.'); + $this->assertMenuLink($menu_link->id(), array('menu_name' => $menu_name, 'link_path' => $sample_link_path, 'langcode' => 'cc')); + + // Edit menu to hide the language select on menu link item add. + $edit = array( + 'default_language[language_show]' => FALSE, + ); + $this->drupalPost('admin/structure/menu/manage/' . $menu_name, $edit, t('Save')); + $this->assertNoFieldChecked('edit-default-language-language-show'); + + // Check that the language settings were saved. + $language_settings = language_get_default_configuration('menu_link', $menu_name); + $this->assertEqual($language_settings['langcode'], 'cc'); + $this->assertEqual($language_settings['language_show'], FALSE); + + // Check that the language selector is not available on menu link add page. + $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/add'); + $this->assertNoField('edit-langcode', 'The language selector field was hidden the page'); + } + + /** + * Gets a menu item from the database and compare it to the specified array. + * + * @param int $mlid + * Menu item id. + * @param array $expected_item + * Array containing properties to verify. + * + * @see \Drupal\menu\Tests\MenuTest::assertMenuLink() + */ + function assertMenuLink($mlid, array $expected_item) { + // Retrieve menu link. + $item = entity_load('menu_link', $mlid); + $options = $item->options; + if (!empty($options['query'])) { + $item['link_path'] .= '?' . \Drupal::urlGenerator()->httpBuildQuery($options['query']); + } + if (!empty($options['fragment'])) { + $item['link_path'] .= '#' . $options['fragment']; + } + foreach ($expected_item as $key => $value) { + $this->assertEqual($item[$key], $value, format_string('Parameter %key had expected value.', array('%key' => $key))); + } + } + +} diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index 46e6825..cf15031 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -158,7 +158,6 @@ function addCustomMenu() { $this->assertText($label, 'Menu created'); // Enable the custom menu block. - $menu_name = 'menu-' . $menu_name; // Drupal prepends the name with 'menu-'. // Confirm that the custom menu block is available. $this->drupalGet('admin/structure/block/list/block_plugin_ui:' . config('system.theme')->get('default') . '/add'); $this->assertText($label); @@ -395,7 +394,7 @@ function addMenuLink($plid = 0, $link = '', $menu_name = 'tools', $expand $menu_links = entity_load_multiple_by_properties('menu_link', array('link_title' => $title)); $menu_link = reset($menu_links); - $this->assertTrue('Menu link was found in database.'); + $this->assertTrue($menu_link, 'Menu link was found in database.'); $this->assertMenuLink($menu_link->id(), array('menu_name' => $menu_name, 'link_path' => $link, 'has_children' => 0, 'plid' => $plid)); return $menu_link; @@ -591,7 +590,7 @@ function assertMenuLink($mlid, array $expected_item) { $item = entity_load('menu_link', $mlid); $options = $item->options; if (!empty($options['query'])) { - $item['link_path'] .= '?' . drupal_http_build_query($options['query']); + $item['link_path'] .= '?' . \Drupal::urlGenerator()->httpBuildQuery($options['query']); } if (!empty($options['fragment'])) { $item['link_path'] .= '#' . $options['fragment']; diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php index 9aa76d4..ab7969f 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -86,7 +86,7 @@ public function form(array $form, array &$form_state) { // $base_path. $path = $menu_link->link_path; if (isset($menu_link->options['query'])) { - $path .= '?' . drupal_http_build_query($menu_link->options['query']); + $path .= '?' . \Drupal::urlGenerator()->httpBuildQuery($menu_link->options['query']); } if (isset($menu_link->options['fragment'])) { $path .= '#' . $menu_link->options['fragment']; @@ -156,11 +156,36 @@ public function form(array $form, array &$form_state) { '#description' => t('Optional. In the menu, the heavier links will sink and the lighter links will be positioned nearer the top.'), ); + // Get the default langcode and show language select value. + $language_configuration = \Drupal::moduleHandler()->invoke('language', 'get_default_configuration', array('menu_link', $menu_link->bundle())); + + if ($menu_link->isNew()) { + // Adding a new menu link, use the default from language settings config, + // if it is available. + if (!is_null($language_configuration['langcode'])) { + $default_langcode = $language_configuration['langcode']; + } + elseif (\Drupal::moduleHandler()->moduleExists('menu')) { + // If no default for menu links, default to the language of the menu. + $menu = menu_load($menu_link->menu_name); + $default_langcode = $menu->langcode; + } + else { + // We do not know the language of the menu. + $default_langcode = Language::LANGCODE_NOT_SPECIFIED; + } + } + else { + // Editing an already existing menu link, so use it's saved language. + $default_langcode = $menu_link->langcode; + } + $form['langcode'] = array( '#type' => 'language_select', '#title' => t('Language'), '#languages' => Language::STATE_ALL, - '#default_value' => $menu_link->langcode, + '#default_value' => $default_langcode, + '#access' => !is_null($language_configuration['language_show']) && $language_configuration['language_show'], ); return parent::form($form, $form_state, $menu_link); diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php index 5af23d7..484f5d0 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php @@ -32,6 +32,7 @@ * static_cache = FALSE, * base_table = "menu_links", * uri_callback = "menu_link_uri", + * translatable = TRUE, * entity_keys = { * "id" = "mlid", * "label" = "link_title",