Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When you query for a single post via URI, then the language is ignored #46

Closed
MobyDigg opened this issue May 6, 2021 · 6 comments
Closed
Labels
duplicate This issue or pull request already exists

Comments

@MobyDigg
Copy link

MobyDigg commented May 6, 2021

When you query for a single post via URI, then the language parameter in the URL is ignored.
Query returns only the post in the standard language:

query MyQuery {
  teamMember(id: "/fr/team_members/lorem-ipsum/", idType: URI) {
    slug
    language {
      code
    }
    uri
  }
}

It should return the the French version for the query above.

@tim9009
Copy link

tim9009 commented May 10, 2021

I have a similar issue now and it's blocking my entire project. Did you find a solution yet @MobyDigg?

In my case if I query the main language version of the cpt by URI I get the expected result.

If I query the translated version of the cpt by URI (the exact URI, copied from wp-admin, including a translated rewrite slug) I get an internal server error "Cannot return null for non-nullable field "Article.databaseId".".

If I query the cpt by using the untranslated URI and just replace the final slug with the translated one I get the translated cpt. The returned URI field is exactly the same as in wp-admin.

@MobyDigg
Copy link
Author

MobyDigg commented May 11, 2021

Unfortunately not. I had to create a work-around… In the end I queried all posts and then filtered by the slug. Obviously that is not really performant.

@gorkalaucirica
Copy link

gorkalaucirica commented Jun 2, 2021

This filter worked for me:

add_filter(
    'request',
    function ( array $query_args) {
        if ( isset( $query_args['name'] ) ) {
            $allowed_post_types = get_post_types( [
                'show_in_graphql' => true,
                'public'          => true,
            ] );

            $post_type = 'post';
            if ( isset( $query_args['post_type'] ) && in_array( $query_args['post_type'], $allowed_post_types, true ) ) {
                $post_type = $query_args['post_type'];
            }

            $post = get_page_by_path( $query_args['name'], 'OBJECT', $post_type );
            $translations = pll_get_post_translations($post->ID);
            $post_id = $translations[$query_args['lang']] ?? null;

            $query_args["page_id"] = $post_id;
        }
        return $query_args;
}, 	10, 2);

It's based on how wpgraphql's NodeResolver works

@pangeaos
Copy link

hi @gorkalaucirica, any help how to implement this filter? or how it works. thanks.

@esamattis esamattis added bug Something isn't working duplicate This issue or pull request already exists and removed bug Something isn't working labels Nov 11, 2021
@esamattis
Copy link
Member

This is actually a duplicate of #35

Might want to read this #35 (comment)

Thank you for the filter workaround @gorkalaucirica

@simplenotezy
Copy link

simplenotezy commented Jan 13, 2022

Unfortunately I didn't have much luck with @gorkalaucirica's filter. Instead, this fixed it for my use-case:

/**
 * Bugfix: prevent fetching pages from other languages. Without below filter, /de/about-us would resolve
 * to the english post called /en/about-us, which will give SEO issues. It also fixes an issue if two
 * posts in two different languages had the same post_name, the wrong one would/could be resolved
 * depending on what language you was requesting
 *
 * https://github.com/valu-digital/wp-graphql-polylang/issues/35
 */

add_filter( 'request', function ( $query_args) {
    if(isset($query_args['uri']) && $query_args['uri'] && isset($query_args['lang'])) {
        $explodedUri = explode('/', $query_args['uri']);
        if($explodedUri[0] !== $query_args['lang']) {
            // query was made without language slug in URI
            return $query_args;
        }

        unset($explodedUri[0]); // remove language slug from URL
        $uriWithoutLang = implode('/', $explodedUri); // rebuild the URI without the slug in front

        // search for the URI (post_name) without the language slug
        // as well as including the requested $lang in the query
        $query = new \WP_Query([
            'post_type'      => isset($query_args['post_type']) ? $query_args['post_type'] : 'any',
            'lang'           => $query_args['lang'],
            'posts_per_page' => 1,
            'post_status'    => 'publish',
            'name'           => $uriWithoutLang
        ]);

        if($query->have_posts() && isset($query->posts[0])) {
            // if we found a post, that's most likely the post we're looking for,
            // in the given language
            $query_args['p'] = $query->posts[0]->ID;
        } else {
            // we weren't able to find a post/page with the given URI and language
            // reset the query_args to return an empty response (to generate 404 page)
            // alternatively remove below line, if you wish to fallback to default behaviour
            // which may cause SEO issues, depending on your setup

            // some custom post types, or posts which are parents of other pasts, and thus have
            // a more complicated structure, we can run it through pll_get_post_language
            // and check if the post language corresponds to the requested language
            if(function_exists('pll_get_post_language')) {
                $post = get_page_by_path($uriWithoutLang);

                if($post && pll_get_post_language($post->ID) !== $query_args['lang']) {
                    $query_args = [];
                }
            }
        }
    }
    return $query_args;
}, 	10, 2);

It's not the prettiest, but it does it's job. We had an issue if two pages was called the same, e.g. /de/about us and /en/about-us, when requesting the /de/about-us, it would resolve the english version.

Also we had an issue where if you requested an english slug, on the german prefix, if a german page did not exist with that name, it would return the english page - on the german site. Above filter also fixes that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

6 participants