add_filter function concatenate string and locate_template function

Running output when concatenating a string does not work in PHP. If you try this:

function goes() {
    echo 'goes';
}

$string = 'My string ' . goes() . 'here';

echo $string;

Then the output would be:

goesMy string here

The same thing applies for include or require when the files being included produce output.

If you want to concatenate the output of a PHP file into a string, you’re going to need to include it and capture the output with output buffering. If the file’s in your theme then you should include it with get_template_part(), rather than locate_template().

add_filter('wp_nav_menu_items', 'add_css_switcher', 10, 2);
function add_css_switcher($items, $args){
    ob_start();

    get_template_part( 'inc/css-switcher' );

    $css_switcher = ob_get_clean();

    $items .= '<li class="css-toggler hidden">' . $css_switcher . '</li>';

    return $items;
}

But this is a frankly silly way to do this. If you want to return a value that’s meant to be concatenated into a string then a template file is not a smart way to go about it. You should be putting the functionality of css-switcher.php into a function and changing it to return its output, rather than echoing it. Then you can use that function in your code:

function css_switcher() {
    // Return menu item code here.
}

add_filter('wp_nav_menu_items', 'add_css_switcher', 10, 2);
function add_css_switcher($items, $args){    
    $items .= '<li class="css-toggler hidden">' . css_switcher() . '</li>';

    return $items;
}