Translation
Directive @strTranslate
to translate a field value using any provider's API.
Description
Add directive @strTranslate
to any field of type String
, to translate it to the desired language.
For instance, this query translates the post's title
and excerpt
fields from English to French (using the default API provider):
{
posts {
enTitle: title
frTitle: title @strTranslate(from: "en", to: "fr")
enExcerpt: excerpt
frExcerpt: excerpt @strTranslate(from: "en", to: "fr")
}
}
...producing:
{
"data": {
"posts": [
{
"enTitle": "Welcome to a single post full of blocks!",
"frTitle": "Bienvenue dans un poste unique plein de blocs !",
"enExcerpt": "When I look back on my past and think how much time I wasted on nothing, how much time has been lost in futilities, errors, laziness, incapacity to live; how little I appreciated it, how many times I sinned against my heart and soul-then my heart bleeds. Life is a gift, life is happiness, every…",
"frExcerpt": "Quand je repense à mon passé et que je pense au temps que j'ai perdu pour rien, au temps perdu en futilités, en erreurs, en paresse, en incapacité de vivre ; combien je l'ai peu apprécié, combien de fois j'ai péché contre mon cœur et mon âme, alors mon cœur saigne. La vie est un cadeau, la vie est un bonheur, chaque…"
},
{
"enTitle": "Explaining the privacy policy",
"frTitle": "Expliquer la politique de confidentialité",
"enExcerpt": "Our privacy policy is at https://gato-graphql-pro.lndo.site/privacy/, and we are based in Carimano.",
"frExcerpt": "Notre politique de confidentialité se trouve sur https://gato-graphql-pro.lndo.site/privacy/, et nous sommes basés à Carimano."
},
{
"enTitle": "HTTP caching improves performance",
"frTitle": "La mise en cache HTTP améliore les performances",
"enExcerpt": "Categories Block Latest Posts Block Did you know? We are not rich by what we possess but by what we can do without. Patience is the strength of the weak, impatience is the weakness of the strong.",
"frExcerpt": "Catégories Bloquer les derniers messages Bloquer Le saviez-vous ? Nous ne sommes pas riches de ce que nous possédons mais de ce dont nous pouvons nous passer. La patience est la force du faible, l'impatience est la faiblesse du fort."
}
]
}
}
Schema Configuration
Directive @strTranslate
requires passing three arguments:
provider
: the provider to use for the translationfrom
: the language code of the textto
: the language code to translate to
We can define a default value for these properties in tab "Schema Configuration => Translation" on the Settings page. These values will be used whenever any of those arguments is not provided in the query:
{
posts {
title @strTranslate
}
}
In addition, when defining default values, the corresponding argument in the GraphQL schema becomes non-mandatory.
By default, the default from
value is the language used in WordPress.
By Settings
Input the provider
/from
/to
fields in the corresponding input in the Settings page, and click on "Save Changes (All)":

wp-config.php
In
Add constants in wp-config.php
:
GATOGRAPHQL_TRANSLATION_DEFAULT_PROVIDER
GATOGRAPHQL_TRANSLATION_DEFAULT_FROM_LANG_CODE
GATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE
For instance:
define( 'GATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE', 'fr' );
By environment variable
Define environment variables:
TRANSLATION_DEFAULT_PROVIDER
TRANSLATION_DEFAULT_FROM_LANG_CODE
TRANSLATION_DEFAULT_TO_LANG_CODE
Sync/Async multi-language translation
Directive @strTranslate
will send a request per language to translate. When translating to multiple languages, you can decide if to send the requests asynchronously (i.e. in parallel) or synchronously (i.e. sequentially).
Synchronous vs Asynchronous Requests:
- Synchronous: Each translation request waits for the previous one to complete before starting. Slower but safer with rate limits.
- Asynchronous: All translation requests are sent simultaneously. Faster but may hit rate limits if too many requests are sent at once.

Debugging AI Requests
To debug the requests sent to AI providers (like ChatGPT or Claude) and their responses, you can enable the 🔵 Info severity level in the Logs settings.
When doing so, the logs will contain all interactions with the AI providers, stored under the ai-requests
entries.

What's Logged
The ai-requests
entry contains detailed information about:
- The prompt sent to the AI provider
- The complete response received
- Any errors or issues during the communication
- The model used
- The number of tokens used

For instance, the following "Additional context" JSON shows the details of a request sent to ChatGPT, and its response:
{
"request": {
"model": "gpt-4o-mini",
"messages": [
{
"role": "system",
"content": "You are a language translator."
},
{
"role": "user",
"content": "I'm working on internationalizing my application.\n\nI've created a JSON with sentences in English. Please translate the sentences to Spanish from .\n\nIf a sentence contains HTML, do not translate inside the HTML tags. Keep emojis exactly as they are, do not translate them.\n\nThis is the JSON:\n\n[\"Welcome to a single post full of blocks!\",\"Repeating the privacy policy\",\"Explaining the privacy policy\",\"HTTP caching improves performance\",\"Public or Private API mode, for extra security\",\"GraphQL or REST? Why not both?\",\"Customize the schema for each client\",\"Nested mutations are a must have\",\"Working on flat chain syntax next\",\"Released v0.6, check it out\"]"
}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "translation_response",
"strict": true,
"schema": {
"type": "object",
"properties": {
"translations": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"translations"
],
"additionalProperties": false
}
}
}
},
"response": {
"id": "chatcmpl-BbjNiuO5Si1vhalfIXYU0hWiCmg12",
"object": "chat.completion",
"created": 1748332282,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"translations\":[\"¡Bienvenido a una publicación única llena de bloques!\",\"Repitiendo la política de privacidad\",\"Explicando la política de privacidad\",\"La caché HTTP mejora el rendimiento\",\"Modo API Público o Privado, para mayor seguridad\",\"¿GraphQL o REST? ¿Por qué no ambos?\",\"Personaliza el esquema para cada cliente\",\"Las mutaciones anidadas son imprescindibles\",\"Próximamente trabajando en la sintaxis de cadena plana\",\"Lanzada la versión v0.6, ¡échale un vistazo!\"]}",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 184,
"completion_tokens": 112,
"total_tokens": 296,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"service_tier": "default",
"system_fingerprint": "fp_34a54ae93c"
}
}