Tłumaczenie
Dyrektywa @strTranslate do tłumaczenia wartości pola przy użyciu API dowolnego dostawcy.
Description
Dodaj dyrektywę @strTranslate do dowolnego pola typu String, aby przetłumaczyć je na wybrany język.
Na przykład poniższe query tłumaczy pola title i excerpt wpisu z angielskiego na francuski (używając domyślnego dostawcy API):
{
posts {
enTitle: title
frTitle: title @strTranslate(from: "en", to: "fr")
enExcerpt: excerpt
frExcerpt: excerpt @strTranslate(from: "en", to: "fr")
}
}...dając w wyniku:
{
"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
Dyrektywa @strTranslate wymaga podania trzech argumentów:
provider: dostawca używany do tłumaczeniafrom: kod języka tekstu źródłowegoto: kod języka, na który ma nastąpić tłumaczenie
Możemy zdefiniować wartości domyślne dla tych właściwości w zakładce "Schema Configuration => Translation" na stronie Ustawień. Wartości te będą używane zawsze, gdy którykolwiek z tych argumentów nie zostanie podany w query:
{
posts {
title @strTranslate
}
}Ponadto po zdefiniowaniu wartości domyślnych odpowiedni argument w schemacie GraphQL przestaje być obowiązkowy.
Domyślnie wartość domyślna from to język używany w WordPress.
W Ustawieniach
Wpisz pola provider/from/to w odpowiednim polu na stronie Ustawień i kliknij "Save Changes (All)":

W wp-config.php
Dodaj stałe w wp-config.php:
GATOGRAPHQL_TRANSLATION_DEFAULT_PROVIDERGATOGRAPHQL_TRANSLATION_DEFAULT_FROM_LANG_CODEGATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE
Na przykład:
define( 'GATOGRAPHQL_TRANSLATION_DEFAULT_TO_LANG_CODE', 'fr' );Za pomocą zmiennej środowiskowej
Zdefiniuj zmienne środowiskowe:
TRANSLATION_DEFAULT_PROVIDERTRANSLATION_DEFAULT_FROM_LANG_CODETRANSLATION_DEFAULT_TO_LANG_CODE
Wielojęzyczne tłumaczenie Sync/Async
Dyrektywa @strTranslate wysyła jedno żądanie na język do przetłumaczenia. Podczas tłumaczenia na wiele języków możesz zdecydować, czy wysyłać żądania asynchronicznie (czyli równolegle), czy synchronicznie (czyli sekwencyjnie).
Żądania synchroniczne vs asynchroniczne:
- Synchroniczne: Każde żądanie tłumaczenia czeka na zakończenie poprzedniego przed rozpoczęciem. Wolniejsze, ale bezpieczniejsze przy limitach częstotliwości.
- Asynchroniczne: Wszystkie żądania tłumaczenia są wysyłane jednocześnie. Szybsze, ale może prowadzić do przekroczenia limitów częstotliwości, jeśli jednocześnie wysłano zbyt wiele żądań.

Limity czasu żądania i połączenia
Tłumaczenie długiego dokumentu przez zewnętrznego dostawcę może być powolne, a zawieszony upstream zajmowałby wątek PHP aż do momentu, gdy sam PHP zakończyłby żądanie.
Twój serwer internetowy wymusza maksymalny czas wykonania dla każdego żądania PHP za pomocą dyrektywy max_execution_time (ustawionej w php.ini lub za pośrednictwem panelu sterowania hostingu — cPanel zazwyczaj udostępnia ją w "Select PHP Version" → "Options", a zarządzane hosty takie jak SiteGround / Kinsta Engine prezentują ją w swoich ustawieniach PHP).
Wtyczka udostępnia dwie opcje na stronie Ustawień, w sekcji Plugin Configuration > Translation:
- Request timeout: maksymalny czas oczekiwania (w sekundach) na pełną odpowiedź od dostawcy tłumaczenia
- Connection timeout: maksymalny czas oczekiwania (w sekundach) przy nawiązywaniu połączenia z dostawcą tłumaczenia

Wartości te powinny być niższe niż max_execution_time serwera, aby zawieszone tłumaczenie kończyło się w kontrolowany sposób z czytelnym komunikatem o błędzie, zamiast wyzwalać ogólny limit czasu serwera (HTTP 502 / 504 lub pusta strona "Maximum execution time of N seconds exceeded"). Jeśli tłumaczenia regularnie przekraczają limit czasu, zwiększ obie te wartości oraz max_execution_time serwera jednocześnie.
Debugowanie żądań API
Aby debugować żądania wysyłane do dostawców tłumaczeń (takich jak ChatGPT, Claude lub Google Translate) i ich odpowiedzi, możesz włączyć poziom ważności 🔵 Info w ustawieniach Logów.
Po włączeniu tej opcji logi będą zawierać wszystkie interakcje z dostawcami tłumaczeń, zapisane w pozycjach api-requests.

Co jest rejestrowane
W przypadku dostawców AI pozycja api-requests zawiera szczegółowe informacje na temat:
- Promptu wysłanego do dostawcy tłumaczenia
- Kompletnej otrzymanej odpowiedzi
- Wszelkich błędów lub problemów podczas komunikacji
- Użytego modelu
- Liczby użytych tokenów

Na przykład poniższy JSON "Additional context" pokazuje szczegóły żądania wysłanego do ChatGPT i jego odpowiedź:
{
"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"
}
}