statamic / ideas

💡Discussions on ideas and feature requests for Statamic
https://statamic.dev
31 stars 1 forks source link

GraphQL: provide translations for entries #508

Open olivererdmann opened 3 years ago

olivererdmann commented 3 years ago

Bug Description

We're trying to query the list of translations for entries in GraphQL, which seems not possible at this time. Our goal is to provide links to related entries in other languages.

How to Reproduce

Open a GraphQL Browser and inspect the Schema for EntryInterface. It shows locale and site as only language related information, but no details about the entry's translations.

Extra Detail

When inspecting the Entry-class, I can see it has a property $locations and a method descendants(), which could provide this information.

Environment

Statamic 3.1.1 Pro Laravel 8.36.1 PHP 7.4.9 No addons installed

Install method (choose one):

jasonvarga commented 3 years ago

This is not a bug, it's a feature request. I've moved this to the ideas repo. Thanks!

olivererdmann commented 3 years ago

Alright, thank you!

grischaerbe commented 3 years ago

Although i agree this should be a feature out-of-the-box, for the time being, we are adding these custom fields ourselves:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Log;
use Statamic\Facades\GraphQL;
use Statamic\Facades\Site;

class GraphQLTranslationsServiceProvider extends ServiceProvider
{
    public function boot()
    {
        GraphQL::addField('EntryInterface', 'in', function () {
            return [
                'type' => GraphQL::type('EntryInterface'),
                'args' => [
                    'locale' => [
                        'type' => GraphQL::nonNull(GraphQL::string()),
                    ]
                ],
                'resolve' => function ($entry, $args) {
                    try {
                        // parsed locale argument
                        $locale = $args["locale"] ?? null;

                        // check if arg locale is provided
                        if (!$locale === null) {
                            throw new \Exception("No locale provided", 1);
                        }

                        // check if arg locale is available
                        $site = Site::get($locale);
                        if ($site === null) {
                            throw new \Exception("Locale provided does not exist", 1);
                        }

                        // check if entry is available in provided locale
                        if (!$entry->existsIn($locale)) return null;

                        // return the localized entry
                        return $entry->in($locale);
                    } catch (\Throwable $th) {
                        Log::error("Unable to resolve field 'thumbnail': " . $th->getMessage());
                        throw new \Exception("Error Processing Request: " . $th->getMessage(), 1);
                    }
                }
            ];
        });

        GraphQL::addField('EntryInterface', 'existsIn', function () {
            return [
                'type' => GraphQL::nonNull(GraphQL::boolean()),
                'args' => [
                    'locale' => [
                        'type' => GraphQL::nonNull(GraphQL::string()),
                    ]
                ],
                'resolve' => function ($entry, $args) {
                    try {
                        // parsed locale argument
                        $locale = $args["locale"] ?? null;

                        // check if arg locale is provided
                        if (!$locale === null) {
                            throw new \Exception("No locale provided", 1);
                        }

                        // check if arg locale is available
                        $site = Site::get($locale);
                        if ($site === null) {
                            throw new \Exception("Locale provided does not exist", 1);
                        }

                        // return if localized entry exists
                        return $entry->existsIn($locale);
                    } catch (\Throwable $th) {
                        Log::error("Unable to resolve field 'thumbnail': " . $th->getMessage());
                        throw new \Exception("Error Processing Request: " . $th->getMessage(), 1);
                    }
                }
            ];
        });
    }
}

Example usage:

query MyQuery {
  entry(collection: "pages", slug: "home") {
    slug_de: in(locale: "de") {
      slug
    }
    has_german_translation: existsIn(locale: "de")
  }
}