WordPress.org

Ready to get started?Download WordPress

Forums

Polylang
[resolved] Theme Menus Links (CPT Pages) shown for all languages (12 posts)

  1. ReactorShop
    Member
    Posted 7 months ago #

    Hi Chouby. I tried the modification you kindly provided to fix the wpsc-product posts being shown for all languages situation:

    if (function_exists('pll_get_post')) // test a Polylang function to avoid ugly fatal error at Polylang upgrade
    	add_action('parse_query', 'pll_wpsc_parse_query');
    
    function pll_wpsc_parse_query($query) {
    	if (is_page( pll_get_post(wpsc_get_the_post_id_by_shortcode( '[productspage]' ) ))) {
    		global $polylang;
    		$polylang->choose_lang->set_lang_query_var($query, $polylang->curlang);
    	}
    }

    It does filter the wpsc-product posts to show only the ones created for the current language, but if I select a different page from the theme's main menu links (e.g. Your Account, Transaction Results, Checkout, Contact), it continues to show wpsc-product posts in the current language as page content after clicking any of the menu links, instead of the expected content. Only if I click "Home", I get to see something different than the wpsc-product posts. Another issue is that while I click a theme menu link that points to a CPT page (products page, checkout, etc.), it shows all the theme's main menu links in all languages, instead of only showing the ones that apply for the current language.

    I tried the following:

    function p4we_wpsc_parse_query($query) {
    		global $polylang;
    		$polylang->choose_lang->set_lang_query_var($query, $polylang->curlang);
    }
    add_action('parse_query', 'p4we_wpsc_parse_query');

    And this allows me to see the expected content after clicking any menu link (Home, CPT pages, etc.). Only the wpsc-products posts created for the current language are shown in the products CPT page, as expected, but now the theme's main menu links are shown in all languages and this even happens when viewing the Home page, as you may see circled in yellow in the following image:

    Main menu links shown for all languages.

    Is there something that you may recommend to fix this situation?

    Thank you, Chouby!

    http://wordpress.org/plugins/polylang/

  2. ReactorShop
    Member
    Posted 7 months ago #

    HI Chouby,

    The $polylang object it's only instantiated at the Front End, so I had to add an "is_admin" check.

    function p4we_wpsc_parse_query($query) {
    	if(!is_admin()) {
    		global $polylang;
    		$polylang->choose_lang->set_lang_query_var($query, $polylang->curlang);
    	}
    }
    add_action('parse_query', 'p4we_wpsc_parse_query');

    I'm still getting the menu entries shown in all languages just like before, but this eliminates an error I had when entering the admin side.

  3. Chouby
    Member
    Plugin Author

    Posted 7 months ago #

    Yes I reproduced the issue with the menu (not the issue with the checkout page though). I added a test to alter only the right query and avoid breaking the Polylang page filter.

    <?php
    /*
    Plugin name: Polylang WP E-Commerce Compatibility
    */
    
    add_action('parse_query', 'pll_wpsc_parse_query');
    
    function pll_wpsc_parse_query($query) {
    	if (is_page( pll_get_post(wpsc_get_the_post_id_by_shortcode( '[productspage]' ) )) && isset($query->query['post_type']) &&  'wpsc-product' == $query->query['post_type']){
    		global $polylang;
    		if (isset($polylang->choose_lang)) // test we are on frontend
    			$polylang->choose_lang->set_lang_query_var($query, $polylang->curlang);
    	}
    }

    NB: the $polylang object exists on both frontend and admin but it is not an instance of the same class so that's true taht it's good to test if we are on frontend or admin.

  4. ReactorShop
    Member
    Posted 7 months ago #

    Hi Chouby,

    I still have the wpsc-products posts from the current language showing every time I click a CPT page, instead of its regular content.

    Please look at the top link in this image.

    "Your account" information should be shown here (same as it was shown in spanish in my previously posted image), instead of those 2 wpsc-products posts.

    EDIT: I just took a second look at the image, and saw that the permalink's redirect query string is missing when I apply your modification which includes the IF condition.

    This is what I had to do to fix URLs in order to avoid losing the redirect query strings that WP e-Commerce uses:

    function p4we_translated_product_url($url = '', $lang_slug = '') {
    	global $wp_rewrite, $wp_query;
    
    	if ('' != $url && '' != $lang_slug && strpos($url, 'sitemap') === false && (in_array ( $wp_query->post->post_type, array (
    			'page',
    			'wpsc-product'
    	) ))) {
    		$translated_page = get_post ( pll_get_post ( $wp_query->post->ID, $lang_slug ) );
    		$draft_or_pending = in_array ( $translated_page->post_status, array (
    				'draft',
    				'pending',
    				'auto-draft'
    		) );
    		if ($translated_page->post_type == 'page') {
    			$url = $wp_rewrite->get_page_permastruct ();
    			if (! empty ( $url ) && ((isset ( $translated_page->post_status ) && ! $draft_or_pending) || $sample)) {
    				if (! $leavename)
    					$url = str_replace ( '%pagename%', get_page_uri ( $translated_page ), $url );
    					// FIXME Only covers ReactorShop's specific Polylang/WP e-Commerce configuration.
    				$url = home_url ( $lang_slug . '/' . $url );
    				$url = user_trailingslashit ( $url, 'page' );
    				if (isset ( $_SERVER ['REDIRECT_QUERY_STRING'] ))
    					$url .= '?' . $_SERVER ['REDIRECT_QUERY_STRING'];
    			} else
    				$url = home_url ( '?page_id=' . $translated_page->ID );
    		} else {
    			$request_uri = $_SERVER ['REQUEST_URI'];
    			if (substr ( $request_uri, 0, 1 ) == '/')
    				$request_uri = substr ( $request_uri, 1, strlen ( $request_uri ) - 1 );
    			$request_uri = untrailingslashit ( $request_uri );
    			$request_parts = explode ( '/', $request_uri );
    			// FIXME Only covers ReactorShop's specific Polylang/WP e-Commerce configuration.
    			$translated_url [0] = $lang_slug;
    			$translated_url [1] = p4we_translated_name_from_name ( $request_parts [1], $lang_slug );
    			if (isset ( $request_parts [2] )) {
    				$term = get_term_by ( 'slug', $request_parts [2], 'wpsc_product_category' );
    				$term = get_term_by ( 'id', pll_get_term ( $term->term_id, $lang_slug ), 'wpsc_product_category' );
    				$translated_url [2] = $term->slug;
    			}
    			if (! (strpos ( $_SERVER ['REQUEST_URI'], p4we_translated_name_from_name ( $translated_page->post_name, $request_parts [0] ) ) === false))
    				$translated_url [3] = p4we_translated_name_from_name ( $translated_page->post_name, $lang_slug );
    			$url = implode ( '/', $translated_url );
    			$url = home_url ( '/' . $url );
    			$url = user_trailingslashit ( $url, 'single' );
    			if (isset ( $_SERVER ['REDIRECT_QUERY_STRING'] ))
    				$url .= '?' . $_SERVER ['REDIRECT_QUERY_STRING'];
    		}
    	}
    	return $url;
    }
    add_filter ( 'pll_translation_url', 'p4we_translated_product_url', 10, 2 );

    I don't know if this could be causing any conflicts (after applying your mod I no longer see the server redirect_query string at the end of the permalink).

  5. ReactorShop
    Member
    Posted 7 months ago #

    Just to clarify, the redirect query strings need to be added when either the Purchase History, the Edit Profile or the Downloads "tab" is selected inside "Your Account" page.

    Your Account tab selection.

    I get to see those tabs until I remove the IF conditional to let the filter always set the taxonomies language. With the IF clause, I always see the wpsc-products posts (when viewing a CPT page) instead, as indicated in my previous post image.

  6. Chouby
    Member
    Plugin Author

    Posted 7 months ago #

    Well I don't know WP-Ecommerce so I must admit that I am a bit lost.

    What changed between 1.2.4 and 1.3 and which I think probably impacted you (because it was what I played around in 1.2dev57 too) is the 'parse_query' function in frontend/frontend.php:

    if (isset($query->tax_query->queries))
    	foreach ($query->tax_query->queries as $tax)
    		if (pll_is_translated_taxonomy($tax['taxonomy']))
    			$has_tax = true;
    
    // allow filtering recent posts and secondary queries by the current language
    // take care not to break queries for non visible post types such as nav_menu_items
    // do not filter if lang is set to an empty value
    // do not filter single page and translated taxonomies
    if (/*$query->is_home &&*/ !empty($this->curlang) && !isset($qv['lang']) && !$has_tax && empty($qv['page_id']) && empty($qv['pagename']) && (empty($qv['post_type']) || $this->model->is_translated_post_type($qv['post_type'])))
    	$query->set('lang', $this->curlang->slug);

    has been moved to:

    if (isset($query->tax_query->queries))
    	foreach ($query->tax_query->queries as $tax)
    		if ('post_format' != $tax['taxonomy'])
    			$has_tax = true;
    
    // allow filtering recent posts and secondary queries by the current language
    // take care not to break queries for non visible post types such as nav_menu_items
    // do not filter if lang is set to an empty value
    // do not filter single page and translated taxonomies to avoid conflicts
    if (!empty($this->curlang) && !isset($qv['lang']) && !$has_tax && empty($qv['page_id']) && empty($qv['pagename']) && (empty($qv['post_type']) || $this->model->is_translated_post_type($qv['post_type']))) {
    	$this->choose_lang->set_lang_query_var($query, $this->curlang);
    }

    and to understand the new 'set_lang_query_var' function, this is how it is defined in frontend/choose-lang.php:

    public function set_lang_query_var(&$query, $lang) {
    	// backward compatibility WP < 3.5
    	if (version_compare($GLOBALS['wp_version'], '3.5' , '<')) {
    		$query->set('lang', $lang->slug);
    	}
    	else {
    		// defining directly the tax_query (rather than setting 'lang' avoids transforming the query by WP)
    		$query->query_vars['tax_query'][] = array(
    			'taxonomy' => 'language',
    			'field'    => 'term_taxonomy_id', // since WP 3.5
    			'terms'    => $lang->term_taxonomy_id,
    			'operator' => 'IN'
    		);
    	}
    }

    So as you can see, I now don't set anymore the language on single pages to avoid a conflict (I was aware of that but forgot it in 1.2.x)

    Could you check that reverting this change does solve your issue?

  7. Chouby
    Member
    Plugin Author

    Posted 7 months ago #


  8. ReactorShop
    Member
    Posted 7 months ago #

    I'm sorry, my bad. Hit the wrong buttons.

    Regarding what you asked me to do, here's is what I did:

    I took PLL 1.2dev59 parse_query (my last known good config. I wasn't aware of PLL 1.2.4 until I received the 1.3 upgrade notification):

    public function parse_query($query) {
    		$qv = $query->query_vars;
    
    		// allow filtering recent posts and secondary queries by the current language
    		// take care not to break queries for non visible post types such as nav_menu_items
    		// do not filter if lang is set to an empty value
    		if (/*$query->is_home &&*/ !isset($qv['lang']) && (empty($qv['post_type']) || $this->model->is_translated_post_type($qv['post_type'])))
    			$query->set('lang', $this->curlang->slug);
    
    		// modifies query vars when the language is queried
    		if (!empty($qv['lang'])) {
    			// remove pages query when the language is set unless we do a search
    			if (empty($qv['post_type']) && !$query->is_search)
    				$query->set('post_type', 'post');
    
    			// unset the is_archive flag for language pages to prevent loading the archive template
    			// keep archive flag for comment feed otherwise the language filter does not work
    			if (!$query->is_comment_feed && !$query->is_post_type_archive && !$query->is_date && !$query->is_author && !$query->is_category && !$query->is_tag && !$query->is_tax('post_format'))
    				$query->is_archive = false;
    
    			// unset the is_tax flag for authors pages and post types archives
    			// FIXME Should I do this for other cases?
    			if ($query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search) {
    				$query->is_tax = false;
    				unset($query->queried_object);
    			}
    		}
    
    		// to avoid conflict beetwen taxonomies
    		if (isset($query->tax_query->queries))
    			foreach ($query->tax_query->queries as $tax)
    				if (pll_is_translated_taxonomy($tax['taxonomy']))
    					unset($query->query_vars['lang']);
    	}

    and used it to replace PLL 1.3.1

    public function parse_query($query) {
    		$qv = $query->query_vars;
    
    		// to avoid conflict beetwen taxonomies
    		// FIXME generalize post format like taxonomies (untranslated but filtered)
    		$has_tax = false;
    		if (isset($query->tax_query->queries))
    			foreach ($query->tax_query->queries as $tax)
    				if ('post_format' != $tax['taxonomy'])
    					$has_tax = true;
    
    		// allow filtering recent posts and secondary queries by the current language
    		// take care not to break queries for non visible post types such as nav_menu_items
    		// do not filter if lang is set to an empty value
    		// do not filter single page and translated taxonomies to avoid conflicts
    		if (!empty($this->curlang) && !isset($qv['lang']) && !$has_tax && empty($qv['page_id']) && empty($qv['pagename']) && (empty($qv['post_type']) || $this->model->is_translated_post_type($qv['post_type']))) {
    			$this->choose_lang->set_lang_query_var($query, $this->curlang);
    		}
    
    		// modifies query vars when the language is queried
    		if (!empty($qv['lang'])) {
    			// remove pages query when the language is set unless we do a search
    			if (empty($qv['post_type']) && !$query->is_search)
    				$query->set('post_type', 'post');
    
    			// unset the is_archive flag for language pages to prevent loading the archive template
    			// keep archive flag for comment feed otherwise the language filter does not work
    			if (!$query->is_comment_feed && !$query->is_post_type_archive && !$query->is_date && !$query->is_author && !$query->is_category && !$query->is_tag && !$query->is_tax('post_format'))
    				$query->is_archive = false;
    
    			// unset the is_tax flag for authors pages and post types archives
    			// FIXME Should I do this for other cases?
    			if ($query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search) {
    				$query->is_tax = false;
    				unset($query->queried_object);
    			}
    		}
    	}

    And it's working now.

    I'm not looking for you to switch to an approach that may destabilize PLL. Maybe another approach would be to add a filter hook so that these differences may be dealt with another plugin?

  9. Chouby
    Member
    Plugin Author

    Posted 7 months ago #

    I thought I was going crazy ;-)

    Maybe you can just remove the Polylang filter and set your own (hoping that you won't run in a conflict with pages:

    global $polylang;
    if ($polylang instanceof PLL_Frontend) {
    remove_filter('parse_query', array(&$polylang, 'parse_query'), 6);
    add_filter('parse_query', 'reactorshop_parse_query), 6);
    }
  10. ReactorShop
    Member
    Posted 7 months ago #

    Perfect! This is how it was fixed.

    1. Put the 1.2dev59 parse_query filter into a new plugin, like this:

    function pll_wpsc_parse_query($query) {
    	global $polylang;
    
    	if(isset($polylang->choose_lang)) {
    		$qv = $query->query_vars;
    
    		// allow filtering recent posts and secondary queries by the current language
    		// take care not to break queries for non visible post types such as nav_menu_items
    		// do not filter if lang is set to an empty value
    		if (/*$query->is_home &&*/ !isset($qv['lang']) && (empty($qv['post_type']) || $polylang->model->is_translated_post_type($qv['post_type'])))
    			$query->set('lang', $polylang->curlang->slug);
    
    		// modifies query vars when the language is queried
    		if (!empty($qv['lang'])) {
    			// remove pages query when the language is set unless we do a search
    			if (empty($qv['post_type']) && !$query->is_search)
    				$query->set('post_type', 'post');
    
    			// unset the is_archive flag for language pages to prevent loading the archive template
    			// keep archive flag for comment feed otherwise the language filter does not work
    			if (!$query->is_comment_feed && !$query->is_post_type_archive && !$query->is_date && !$query->is_author && !$query->is_category && !$query->is_tag && !$query->is_tax('post_format'))
    				$query->is_archive = false;
    
    			// unset the is_tax flag for authors pages and post types archives
    			// FIXME Should I do this for other cases?
    			if ($query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search) {
    				$query->is_tax = false;
    				unset($query->queried_object);
    			}
    		}
    
    		// to avoid conflict beetwen taxonomies
    		if (isset($query->tax_query->queries))
    			foreach ($query->tax_query->queries as $tax)
    				if (pll_is_translated_taxonomy($tax['taxonomy']))
    					unset($query->query_vars['lang']);
    	}
    	return $query;
    }
    add_filter('parse_query', 'pll_wpsc_parse_query', 6);

    2. Add another filter in that same plugin, which will be applied with priority 5, to remove PLL's 1.3.1 parse_query filter before it gets applied:

    function pll_remove_new_parse_query($query) {
    	global $polylang;
    	remove_filter('parse_query', array(&$polylang, 'parse_query'),6);
    	return $query;
    }
    add_filter('parse_query', 'pll_remove_new_parse_query', 5);

    And now, everyone is happy and this situation is solved.

    Thank you, Chouby!

  11. Chouby
    Member
    Plugin Author

    Posted 7 months ago #

    You can't do

    function pll_remove_new_parse_query($query) {
    	global $polylang;
    	remove_filter('parse_query', array(&$polylang, 'parse_query'),6);
    	return $query;
    }
    add_filter('parse_query', 'pll_remove_new_parse_query', 5);

    due to this bug: http://core.trac.wordpress.org/ticket/17817

    Any other hook strictly between 'plugins_loaded', 1 and 'parse_query' should be OK:
    add_filter('init', 'pll_remove_new_parse_query');

  12. ReactorShop
    Member
    Posted 7 months ago #

    Hi Chouby,

    It was working as I entered it (I'm not only removing a filter from this hook, but replacing it with other that has the same priority and all remaining hooked filters are being applied).

    But I'm considering your recommendation as good (better) practice, so I already tested it and it's working as you indicated.

    Thank you, Chouby!

Reply

You must log in to post.

About this Plugin

About this Topic