Translate Text
One script reply has been approved by the moderators Verified

Creates a translation task via the Nextcloud OCS Task Processing API, polls until task completes, and returns the translated text.

Created by nextcloud 37 days ago Picked 1 time
Submitted by nextcloud Bun
Verified 37 days ago
1
import createClient, { type Middleware } from "openapi-fetch";
2

3
type Nextcloud = {
4
  baseUrl: string,
5
  userId: string,
6
  token: string
7
};
8

9
const TASK_TYPE_TRANSLATE = "core:text2text:translate";
10
const POLL_INTERVAL_MS = 1000;
11
const DEFAULT_POLL_TIMEOUT_MS = 600_000; // 10 minutes (ensure one cron job finished)
12

13
/**
14
 * Creates a translation task via the Nextcloud OCS Task Processing API,
15
 * polls until the task completes, and returns the translated text.
16
 */
17
export async function main(
18
  ncResource: Nextcloud,
19
  text: string,
20
  targetLanguage: string,
21
  originLanguage: string | null = null,
22
  model: string | null = null,
23
  timeout_ms: number = DEFAULT_POLL_TIMEOUT_MS,
24
  interval_ms: number = POLL_INTERVAL_MS,
25
) {
26
  const client = createClient({ baseUrl: ncResource.baseUrl }) as any;
27
  const authMiddleware: Middleware = {
28
    async onRequest({ request, options }) {
29
      request.headers.set("Authorization", `Basic ${btoa(ncResource.userId + ':' + ncResource.token)}`);
30
      return request;
31
    },
32
  };
33
  client.use(authMiddleware);
34

35
  const input: Record<string, string> = {
36
    input: text,
37
    target_language: targetLanguage,
38
  };
39
  if (originLanguage !== null && originLanguage !== "") {
40
    input.origin_language = originLanguage;
41
  }
42
  if (model !== null && model !== "") {
43
    input.model = model
44
  }
45

46
  // Schedule the translation task
47
  const { data: scheduleData, error: scheduleError } = await client.POST(
48
    "/ocs/v2.php/taskprocessing/schedule",
49
    {
50
      params: {
51
        header: {
52
          "OCS-APIRequest": true,
53
        },
54
        query: {
55
          format: "json",
56
        },
57
      },
58
      body: {
59
        type: TASK_TYPE_TRANSLATE,
60
        input,
61
        appId: "windmill",
62
      },
63
    },
64
  );
65

66
  if (scheduleError) {
67
    throw new Error(`Failed to schedule translation task: ${JSON.stringify(scheduleError)}`);
68
  }
69
  const taskId = scheduleData?.ocs?.data?.task?.id;
70

71
  // Polls every interval until timeout or a result happens
72
  const deadline = Date.now() + timeout_ms;
73
  while (Date.now() < deadline) {
74
    console.log("Polling task output")
75
    const { data: taskData, error: taskError } = await client.GET(
76
      "/ocs/v2.php/taskprocessing/task/{id}",
77
      {
78
        params: {
79
          header: {
80
            "OCS-APIRequest": true,
81
          },
82
          query: {
83
            format: "json",
84
          },
85
          path: {
86
            id: taskId,
87
          },
88
        },
89
      },
90
    );
91

92
    if (taskError) {
93
      throw new Error(`Failed to get task ${taskId}: ${JSON.stringify(taskError)}`);
94
    }
95
    const task = taskData.ocs?.data?.task;
96
    const status = task.status;
97

98
    if (status === "STATUS_SUCCESSFUL") {
99
      const output = task.output;
100
      if (output && typeof output.output === "string") {
101
        return { translatedText: output.output, taskId };
102
      }
103
      return { translatedText: output, taskId };
104
    }
105

106
    if (status === "STATUS_FAILED" || status === "STATUS_CANCELLED") {
107
      const msg = JSON.stringify(task);
108
      throw new Error(`Translation task failed: ${msg}`);
109
    }
110
    if (!["STATUS_SCHEDULED", "STATUS_RUNNING"].includes(status)) {
111
      const msg = JSON.stringify(task);
112
      throw new Error(`Translation task failed with unknown status: ${msg}`)
113
    }
114
    await new Promise((r) => setTimeout(r, interval_ms));
115
  }
116

117
  throw new Error(
118
    `Translation task did not complete within ${timeout_ms}ms (taskId: ${taskId})`,
119
  );
120
}
121