Closed retzion closed 2 years ago
@rburgst Pinging this too - currently querying posts
returns all posts in all languages - I need a way to query just English, or just Spanish, to allow for pagination.
I know this is an urgent request however, at the moment I am very busy with other things.
following this thread
follow
You can do this: https://DOMAIN.com/graphql?locale=en
You can do this: https://DOMAIN.com/graphql?locale=en
Is it really possible?
If this can help anyone, i've developped a code that allows you to filter content by WPML locale by adding a new "wpmlLanguage" in the WHERE clause of the following post types:
Keep in mind that i've developped this for my specific use case so it might not be the most optimized. It also hasn't been tested on a website with lots of content, but it works for me right now.
This code can be added to a custom plugin or in a theme's functions.php. It has been developped with WP GraphQL 1.6.12 and WPGraphQL WPML 1.0.8.
/**
* Function called by the graphql_register_types action. Used to register a new "wpmlLanguage" where clause in specific post types. This function only registers the field, it is not in charge of filtering by language.
* Adds a wpmlLanguage field where clause to: Pages, Posts, Categories, Comments, any custom post type and any custom taxonomy.
* @return void
*/
function leonard_graphql_register_language_where_option(){
$connections_where_name = [
'RootQueryToPostConnectionWhereArgs',
'RootQueryToPageConnectionWhereArgs',
'RootQueryToCategoryConnectionWhereArgs',
'RootQueryToCommentConnectionWhereArgs',
];
$language_field_params = [
'wpmlLanguage' => [
'type' => 'String',
'description' => 'Filter by WPML language code',
],
];
//Get all new custom post types that are available in the GraphQL schema
$gql_valid_custom_post_types = get_post_types([
'show_in_graphql' => true,
'_builtin' => false
], 'objects');
//Get all new taxonomies post types that are available in the GraphQL schema
$gql_valid_taxonomies = get_taxonomies([
'show_in_graphql' => true,
'_builtin' => false
], 'objects');
//Add the custom post types to the connections that require the language filter option
foreach ($gql_valid_custom_post_types as $custom_post_type) {
$connections_where_name[] = 'RootQueryTo' . ucwords($custom_post_type->graphql_single_name) . 'ConnectionWhereArgs';
}
//Add the custom taxonomies to the connections that require the language filter option
foreach ($gql_valid_taxonomies as $custom_taxonomy) {
$connections_where_name[] = 'RootQueryTo' . ucwords($custom_taxonomy->graphql_single_name) . 'ConnectionWhereArgs';
}
foreach ($connections_where_name as $connection) {
register_graphql_fields($connection, $language_field_params);
}
}
function leonard_graphql_action_init()
{
add_action(
'graphql_register_types',
'leonard_graphql_register_language_where_option',
10,
0
);
}
add_action('graphql_init', 'leonard_graphql_action_init');
/**
* Function used to filter the query args of specific graphql request.
* Checks if the wpmlLanguage exists in the GraphQL query WHERE clause. If so, switch the language to the specified locale.
*
* @param array $query_args: Array used as arguments in a WP Query request
* @param array $args: Array containing the GraphQL query filter params
* @return $query_args
*/
function leonard_handle_lang_filter_request($query_args, $source, $args, $context, $info)
{
$lang = $args['where']['wpmlLanguage'];
//If the wpmlLanguage argument exists
if(isset($lang)){
global $sitepress;
//If WPML is installed
if($sitepress){
//Switch the current locale
$sitepress->switch_lang($lang);
//Remove the argument added earlier that removes all language filtering
$query_args['suppress_wpml_where_and_join_filter'] = false;
}
}
return $query_args;
}
add_filter('graphql_post_object_connection_query_args', 'leonard_handle_lang_filter_request', 110, 5);
add_filter('graphql_term_object_connection_query_args', 'leonard_handle_lang_filter_request', 110, 5);
add_filter('graphql_comment_object_connection_query_args', 'leonard_handle_lang_filter_request', 110, 5);
@macharest this looks really good. Would you mind creating a PR so we can integrate this into this plugin?
@rburgst Sure I could probably integrate this as a PR in the next few days or so.
@macharest This works well, thank you! In many front end clients (such as apollo or urql) this would require destroying the client instance and re-creating a new client on locale change. It seems like a more elegant solution may be to support reading a request header from the client. Something like "locale: en" for example. Then we can simply invalidate cache on locale change to get fresh queries. Is this something that's possible?
@RevNelson I am not sure I understand, the PR https://github.com/rburgst/wp-graphql-wpml/pull/32 adds a new filter option where you can choose the language via your normal Query.
@rburgst @macharest is it possible to implement the where also on singular item like Page and Post?
for example if I want to query a page by slug I need to filter also for language in case I have the same slug on two different languages, es test
and test?lang=en
@rburgst @macharest is it possible to implement the where also on singular item like Page and Post? for example if I want to query a page by slug I need to filter also for language in case I have the same slug on two different languages, es
test
andtest?lang=en
I am also looking for this solution to return a single translated post
eg: I need to retrieve a single post by its slug. In WPGraphQL there is no way to retrieve a single post by ID type slug when using Posts. This only works on singular Post
Since where and wpmlLanguage: "es" only works on pages I am unable to retrieve a single post in the specific language
Something like this would be ideal
post(id: "some/post", idType: URI, wpmlLanguage: "es") {
@rburgst also running into the same problem as @andyjamesn, being unable to just query a post by its slug and the desired language. I sort of see why, since slugs are meant to be unique, but in the context of wpml where slugs may be the same, it would be incredibly useful.
I'm unable to think of a solution that doesn't require two requests (first to get post and the id of its translations, second to get the desired translation).
I'm using NextJS with SSR, and trying to use pretty permalinks. To identify a unique post, I would like to use its URI or slug. However, using post(id: $slug, idType: SLUG)
(or a CPT's equivalent) returns null
for every slug that doesn't match a default language post.
In my use-case, the slugs for different languages will be derived from the translated post's title, so they will (almost certainly) be unique across languages. Having support for querying single posts based on their (translated) slug, would be great.
I could extract the language from the language code from the request URI and use it to set a language filter, if a solution like the one @andyjamesn suggested, was implemented.
Edit: I don't know how I didn't think of this earlier, but a very easy workaround is to use the multiple object version of the query and using the where
filter, combined with first
, which allows to get only one post, according to name (slug) and language.
posts(where: {name: $slug, wpmlLanguage: $languageCode}, first: 1) {
nodes {
id
}
}
@Ririshi this sounds like a reasonable approach for now, thanks for sharing
Thank you to anyone who can help with this. Maybe my approach is wrong and you can tell me how you are getting the results I'm looking for.