datocms-plugin-ai-translations 2.0.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -5
- package/dist/assets/index-CZF7YKl5.js +343 -0
- package/dist/index.html +1 -1
- package/docs/AI-Proxies.md +88 -0
- package/package.json +12 -14
- package/dist/assets/index-BFAwSDKK.js +0 -342
- package/docs/DeepL-Proxy-CLI.md +0 -195
package/README.md
CHANGED
|
@@ -159,7 +159,11 @@ export default {
|
|
|
159
159
|
};
|
|
160
160
|
if (req.method === 'OPTIONS') return new Response(null, { headers: cors });
|
|
161
161
|
|
|
162
|
-
const
|
|
162
|
+
const url = new URL(req.url);
|
|
163
|
+
const isFree = url.searchParams.get('endpoint') === 'free';
|
|
164
|
+
const baseUrl = isFree ? 'https://api-free.deepl.com' : 'https://api.deepl.com';
|
|
165
|
+
const upstream = new URL('/v2/translate', baseUrl);
|
|
166
|
+
|
|
163
167
|
const body = await req.text(); // passthrough JSON body
|
|
164
168
|
|
|
165
169
|
const resp = await fetch(upstream, {
|
|
@@ -195,7 +199,10 @@ export default async function handler(req, res) {
|
|
|
195
199
|
res.setHeader('Access-Control-Allow-Headers', '*');
|
|
196
200
|
if (req.method === 'OPTIONS') return res.status(204).end();
|
|
197
201
|
|
|
198
|
-
const
|
|
202
|
+
const isFree = req.query.endpoint === 'free';
|
|
203
|
+
const baseUrl = isFree ? 'https://api-free.deepl.com' : 'https://api.deepl.com';
|
|
204
|
+
const upstream = `${baseUrl}/v2/translate`;
|
|
205
|
+
|
|
199
206
|
const r = await fetch(upstream, {
|
|
200
207
|
method: 'POST',
|
|
201
208
|
headers: {
|
|
@@ -229,7 +236,11 @@ export const handler = async (event) => {
|
|
|
229
236
|
if (event.httpMethod === 'OPTIONS') {
|
|
230
237
|
return { statusCode: 204, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*' } };
|
|
231
238
|
}
|
|
232
|
-
|
|
239
|
+
|
|
240
|
+
const isFree = event.queryStringParameters?.endpoint === 'free';
|
|
241
|
+
const baseUrl = isFree ? 'https://api-free.deepl.com' : 'https://api.deepl.com';
|
|
242
|
+
const upstream = `${baseUrl}/v2/translate`;
|
|
243
|
+
|
|
233
244
|
const r = await fetch(upstream, {
|
|
234
245
|
method: 'POST',
|
|
235
246
|
headers: {
|
|
@@ -267,8 +278,95 @@ Endpoint selection (Free vs Pro)
|
|
|
267
278
|
|
|
268
279
|
That’s it — once your proxy passes the test, DeepL translations (including large Structured Text fields) will work end‑to‑end.
|
|
269
280
|
|
|
270
|
-
|
|
271
|
-
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
## DeepL Glossaries
|
|
284
|
+
|
|
285
|
+
The plugin supports DeepL glossaries to enforce preferred terminology. You can set a default glossary ID and/or map specific language pairs to specific glossary IDs. This works for all field types, including Structured Text.
|
|
286
|
+
|
|
287
|
+
### Requirements
|
|
288
|
+
|
|
289
|
+
- A DeepL API key with access to Glossaries. Check your DeepL account/plan capabilities.
|
|
290
|
+
- The same proxy described above; translations with a glossary still call `POST <proxy>/v2/translate` with an extra `glossary_id` in the JSON body.
|
|
291
|
+
|
|
292
|
+
### Configure in the Plugin
|
|
293
|
+
|
|
294
|
+
1. Open Settings → vendor “DeepL”.
|
|
295
|
+
2. Set “Proxy URL” and verify it via “Test proxy”.
|
|
296
|
+
3. Expand “Advanced settings”.
|
|
297
|
+
4. Optional: set “Default glossary ID” (e.g., `gls-abc123`).
|
|
298
|
+
5. Optional: fill in “Glossaries by language pair” with one mapping per line.
|
|
299
|
+
|
|
300
|
+
You can use either DatoCMS locales (e.g., `en-US`, `pt-BR`) or DeepL codes (e.g., `EN`, `PT-BR`). The plugin normalizes both to DeepL codes internally.
|
|
301
|
+
|
|
302
|
+
### Mapping Syntax
|
|
303
|
+
|
|
304
|
+
One entry per line. Supported forms:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
EN->DE=gls-abc123
|
|
308
|
+
en-US->pt-BR=gls-xyz789
|
|
309
|
+
fr→it gls-123 # alt arrow and delimiter
|
|
310
|
+
*->pt-BR=gls-777 # wildcard: any source to target
|
|
311
|
+
EN->*=gls-555 # wildcard: source to any target
|
|
312
|
+
pt-BR=gls-777 # shorthand for *->pt-BR
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Delimiters: `=`, `:`, or whitespace. Arrows: `->`, `→`, `⇒` (all treated the same). Case is ignored.
|
|
316
|
+
|
|
317
|
+
### Resolution Order
|
|
318
|
+
|
|
319
|
+
When translating from `fromLocale` → `toLocale`, the plugin picks a glossary ID using this precedence:
|
|
320
|
+
|
|
321
|
+
1. Exact pair match by DeepL codes (e.g., `EN:PT-BR`).
|
|
322
|
+
2. Exact pair match by your raw locales (e.g., `en-US:pt-BR`).
|
|
323
|
+
3. Wildcard any→target (e.g., `*:PT-BR` or `*:pt-BR`).
|
|
324
|
+
4. Wildcard source→any (e.g., `EN:*` or `en-US:*`).
|
|
325
|
+
5. Default glossary ID (if set).
|
|
326
|
+
6. Otherwise, no glossary is used.
|
|
327
|
+
|
|
328
|
+
If DeepL returns a glossary mismatch (e.g., glossary languages don’t match the current pair) or a missing glossary, the plugin automatically retries the same request once without a glossary so your translation continues. A brief hint is surfaced in the UI logs.
|
|
329
|
+
|
|
330
|
+
### Finding or Creating a Glossary ID
|
|
331
|
+
|
|
332
|
+
The plugin only needs the `glossary_id` string. You can create and list glossaries with the DeepL API from your own machine or server. Examples with cURL:
|
|
333
|
+
|
|
334
|
+
List glossaries
|
|
335
|
+
```
|
|
336
|
+
curl -H "Authorization: DeepL-Auth-Key $DEEPL_AUTH_KEY" \
|
|
337
|
+
https://api.deepl.com/v2/glossaries
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Create a small glossary inline (tab-separated entries)
|
|
341
|
+
```
|
|
342
|
+
curl -X POST https://api.deepl.com/v2/glossaries \
|
|
343
|
+
-H "Authorization: DeepL-Auth-Key $DEEPL_AUTH_KEY" \
|
|
344
|
+
-H "Content-Type: application/json" \
|
|
345
|
+
-d '{
|
|
346
|
+
"name": "Marketing-EN-DE",
|
|
347
|
+
"source_lang": "EN",
|
|
348
|
+
"target_lang": "DE",
|
|
349
|
+
"entries_format": "tsv",
|
|
350
|
+
"entries": "CTA\tCall-to-Action\nlead magnet\tLeadmagnet"
|
|
351
|
+
}'
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Note: If your account uses the Free endpoint, replace the host with `https://api-free.deepl.com`.
|
|
355
|
+
|
|
356
|
+
You do not need to expose `/v2/glossaries` through your proxy for the plugin to work — it only calls `/v2/translate`. Manage glossaries from your server/CLI, then paste the resulting IDs into the plugin settings.
|
|
357
|
+
|
|
358
|
+
### Tips and Limitations
|
|
359
|
+
|
|
360
|
+
- Glossaries apply only to the DeepL vendor. OpenAI/Gemini/Anthropic do not use glossaries.
|
|
361
|
+
- The plugin preserves placeholders and HTML tags automatically (`notranslate`, `ph`, etc.). Glossaries will not alter those tokens.
|
|
362
|
+
- If you use DeepL “formality”, it is sent only for targets that support it; otherwise omitted.
|
|
363
|
+
- A wrong Pro/Free endpoint for your key will still raise the “Wrong endpoint” hint shown in settings and translation errors.
|
|
364
|
+
|
|
365
|
+
### Quick Sanity Test
|
|
366
|
+
|
|
367
|
+
1. Create a small EN→DE glossary with an obvious term (e.g., “CTA” → “Call‑to‑Action”).
|
|
368
|
+
2. In Settings → DeepL, paste the glossary ID into either Default or the `EN->DE=...` mapping.
|
|
369
|
+
3. Translate a field from EN to DE containing “CTA”. The resulting German text should include your glossary translation.
|
|
272
370
|
|
|
273
371
|
## Migration Notes
|
|
274
372
|
|