Vertaling
VertalingVertaling

Vertaling

Directive @strTranslate om een veldwaarde te vertalen via de API van elke provider.

Description

Voeg directive @strTranslate toe aan elk veld van het type String om het naar de gewenste taal te vertalen.

Zo vertaalt deze query bijvoorbeeld de velden title en excerpt van een bericht van Engels naar Frans (met de standaard API-provider):

{
  posts {
    enTitle: title
    frTitle: title @strTranslate(from: "en", to: "fr")
 
    enExcerpt: excerpt    
    frExcerpt: excerpt @strTranslate(from: "en", to: "fr")
  }
}

...wat het volgende oplevert:

{
  "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 vereist drie argumenten:

  • provider: de provider die voor de vertaling wordt gebruikt
  • from: de taalcode van de brontekst
  • to: de taalcode waarnaar vertaald moet worden

Je kunt standaardwaarden voor deze eigenschappen instellen via het tabblad "Schema Configuration => Translation" op de instellingenpagina. Deze waarden worden gebruikt wanneer een van de argumenten niet in de query is opgegeven:

{
  posts {
    title @strTranslate
  }
}

Bovendien wordt het bijbehorende argument in het GraphQL-schema niet-verplicht zodra standaardwaarden zijn gedefinieerd.

Standaard is de standaardwaarde van from de taal die in WordPress wordt gebruikt.

Via Instellingen

Vul de velden provider/from/to in het bijbehorende invoerveld op de instellingenpagina in en klik op "Save Changes (All)":

De standaard 'provider' en de talen 'from' en 'to' instellen
De standaard 'provider' en de talen 'from' en 'to' instellen

In wp-config.php

Voeg constanten toe in wp-config.php:

  • GATOGRAPHQL_TRANSLATION_DEFAULT_PROVIDER
  • GATOGRAPHQL_TRANSLATION_DEFAULT_FROM_LANG_CODE
  • GATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE

Bijvoorbeeld:

define( 'GATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE', 'fr' );

Via omgevingsvariabele

Definieer omgevingsvariabelen:

  • TRANSLATION_DEFAULT_PROVIDER
  • TRANSLATION_DEFAULT_FROM_LANG_CODE
  • TRANSLATION_DEFAULT_TO_LANG_CODE

Sync/Async meertalige vertaling

Directive @strTranslate verstuurt één verzoek per taal om te vertalen. Bij het vertalen naar meerdere talen kun je kiezen of je de verzoeken asynchroon (d.w.z. parallel) of synchroon (d.w.z. sequentieel) verstuurt.

Synchrone vs. asynchrone verzoeken:

  • Synchroon: Elk vertaalverzoek wacht tot het vorige is voltooid voordat het begint. Langzamer, maar veiliger bij snelheidslimieten.
  • Asynchroon: Alle vertaalverzoeken worden tegelijkertijd verstuurd. Sneller, maar kan snelheidslimieten overschrijden als er te veel verzoeken tegelijk worden verstuurd.
Sync/async-modus gebruiken om meerdere talen tegelijk te vertalen
Sync/async-modus gebruiken om meerdere talen tegelijk te vertalen

Time-outs voor verzoeken en verbindingen

Het vertalen van een lang document via een externe provider kan traag zijn, en een vastgelopen upstream houdt anders een PHP-worker bezet totdat PHP zelf het verzoek afbreekt.

Je webserver legt via de max_execution_time-directive een maximale uitvoeringstijd op voor elk PHP-verzoek (ingesteld in php.ini of via het controlepaneel van je hosting — cPanel biedt dit doorgaans aan onder "Select PHP Version" → "Options", en beheerde hosts zoals SiteGround / Kinsta Engine stellen het beschikbaar in hun PHP-instellingen).

De plugin biedt twee opties op de instellingenpagina, onder Plugin Configuration > Translation:

  • Request timeout: de maximale tijd (in seconden) om te wachten op de volledige reactie van de vertaalprovider
  • Connection timeout: de maximale tijd (in seconden) om te wachten bij het opzetten van de verbinding met de vertaalprovider
De Request timeout en Connection timeout voor vertaling instellen
De Request timeout en Connection timeout voor vertaling instellen

Deze waarden moeten lager zijn dan de max_execution_time van je server, zodat een vastgelopen vertaling netjes eindigt met een duidelijke foutmelding in plaats van de algemene server-time-out te activeren (HTTP 502 / 504, of een lege pagina "Maximum execution time of N seconds exceeded"). Als vertalingen regelmatig uitvallen wegens een time-out, verhoog dan beide waarden samen met de max_execution_time van je server.

API-verzoeken debuggen

Om de verzoeken die naar vertaalproviders (zoals ChatGPT, Claude of Google Translate) worden gestuurd en hun antwoorden te debuggen, kun je het 🔵 Info-ernstniveau inschakelen in de instellingen voor Logs.

Wanneer je dit doet, bevatten de logs alle interacties met de vertaalproviders, opgeslagen onder de api-requests-vermeldingen.

AI-verzoeken in de Logs
AI-verzoeken in de Logs

Wat wordt geregistreerd

Voor AI-providers bevat de api-requests-vermelding gedetailleerde informatie over:

  • De prompt die naar de vertaalprovider is gestuurd
  • Het volledige ontvangen antwoord
  • Eventuele fouten of problemen tijdens de communicatie
  • Het gebruikte model
  • Het aantal gebruikte tokens
Detail van een AI-verzoek in de Logs
Detail van een AI-verzoek in de Logs

Zo toont de volgende JSON "Additional context" de details van een verzoek dat naar ChatGPT is gestuurd en het bijbehorende antwoord:

{
  "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"
  }
}