SurveyJS Server Integration · PHP / Laravel III.3 · Translate strings with AI
You work in a private copy of the demo database, kept until it has been unused for 24 hours.

III.3

Translate strings with AI

You need this: Multilingual forms.

The Translations tab can request machine translation. Creator passes you the strings and the locales; your endpoint calls the AI provider you choose with your own key, and the author reviews the result. Nothing goes to SurveyJS.

This step on the Server Integration page Source on GitHub Commercial client licence: without SURVEYJS_LICENSE_KEY the component shows a licence banner

Try this

  1. The Translations tab opens with Deutsch, Français and Español added, and Español selected. Press Auto-translate All (the language list is in the side panel, Languages), or tick another language to translate into it too.
  2. Requests shows one POST /api/translate with the strings and the locales: it is the only outbound request, and your server calls your AI provider.
  3. Without AI_API_KEY, the endpoint answers 501 and the page shows its message.

Code that just ran

These regions are read from the files that served this page, the same lines the Server Integration page shows.

Client · shared/client/ai-translation.js · sjs:III.3.client View on GitHub
// Creator asks for machine translation; your server calls the AI provider
creator.onMachineTranslate.add(async (_, options) => {
  const res = await fetch("/api/translate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ strings: options.strings, from: options.fromLocale, to: options.toLocale })
  });
  options.callback(res.ok ? await res.json() : []);   // same order as options.strings; [] when it failed
});
Server · routes/examples/ai-translation.php · sjs:III.3.server View on GitHub
// POST /api/translate — strings in, translated strings out (same order); nothing goes to SurveyJS
Route::post('/api/translate', function (Request $request) {
    abort_unless(config('surveyjs.ai.api_key'), 501, 'Set AI_API_KEY to enable translation');
    ['strings' => $strings, 'from' => $from, 'to' => $to] = $request->only(['strings', 'from', 'to']) + ['strings' => [], 'from' => '', 'to' => ''];

    $reply = Http::baseUrl(config('surveyjs.ai.base_url'))->withToken(config('surveyjs.ai.api_key'))->timeout(60)
        ->post('/chat/completions', [                                         // any OpenAI-compatible provider: your key, your choice
            'model' => config('surveyjs.ai.model'),
            'messages' => [
                ['role' => 'system', 'content' => "Translate each string from {$from} to {$to}. Return a JSON array in the same order."],
                ['role' => 'user', 'content' => json_encode(array_values($strings), JSON_UNESCAPED_UNICODE)],
            ],
        ])->throw();

    // Models sometimes wrap the array in prose or a code fence: take the array itself
    preg_match('/\[.*\]/s', (string) $reply->json('choices.0.message.content'), $match);
    $translated = json_decode($match[0] ?? 'null');
    abort_unless(is_array($translated) && count($translated) === count($strings), 502, 'The AI provider returned an unexpected answer');

    return response()->json($translated);                                    // what options.callback() takes
});

Definition: shared/definitions/creator-load-save.json