Can not switch the queried post in pre_get_posts hook

Huh. I double-checked. On my local server, this bit of code successfully changes the post:

function test_redirect()
{
        global $wp_query;
        $wp_query->set('page_id', 5); 
}
add_action('pre_get_posts', 'test_redirect');

You’re going to have to do a bit of debugging. On a dev server, var_dump the $wp_query variable a few key places to check that it has what you expect it to.

One alternate solution is to hook into the parse_query action to modify the query earlier.

Another option is hooking into template_redirect later, and then create a brand new wp_query object. This would generally be preferable if you were changing the post to something fundamentally different, instead of just another translation, because it will clear out any other variables that were set by parse_query earlier. It comes with the extra overhead of querying for the post twice. Here’s the general idea:

function redirect_translation()
{
        global $wp_query;
        // Replace wp_query here... query_posts() should work too.
        $wp_query = new WP_Query(array('post_id' => 5));
}
add_action('template_redirect','redirect_translation');

Doing this in pre_get_posts will cause an infinite loop.

EDIT: Looking over your code again, how is mt_handle_translation_redirect being called? I suspect you may not be updating the global $wp_query object, which is why the real query isn’t being modified. Verifying the contents of wp_query a few places (like your template file) would be a good start.

Leave a Comment