magento2: [GraphQl] Exception are not translated to store scope.

Preconditions (*)

Reproduced on

  1. Magento 2.3.5-p2
  2. Magento 2.4.1

Steps to reproduce (*)

  1. Set the locale of a store to anything but en_US.
  2. Create a translation file/database entry with one of the translatable exception strings (eg: ‘currentPage value must be greater than 0.’ to ‘This text is translated’)
  3. Make a GraphQl request that will cause the exception to trigger with the Store header for the store set in 1.
query productList{
    products( currentPage: 0) {
        items {
            id
            name
        }
    }
}

Expected result (*)

{
    "errors": [
        {
            "message": "This text is translated.",
            "extensions": {
                "category": "graphql-input"
            },
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "path": [
                "products"
            ]
        }
    ],
    "data": {
        "products": null
    }
}

Actual result (*)

{
    "errors": [
        {
            "message": "currentPage value must be greater than 0.",
            "extensions": {
                "category": "graphql-input"
            },
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "path": [
                "products"
            ]
        }
    ],
    "data": {
        "products": null
    }
}

Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 5
  • Comments: 31 (14 by maintainers)

Commits related to this issue

Most upvoted comments

@gabrieldagama This feels like a waste of having the entire translation functionality in Magento. Adding Error Codes is fine because you might want to do something different based on the error code. But seeing as all other endpoints (soap, rest, the html frontend) do translate their output based on the store scope it would be weird that only graphql doesn’t do this.

And by putting the burden of translations on the frontend application, you’ll increase it’s size which you are trying to prevent especially if it will be running client side.

In my case I’m reading the cart/quote items that have custom made options. The labels of these options were not translated which doesn’t make any sense, also not regarding PWA. My fix is:

Load the translations when the GraphQL controller is dispatched.
===================================================================
--- Controller/GraphQl.php
+++ Controller/GraphQl.php
@@ -7,6 +7,7 @@

 namespace Magento\GraphQl\Controller;

+use Magento\Framework\App\Area;
 use Magento\Framework\App\FrontControllerInterface;
 use Magento\Framework\App\Request\Http;
 use Magento\Framework\App\RequestInterface;
@@ -89,6 +90,9 @@
      */
     private $contextFactory;

+    /** @var \Magento\Framework\App\State $appState */
+    private $appState;
+
     /**
      * @param Response $response
      * @param SchemaGeneratorInterface $schemaGenerator
@@ -114,7 +118,8 @@
         QueryFields $queryFields,
         JsonFactory $jsonFactory = null,
         HttpResponse $httpResponse = null,
-        ContextFactoryInterface $contextFactory = null
+        ContextFactoryInterface $contextFactory = null,
+        \Magento\Framework\App\AreaList $areaList
     ) {
         $this->response = $response;
         $this->schemaGenerator = $schemaGenerator;
@@ -127,6 +132,7 @@
         $this->jsonFactory = $jsonFactory ?: ObjectManager::getInstance()->get(JsonFactory::class);
         $this->httpResponse = $httpResponse ?: ObjectManager::getInstance()->get(HttpResponse::class);
         $this->contextFactory = $contextFactory ?: ObjectManager::getInstance()->get(ContextFactoryInterface::class);
+        $this->areaList = $areaList;
     }

     /**
@@ -138,6 +144,8 @@
      */
     public function dispatch(RequestInterface $request) : ResponseInterface
     {
+        $this->areaList->getArea(Area::AREA_GRAPHQL)->load(Area::PART_TRANSLATE);
+
         $statusCode = 200;
         $jsonResult = $this->jsonFactory->create();
         try {

@ihor-sviziev I agree. It’s quite an important bug since multi-store and multi language features are already there at pwa studio with the release of 2.4.2. This should be addressed soon.

@denis-zyk As far as I know, it hasn’t been integrated in any form. But instead of a patch a small module that just adds a before plugin on dispatch in Magento\GraphQl\Controller\GraphQl is probably cleaner and easier to remember that it exists.

@sidolov @sivaschenko seems like quite an important issue for single-page applications, like PWA, or by using GraphQL on the frontend and showing exceptions to users. Let’s set priority to p2 or even p1.

<?php

namespace Vender\GraphQlExceptionMessageFix\Plugin\Controller;

use Magento\Framework\App\Area;
use Magento\Framework\App\AreaList;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\State;
use Magento\Framework\Locale\ResolverInterface;
use Magento\Framework\TranslateInterface;
use Magento\GraphQl\Controller\GraphQl;
use Magento\Store\Model\StoreManagerInterface;

class GraphQlPlugin
{
    /** @var AreaList $areaList */
    private $areaList;

    /** @var State $appState */
    private $appState;
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var ResolverInterface
     */
    private $localeResolver;

    public function __construct(
        AreaList $areaList,
        State $appState,
        TranslateInterface $translation,
        ResolverInterface $localeResolver,
        StoreManagerInterface $storeManager
    ) {
        $this->areaList = $areaList;
        $this->appState = $appState;
        $this->translation = $translation;
        $this->localeResolver = $localeResolver;
        $this->storeManager = $storeManager;
    }

    public function beforeDispatch(GraphQl $subject, RequestInterface $request)
    {
        $area = $this->areaList->getArea($this->appState->getAreaCode());
        $storeIdOrCode = $request->getHeader('store') ?: 0;
        $locale = $this->storeManager->getStore($storeIdOrCode)->getConfig('general/locale/code');
        $this->localeResolver->setLocale($locale);
        $this->translation->setLocale($locale);
        $area->load(Area::PART_TRANSLATE);
    }
}

Working version of the plugin at https://stackoverflow.com/questions/61770306/while-working-with-the-magento-2-graphql-it-seems-that-the-string-translation-do

I think we can scope this for 2.4.3. We need this merged by May 15h if we want to include it in next release Ideally a PR has to be provided by May 7th We only have to move that scope area code in dispatch and not a plugin https://github.com/magento/magento2/issues/31351#issuecomment-792933568 so fix in https://github.com/magento/magento2/issues/31351#issuecomment-808106829 makes a lot of sense