I'm looking for a way to create a new item that can be added to a menu.
Here are the details of my problem: I use WPML. WPML have that nice feature that you can add the switcher to a menu, automatically. It adds it at the end of the menu, no control on that.
Thing is, I want my language switcher to be element 4 out of 6. That feature to automatically add the element at the end doesn't fit my needs.
So I want to create a new element that can be used in apparence->menu to put my language switcher exactly at the spot I want it.
Is there any way to do that?
TLDR: I want to be able to push custom HTML/PHP code in a menu element (Apparence->Menu). Any functions to do so?
Creating menu –add_action('admin_menu', 'custom_menu'); add_action('admin_menu', 'custom_menu'); In above line of code, first parameter is the hook we discuss about, Second parameter is name of callback function. In callback function you have to write what you want to alter in admin menu.
In order to create a WordPress menu dropdown in the 2022 WordPress theme, you will need to click on the specific menu item for which you want to create a dropdown. You can add the submenu using the 'submenu' block icon.
To do this go to Appearance >Menus and start creating a new menu. Give the menu the title “Secondary Menu”, select “My Custom Menu” for a location and then hit the “Create Menu” button. Finally add some items to the menu (for example Menu item 1, Menu item 2, Menu item 3) and then save the menu.
From wp-includes/nav-menu-template.php
, in Walker_Nav_Menu::start_el
:
/**
* Filter a menu item's starting output.
*
* The menu item's starting output only includes `$args->before`, the opening `<a>`,
* the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
* no filter for modifying the opening and closing `<li>` for a menu item.
*
* @since 3.0.0
*
* @param string $item_output The menu item's starting HTML output.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args An array of {@see wp_nav_menu()} arguments.
*/
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
Which means you can append to individual nav menu item HTML contents (right before the last li
tag) using that filter. $item_output
contains the HTML generated for the item so far. Example:
<?php
add_filter('walker_nav_menu_start_el', function ($item_output) {
return $item_output . '<span>hello world</span>';
});
That would append <span>hello world</span>
to each nav menu item HTML. A closing li
tag will be appended after this filter. You can use the 4th argument ($args
) to validate the currently rendering navigation menu.
All right, I have temporary solution.
These are steps:
\wp-content\plugins\sitepress-multilingual-cms\inc\language-switcher.php
function wp_nav_menu_items_filter($items, $args){
Add this right after first {
:
$tempitems = $items;
$tempitemsexplode = explode("\n", $tempitems);
$items = "";
$id = 2; //This is where widget will be located: example, if you want it to be at place 4, write 5
Right before if ( $abs_menu_id == $settings_menu_id || false === $abs_menu_id ) {
add this:
$id = 2;
for ($i = 0; $i < $id; $i++){
$items .= $tempitemsexplode[$i];
}
for($i = 0; $i < count($tempitemsexplode); $i++){
If ($i == $id){
Go to bottom of function and before:}
return $items;
Add: }}
Now, before return $items;
Add:
for ($i = $id; $i < count($tempitemsexplode); $i++){
$items .= $tempitemsexplode[$i];
}
If you get stuck here is how that whole function looks for me:
function wp_nav_menu_items_filter($items, $args){
$tempitems = $items;
$tempitemsexplode = explode("\n", $tempitems);
$items = "";
global $sitepress_settings, $sitepress;
$current_language = $sitepress->get_current_language();
$default_language = $sitepress->get_default_language();
// menu can be passed as integer or object
if(isset($args->menu->term_id)) $args->menu = $args->menu->term_id;
$abs_menu_id = icl_object_id($args->menu, 'nav_menu', false, $default_language );
$settings_menu_id = icl_object_id( $sitepress_settings[ 'menu_for_ls' ], 'nav_menu', false, $default_language );
$id = 2;
for ($i = 0; $i < $id; $i++){
$items .= $tempitemsexplode[$i];
}
for($i = 0; $i < count($tempitemsexplode); $i++){
If ($i == $id){
if ( $abs_menu_id == $settings_menu_id || false === $abs_menu_id ) {
$languages = $sitepress->get_ls_languages();
$items .= '<li class="menu-item menu-item-language menu-item-language-current">';
if(isset($args->before)){
$items .= $args->before;
}
$items .= '<a href="#" onclick="return false">';
if(isset($args->link_before)){
$items .= $args->link_before;
}
$language_name = '';
if ( $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= $languages[ $current_language ][ 'native_name' ];
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= ' (';
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] ) {
$language_name .= $languages[ $current_language ][ 'translated_name' ];
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= ')';
}
$alt_title_lang = esc_attr($language_name);
if( $sitepress_settings['icl_lso_flags'] ){
$items .= '<img class="iclflag" src="' . $languages[ $current_language ][ 'country_flag_url' ] . '" width="18" height="12" alt="' . $alt_title_lang . '" title="' . esc_attr( $language_name ) . '" />';
}
$items .= $language_name;
if(isset($args->link_after)){
$items .= $args->link_after;
}
$items .= '</a>';
if(isset($args->after)){
$items .= $args->after;
}
unset($languages[ $current_language ]);
$sub_items = false;
$menu_is_vertical = !isset($sitepress_settings['icl_lang_sel_orientation']) || $sitepress_settings['icl_lang_sel_orientation'] == 'vertical';
if(!empty($languages)){
foreach($languages as $lang){
$sub_items .= '<li class="menu-item menu-item-language menu-item-language-current">';
$sub_items .= '<a href="'.$lang['url'].'">';
$language_name = '';
if ( $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= $lang[ 'native_name' ];
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= ' (';
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] ) {
$language_name .= $lang[ 'translated_name' ];
}
if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
$language_name .= ')';
}
$alt_title_lang = esc_attr($language_name);
if( $sitepress_settings['icl_lso_flags'] ){
$sub_items .= '<img class="iclflag" src="'.$lang['country_flag_url'].'" width="18" height="12" alt="'.$alt_title_lang.'" title="' . $alt_title_lang . '" />';
}
$sub_items .= $language_name;
$sub_items .= '</a>';
$sub_items .= '</li>';
}
if( $sub_items && $menu_is_vertical ) {
$sub_items = '<ul class="sub-menu submenu-languages">' . $sub_items . '</ul>';
}
}
if( $menu_is_vertical ) {
$items .= $sub_items;
$items .= '</li>';
} else {
$items .= '</li>';
$items .= $sub_items;
}
}
}
}
for ($i = $id; $i < count($tempitemsexplode); $i++){
$items .= $tempitemsexplode[$i];
}
return $items;
}
I will try to make it easier to change where you want to place widget.
Comment if you have problems. Good luck!
Edit: Explanation what this modified function does.
This function is used to add language switcher to menu.
When this function is called, we have $items
string containing all menu items.
I transferred all menu items from $items
to $tempitems
and set $items
to empty string.
Why? Because now we can insert widget as first menu item or between some menu items.
Then we explode that $tempitems
string so we could use another order.
When you now specify $id
this becomes our offset.
And now in first loop, with help of $id
, we add some temp items to empty $items
string, and then language widget and at the end remaining menu items.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With