@hkonda/loco-translate 1.0.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 +284 -0
- package/bin/loco.js +5 -0
- package/dist/assets/index-CGo6e-bA.js +59 -0
- package/dist/assets/index-DBcQDZ75.css +1 -0
- package/dist/index.html +13 -0
- package/dist-server/app.d.ts +3 -0
- package/dist-server/app.d.ts.map +1 -0
- package/dist-server/app.js +154 -0
- package/dist-server/app.js.map +1 -0
- package/dist-server/config.d.ts +16 -0
- package/dist-server/config.d.ts.map +1 -0
- package/dist-server/config.js +41 -0
- package/dist-server/config.js.map +1 -0
- package/dist-server/db/index.d.ts +8 -0
- package/dist-server/db/index.d.ts.map +1 -0
- package/dist-server/db/index.js +28 -0
- package/dist-server/db/index.js.map +1 -0
- package/dist-server/db/schema.d.ts +851 -0
- package/dist-server/db/schema.d.ts.map +1 -0
- package/dist-server/db/schema.js +65 -0
- package/dist-server/db/schema.js.map +1 -0
- package/dist-server/db/seed.d.ts +14 -0
- package/dist-server/db/seed.d.ts.map +1 -0
- package/dist-server/db/seed.js +229 -0
- package/dist-server/db/seed.js.map +1 -0
- package/dist-server/index.d.ts +2 -0
- package/dist-server/index.d.ts.map +1 -0
- package/dist-server/index.js +31 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/routes/ai-jobs.d.ts +5 -0
- package/dist-server/routes/ai-jobs.d.ts.map +1 -0
- package/dist-server/routes/ai-jobs.js +141 -0
- package/dist-server/routes/ai-jobs.js.map +1 -0
- package/dist-server/routes/backup.d.ts +5 -0
- package/dist-server/routes/backup.d.ts.map +1 -0
- package/dist-server/routes/backup.js +125 -0
- package/dist-server/routes/backup.js.map +1 -0
- package/dist-server/routes/chrome-extension.d.ts +5 -0
- package/dist-server/routes/chrome-extension.d.ts.map +1 -0
- package/dist-server/routes/chrome-extension.js +140 -0
- package/dist-server/routes/chrome-extension.js.map +1 -0
- package/dist-server/routes/export.d.ts +5 -0
- package/dist-server/routes/export.d.ts.map +1 -0
- package/dist-server/routes/export.js +95 -0
- package/dist-server/routes/export.js.map +1 -0
- package/dist-server/routes/languages.d.ts +5 -0
- package/dist-server/routes/languages.d.ts.map +1 -0
- package/dist-server/routes/languages.js +36 -0
- package/dist-server/routes/languages.js.map +1 -0
- package/dist-server/routes/project.d.ts +5 -0
- package/dist-server/routes/project.d.ts.map +1 -0
- package/dist-server/routes/project.js +151 -0
- package/dist-server/routes/project.js.map +1 -0
- package/dist-server/routes/prompts.d.ts +5 -0
- package/dist-server/routes/prompts.d.ts.map +1 -0
- package/dist-server/routes/prompts.js +90 -0
- package/dist-server/routes/prompts.js.map +1 -0
- package/dist-server/routes/screenshots.d.ts +5 -0
- package/dist-server/routes/screenshots.d.ts.map +1 -0
- package/dist-server/routes/screenshots.js +71 -0
- package/dist-server/routes/screenshots.js.map +1 -0
- package/dist-server/routes/textnodes.d.ts +5 -0
- package/dist-server/routes/textnodes.d.ts.map +1 -0
- package/dist-server/routes/textnodes.js +318 -0
- package/dist-server/routes/textnodes.js.map +1 -0
- package/dist-server/routes/translations.d.ts +5 -0
- package/dist-server/routes/translations.d.ts.map +1 -0
- package/dist-server/routes/translations.js +224 -0
- package/dist-server/routes/translations.js.map +1 -0
- package/dist-server/scripts/backup.d.ts +2 -0
- package/dist-server/scripts/backup.d.ts.map +1 -0
- package/dist-server/scripts/backup.js +26 -0
- package/dist-server/scripts/backup.js.map +1 -0
- package/dist-server/services/ai-translation.d.ts +21 -0
- package/dist-server/services/ai-translation.d.ts.map +1 -0
- package/dist-server/services/ai-translation.js +137 -0
- package/dist-server/services/ai-translation.js.map +1 -0
- package/dist-server/services/job-manager.d.ts +67 -0
- package/dist-server/services/job-manager.d.ts.map +1 -0
- package/dist-server/services/job-manager.js +159 -0
- package/dist-server/services/job-manager.js.map +1 -0
- package/dist-server/services/slot-pattern.d.ts +16 -0
- package/dist-server/services/slot-pattern.d.ts.map +1 -0
- package/dist-server/services/slot-pattern.js +68 -0
- package/dist-server/services/slot-pattern.js.map +1 -0
- package/dist-server/utils/network.d.ts +2 -0
- package/dist-server/utils/network.d.ts.map +1 -0
- package/dist-server/utils/network.js +16 -0
- package/dist-server/utils/network.js.map +1 -0
- package/package.json +47 -0
- package/public/loco.js +2386 -0
- package/public/loco.min.js +4 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { rawDb } from '../db/index.js';
|
|
2
|
+
export default async function promptsRoutes(app, opts) {
|
|
3
|
+
app.get('/api/prompts', {
|
|
4
|
+
schema: {
|
|
5
|
+
tags: ['Prompts'],
|
|
6
|
+
summary: 'List all prompt templates',
|
|
7
|
+
response: {
|
|
8
|
+
200: {
|
|
9
|
+
type: 'array',
|
|
10
|
+
items: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
id: { type: 'string' },
|
|
14
|
+
project_id: { type: 'number' },
|
|
15
|
+
name: { type: 'string' },
|
|
16
|
+
prompt: { type: 'string' },
|
|
17
|
+
system_message: { type: 'string' },
|
|
18
|
+
version: { type: 'number' },
|
|
19
|
+
created_at: { type: 'string' },
|
|
20
|
+
updated_at: { type: 'string' },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}, () => {
|
|
27
|
+
const { project } = opts;
|
|
28
|
+
return rawDb.prepare('SELECT * FROM prompt_templates WHERE project_id = ? ORDER BY updated_at DESC').all(project.id);
|
|
29
|
+
});
|
|
30
|
+
app.post('/api/prompts', {
|
|
31
|
+
schema: {
|
|
32
|
+
tags: ['Prompts'],
|
|
33
|
+
summary: 'Create or update a prompt template',
|
|
34
|
+
body: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
id: { type: 'string' },
|
|
38
|
+
name: { type: 'string' },
|
|
39
|
+
prompt: { type: 'string' },
|
|
40
|
+
system_message: { type: 'string' },
|
|
41
|
+
},
|
|
42
|
+
required: ['name', 'prompt'],
|
|
43
|
+
},
|
|
44
|
+
response: {
|
|
45
|
+
200: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
ok: { type: 'boolean' },
|
|
49
|
+
error: { type: 'string' },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}, (req) => {
|
|
55
|
+
const { project } = opts;
|
|
56
|
+
const { id, name, prompt, system_message } = req.body;
|
|
57
|
+
if (!name || !prompt)
|
|
58
|
+
return { error: 'name and prompt are required' };
|
|
59
|
+
const existing = id ? rawDb.prepare('SELECT * FROM prompt_templates WHERE id = ? AND project_id = ?').get(id, project.id) : null;
|
|
60
|
+
if (existing) {
|
|
61
|
+
rawDb.prepare(`UPDATE prompt_templates SET name = ?, prompt = ?, system_message = ?, version = version + 1, updated_at = datetime('now') WHERE id = ? AND project_id = ?`)
|
|
62
|
+
.run(name, prompt, system_message || '', id, project.id);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const newId = id || `prompt_${Date.now()}`;
|
|
66
|
+
rawDb.prepare('INSERT INTO prompt_templates (id, project_id, name, prompt, system_message) VALUES (?, ?, ?, ?, ?)')
|
|
67
|
+
.run(newId, project.id, name, prompt, system_message || '');
|
|
68
|
+
}
|
|
69
|
+
return { ok: true };
|
|
70
|
+
});
|
|
71
|
+
app.delete('/api/prompts/:id', {
|
|
72
|
+
schema: {
|
|
73
|
+
tags: ['Prompts'],
|
|
74
|
+
summary: 'Delete a prompt template',
|
|
75
|
+
params: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: { id: { type: 'string' } },
|
|
78
|
+
required: ['id'],
|
|
79
|
+
},
|
|
80
|
+
response: {
|
|
81
|
+
200: { type: 'object', properties: { ok: { type: 'boolean' } } },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
}, (req) => {
|
|
85
|
+
const { project } = opts;
|
|
86
|
+
rawDb.prepare('DELETE FROM prompt_templates WHERE id = ? AND project_id = ?').run(req.params.id, project.id);
|
|
87
|
+
return { ok: true };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../server/routes/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshots.d.ts","sourceRoot":"","sources":["../../server/routes/screenshots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,wBAA8B,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,iBAiE3F"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { rawDb } from '../db/index.js';
|
|
2
|
+
import { LIMITS } from '../config.js';
|
|
3
|
+
export default async function screenshotsRoutes(app, opts) {
|
|
4
|
+
app.post('/api/screenshots', {
|
|
5
|
+
schema: {
|
|
6
|
+
tags: ['Screenshots'],
|
|
7
|
+
summary: 'Store a page screenshot',
|
|
8
|
+
body: {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
url: { type: 'string' },
|
|
12
|
+
screenshot: { type: 'string' },
|
|
13
|
+
},
|
|
14
|
+
required: ['url', 'screenshot'],
|
|
15
|
+
},
|
|
16
|
+
response: {
|
|
17
|
+
200: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
ok: { type: 'boolean' },
|
|
21
|
+
error: { type: 'string' },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}, (req) => {
|
|
27
|
+
const { project } = opts;
|
|
28
|
+
const { url, screenshot } = req.body;
|
|
29
|
+
if (!url || !screenshot || typeof screenshot !== 'string')
|
|
30
|
+
return { error: 'Missing url or screenshot' };
|
|
31
|
+
if (screenshot.length > LIMITS.MAX_SCREENSHOT_SIZE)
|
|
32
|
+
return { error: 'Screenshot too large' };
|
|
33
|
+
rawDb.prepare(`
|
|
34
|
+
INSERT INTO page_screenshots (project_id, url, screenshot)
|
|
35
|
+
VALUES (?, ?, ?)
|
|
36
|
+
ON CONFLICT(project_id, url) DO UPDATE SET screenshot = excluded.screenshot, captured_at = datetime('now')
|
|
37
|
+
`).run(project.id, url.substring(0, LIMITS.MAX_URL_LENGTH), screenshot);
|
|
38
|
+
return { ok: true };
|
|
39
|
+
});
|
|
40
|
+
app.get('/api/screenshots', {
|
|
41
|
+
schema: {
|
|
42
|
+
tags: ['Screenshots'],
|
|
43
|
+
summary: 'Get a page screenshot by URL',
|
|
44
|
+
querystring: {
|
|
45
|
+
type: 'object',
|
|
46
|
+
properties: { url: { type: 'string' } },
|
|
47
|
+
required: ['url'],
|
|
48
|
+
},
|
|
49
|
+
response: {
|
|
50
|
+
200: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
screenshot: { type: ['string', 'null'] },
|
|
54
|
+
captured_at: { type: 'string' },
|
|
55
|
+
error: { type: 'string' },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
}, (req) => {
|
|
61
|
+
const { project } = opts;
|
|
62
|
+
const { url } = req.query;
|
|
63
|
+
if (!url)
|
|
64
|
+
return { error: 'Missing url' };
|
|
65
|
+
const row = rawDb.prepare('SELECT screenshot, captured_at FROM page_screenshots WHERE project_id = ? AND url = ?').get(project.id, url);
|
|
66
|
+
if (!row)
|
|
67
|
+
return { screenshot: null };
|
|
68
|
+
return row;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=screenshots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshots.js","sourceRoot":"","sources":["../../server/routes/screenshots.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textnodes.d.ts","sourceRoot":"","sources":["../../server/routes/textnodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,wBAA8B,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,iBAuUzF"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { rawDb } from '../db/index.js';
|
|
2
|
+
import { buildSlotRegex, isStaticSlotMatch } from '../services/slot-pattern.js';
|
|
3
|
+
import { LIMITS } from '../config.js';
|
|
4
|
+
export default async function textnodesRoutes(app, opts) {
|
|
5
|
+
// ── Register text nodes (CDN discovers text on pages)
|
|
6
|
+
app.post('/api/textnodes', {
|
|
7
|
+
schema: {
|
|
8
|
+
tags: ['Text Nodes'],
|
|
9
|
+
summary: 'Register discovered text nodes from web pages',
|
|
10
|
+
body: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
keys: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
items: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
key: { type: 'string' },
|
|
19
|
+
context: { type: 'string' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
url: { type: 'string' },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
response: {
|
|
27
|
+
200: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
ok: { type: 'boolean' },
|
|
31
|
+
registered: { type: 'number' },
|
|
32
|
+
keyMap: { type: 'object', additionalProperties: { type: 'string' } },
|
|
33
|
+
error: { type: 'string' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}, (req) => {
|
|
39
|
+
const { project } = opts;
|
|
40
|
+
const { keys, url, key, context, status } = req.body;
|
|
41
|
+
// Dashboard single-key add: { key, context?, status? }
|
|
42
|
+
if (typeof key === 'string' && key.trim()) {
|
|
43
|
+
const ctx = (context || '').trim();
|
|
44
|
+
const st = ['pending', 'approved', 'trash'].includes(status) ? status : 'pending';
|
|
45
|
+
rawDb.prepare(`
|
|
46
|
+
INSERT INTO textnodes (project_id, key, context, status)
|
|
47
|
+
VALUES (?, ?, ?, ?)
|
|
48
|
+
ON CONFLICT(project_id, key, context) DO NOTHING
|
|
49
|
+
`).run(project.id, key.trim(), ctx, st);
|
|
50
|
+
return { ok: true, registered: 1, keyMap: {} };
|
|
51
|
+
}
|
|
52
|
+
if (!Array.isArray(keys))
|
|
53
|
+
return { error: 'keys must be an array' };
|
|
54
|
+
const pageUrl = (typeof url === 'string' ? url : '').substring(0, LIMITS.MAX_URL_LENGTH);
|
|
55
|
+
// Load explicitly-edited pattern keys
|
|
56
|
+
const patternRows = rawDb.prepare("SELECT key FROM textnodes WHERE project_id = ? AND (key LIKE '%{{text:%' OR key LIKE '%{{number:%' OR key LIKE '%{{decimal:%' OR key LIKE '%{{date:%') AND var_slots IS NOT NULL AND var_slots != '[]'").all(project.id);
|
|
57
|
+
const patternMatchers = patternRows.map(row => {
|
|
58
|
+
const { regex, specificity } = buildSlotRegex(row.key);
|
|
59
|
+
return { pattern: row.key, regex, specificity };
|
|
60
|
+
});
|
|
61
|
+
patternMatchers.sort((a, b) => b.specificity - a.specificity);
|
|
62
|
+
const keyMap = {};
|
|
63
|
+
const toInsert = [];
|
|
64
|
+
for (const entry of keys) {
|
|
65
|
+
if (!entry.key || typeof entry.key !== 'string')
|
|
66
|
+
continue;
|
|
67
|
+
const match = patternMatchers.find(m => m.regex.test(entry.key));
|
|
68
|
+
if (match && match.pattern !== entry.key && !isStaticSlotMatch(entry.key, match.pattern)) {
|
|
69
|
+
keyMap[entry.key] = match.pattern;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
toInsert.push(entry);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const upsert = rawDb.prepare(`
|
|
76
|
+
INSERT INTO textnodes (project_id, key, context, url)
|
|
77
|
+
VALUES (?, ?, ?, ?)
|
|
78
|
+
ON CONFLICT(project_id, key, context) DO UPDATE SET url = excluded.url
|
|
79
|
+
`);
|
|
80
|
+
let registered = 0;
|
|
81
|
+
rawDb.transaction((entries) => {
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const ctx = entry.context || '';
|
|
84
|
+
const exists = rawDb.prepare('SELECT 1 FROM textnodes WHERE project_id = ? AND key = ? AND context = ? LIMIT 1').get(project.id, entry.key, ctx);
|
|
85
|
+
if (exists) {
|
|
86
|
+
upsert.run(project.id, entry.key, ctx, pageUrl);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
upsert.run(project.id, entry.key, ctx, pageUrl);
|
|
90
|
+
registered++;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
})(toInsert);
|
|
94
|
+
return { ok: true, registered, keyMap };
|
|
95
|
+
});
|
|
96
|
+
// ── Bulk status change
|
|
97
|
+
app.patch('/api/textnodes/status', {
|
|
98
|
+
schema: {
|
|
99
|
+
tags: ['Text Nodes'],
|
|
100
|
+
summary: 'Bulk status change (move between buckets)',
|
|
101
|
+
body: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
properties: {
|
|
104
|
+
ids: { type: 'array', items: { type: 'number' } },
|
|
105
|
+
status: { type: 'string', enum: ['pending', 'approved', 'trash'] },
|
|
106
|
+
},
|
|
107
|
+
required: ['ids', 'status'],
|
|
108
|
+
},
|
|
109
|
+
response: {
|
|
110
|
+
200: {
|
|
111
|
+
type: 'object',
|
|
112
|
+
properties: { ok: { type: 'boolean' }, updated: { type: 'number' } },
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
}, (req) => {
|
|
117
|
+
const { project } = opts;
|
|
118
|
+
const { ids, status } = req.body;
|
|
119
|
+
if (!Array.isArray(ids) || !['pending', 'approved', 'trash'].includes(status)) {
|
|
120
|
+
return { error: 'Invalid ids or status' };
|
|
121
|
+
}
|
|
122
|
+
const update = rawDb.prepare('UPDATE textnodes SET status = ? WHERE id = ? AND project_id = ?');
|
|
123
|
+
rawDb.transaction((ids) => {
|
|
124
|
+
for (const id of ids)
|
|
125
|
+
update.run(status, id, project.id);
|
|
126
|
+
})(ids);
|
|
127
|
+
return { ok: true, updated: ids.length };
|
|
128
|
+
});
|
|
129
|
+
// ── Get untranslated approved key IDs
|
|
130
|
+
app.get('/api/textnodes/untranslated-ids', {
|
|
131
|
+
schema: {
|
|
132
|
+
tags: ['Text Nodes'],
|
|
133
|
+
summary: 'Get untranslated approved key IDs for a language',
|
|
134
|
+
querystring: {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: { lang: { type: 'string' } },
|
|
137
|
+
},
|
|
138
|
+
response: {
|
|
139
|
+
200: {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: {
|
|
142
|
+
ids: { type: 'array', items: { type: 'number' } },
|
|
143
|
+
total: { type: 'number' },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
}, (req) => {
|
|
149
|
+
const { project } = opts;
|
|
150
|
+
const targetLang = req.query.lang || 'zh-Hans';
|
|
151
|
+
const rows = rawDb.prepare(`
|
|
152
|
+
SELECT k.id FROM textnodes k
|
|
153
|
+
LEFT JOIN translations t
|
|
154
|
+
ON t.project_id = k.project_id AND t.key = k.key AND t.context = k.context AND t.lang = ?
|
|
155
|
+
WHERE k.project_id = ? AND k.status = 'approved'
|
|
156
|
+
AND (t.value IS NULL OR t.value = '')
|
|
157
|
+
ORDER BY k.id
|
|
158
|
+
`).all(targetLang, project.id);
|
|
159
|
+
return { ids: rows.map(r => r.id), total: rows.length };
|
|
160
|
+
});
|
|
161
|
+
// ── Bulk delete textnodes
|
|
162
|
+
app.post('/api/textnodes/bulk-delete', {
|
|
163
|
+
schema: {
|
|
164
|
+
tags: ['Text Nodes'],
|
|
165
|
+
summary: 'Bulk delete text nodes and their translations',
|
|
166
|
+
body: {
|
|
167
|
+
type: 'object',
|
|
168
|
+
properties: {
|
|
169
|
+
ids: { type: 'array', items: { type: 'number' }, maxItems: 200 },
|
|
170
|
+
},
|
|
171
|
+
required: ['ids'],
|
|
172
|
+
},
|
|
173
|
+
response: {
|
|
174
|
+
200: { type: 'object', properties: { ok: { type: 'boolean' }, deleted: { type: 'number' } } },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
}, (req) => {
|
|
178
|
+
const { project } = opts;
|
|
179
|
+
const { ids } = req.body;
|
|
180
|
+
if (!Array.isArray(ids) || ids.length === 0)
|
|
181
|
+
return { ok: true, deleted: 0 };
|
|
182
|
+
const selectRow = rawDb.prepare('SELECT id, key, context FROM textnodes WHERE id = ? AND project_id = ?');
|
|
183
|
+
const delTranslations = rawDb.prepare('DELETE FROM translations WHERE project_id = ? AND key = ? AND context = ?');
|
|
184
|
+
const delTextnode = rawDb.prepare('DELETE FROM textnodes WHERE id = ? AND project_id = ?');
|
|
185
|
+
let deleted = 0;
|
|
186
|
+
rawDb.transaction(() => {
|
|
187
|
+
for (const id of ids) {
|
|
188
|
+
const row = selectRow.get(id, project.id);
|
|
189
|
+
if (!row)
|
|
190
|
+
continue;
|
|
191
|
+
delTranslations.run(project.id, row.key, row.context);
|
|
192
|
+
delTextnode.run(row.id, project.id);
|
|
193
|
+
deleted++;
|
|
194
|
+
}
|
|
195
|
+
})();
|
|
196
|
+
return { ok: true, deleted };
|
|
197
|
+
});
|
|
198
|
+
// ── Delete textnode
|
|
199
|
+
app.delete('/api/textnodes/:id', {
|
|
200
|
+
schema: {
|
|
201
|
+
tags: ['Text Nodes'],
|
|
202
|
+
summary: 'Delete a text node and its translations',
|
|
203
|
+
params: {
|
|
204
|
+
type: 'object',
|
|
205
|
+
properties: { id: { type: 'string' } },
|
|
206
|
+
required: ['id'],
|
|
207
|
+
},
|
|
208
|
+
response: {
|
|
209
|
+
200: {
|
|
210
|
+
type: 'object',
|
|
211
|
+
properties: { ok: { type: 'boolean' }, deleted: { type: 'number' } },
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
}, (req) => {
|
|
216
|
+
const { project } = opts;
|
|
217
|
+
return deleteTextnodeAndTranslations(req.params.id, project.id);
|
|
218
|
+
});
|
|
219
|
+
// ── Update phrase key + var slots
|
|
220
|
+
app.patch('/api/phrases/:id', {
|
|
221
|
+
schema: {
|
|
222
|
+
tags: ['Text Nodes'],
|
|
223
|
+
summary: 'Update phrase key and variable slots',
|
|
224
|
+
params: {
|
|
225
|
+
type: 'object',
|
|
226
|
+
properties: { id: { type: 'string' } },
|
|
227
|
+
required: ['id'],
|
|
228
|
+
},
|
|
229
|
+
body: {
|
|
230
|
+
type: 'object',
|
|
231
|
+
properties: {
|
|
232
|
+
key: { type: 'string' },
|
|
233
|
+
varSlots: { type: 'array', items: { type: 'object', additionalProperties: true } },
|
|
234
|
+
},
|
|
235
|
+
required: ['key'],
|
|
236
|
+
},
|
|
237
|
+
response: {
|
|
238
|
+
200: { type: 'object', properties: { ok: { type: 'boolean' }, deleted: { type: 'number' } } },
|
|
239
|
+
400: { type: 'object', properties: { error: { type: 'string' } } },
|
|
240
|
+
409: { type: 'object', properties: { error: { type: 'string' }, existingId: { type: 'number' } } },
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
}, (req, reply) => {
|
|
244
|
+
const { project } = opts;
|
|
245
|
+
const id = parseInt(req.params.id, 10);
|
|
246
|
+
const { key, varSlots } = req.body || {};
|
|
247
|
+
if (typeof key !== 'string' || !key.trim()) {
|
|
248
|
+
return reply.code(400).send({ error: 'key is required' });
|
|
249
|
+
}
|
|
250
|
+
const trimmedKey = key.trim();
|
|
251
|
+
const slotsJson = JSON.stringify(Array.isArray(varSlots) ? varSlots : []);
|
|
252
|
+
const existing = rawDb.prepare('SELECT id FROM textnodes WHERE project_id = ? AND key = ? AND id != ?').get(project.id, trimmedKey, id);
|
|
253
|
+
if (existing) {
|
|
254
|
+
return reply.code(409).send({ error: 'A phrase with this key already exists', existingId: existing.id });
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const result = rawDb.prepare('UPDATE textnodes SET key = ?, var_slots = ? WHERE id = ? AND project_id = ?').run(trimmedKey, slotsJson, id, project.id);
|
|
258
|
+
if (result.changes === 0)
|
|
259
|
+
return reply.code(404).send({ error: 'Not found' });
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
req.log.error(e);
|
|
263
|
+
return reply.code(500).send({ error: 'Failed to update phrase', detail: e.message });
|
|
264
|
+
}
|
|
265
|
+
// Delete concrete keys matching the placeholder pattern
|
|
266
|
+
if (/\{\{(?:text|number|decimal|date):/.test(trimmedKey)) {
|
|
267
|
+
const { regex: patternRegex } = buildSlotRegex(trimmedKey);
|
|
268
|
+
const likePattern = trimmedKey.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g, '%');
|
|
269
|
+
const candidates = rawDb.prepare("SELECT id, key, context FROM textnodes WHERE project_id = ? AND id != ? AND key LIKE ? AND key NOT LIKE '%{{text:%' AND key NOT LIKE '%{{number:%' AND key NOT LIKE '%{{decimal:%' AND key NOT LIKE '%{{date:%'").all(project.id, id, likePattern);
|
|
270
|
+
const similar = candidates.filter(r => patternRegex.test(r.key));
|
|
271
|
+
if (similar.length > 0) {
|
|
272
|
+
const delTranslations = rawDb.prepare('DELETE FROM translations WHERE project_id = ? AND key = ? AND context = ?');
|
|
273
|
+
const delTextnode = rawDb.prepare('DELETE FROM textnodes WHERE id = ?');
|
|
274
|
+
rawDb.transaction((rows) => {
|
|
275
|
+
for (const r of rows) {
|
|
276
|
+
delTranslations.run(project.id, r.key, r.context);
|
|
277
|
+
delTextnode.run(r.id);
|
|
278
|
+
}
|
|
279
|
+
})(similar);
|
|
280
|
+
}
|
|
281
|
+
return { ok: true, deleted: similar.length };
|
|
282
|
+
}
|
|
283
|
+
return { ok: true };
|
|
284
|
+
});
|
|
285
|
+
// ── Clear pending
|
|
286
|
+
app.post('/api/textnodes/clear-pending', {
|
|
287
|
+
schema: {
|
|
288
|
+
tags: ['Text Nodes'],
|
|
289
|
+
summary: 'Clear all pending text nodes',
|
|
290
|
+
response: {
|
|
291
|
+
200: { type: 'object', properties: { ok: { type: 'boolean' }, deleted: { type: 'number' } } },
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
}, () => {
|
|
295
|
+
const { project } = opts;
|
|
296
|
+
const rows = rawDb.prepare("SELECT id FROM textnodes WHERE project_id = ? AND status = 'pending'").all(project.id);
|
|
297
|
+
rawDb.transaction((ids) => {
|
|
298
|
+
for (const row of ids) {
|
|
299
|
+
deleteTextnodeAndTranslations(row.id, project.id);
|
|
300
|
+
}
|
|
301
|
+
})(rows);
|
|
302
|
+
return { ok: true, deleted: rows.length };
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
function deleteTextnodeAndTranslations(textnodeId, projectId) {
|
|
306
|
+
const row = rawDb.prepare('SELECT id, key, context FROM textnodes WHERE id = ? AND project_id = ?').get(textnodeId, projectId);
|
|
307
|
+
if (!row) {
|
|
308
|
+
return { ok: false, deleted: 0 };
|
|
309
|
+
}
|
|
310
|
+
const deleteTranslations = rawDb.prepare('DELETE FROM translations WHERE project_id = ? AND key = ? AND context = ?');
|
|
311
|
+
const deleteTextnode = rawDb.prepare('DELETE FROM textnodes WHERE id = ? AND project_id = ?');
|
|
312
|
+
const result = rawDb.transaction(() => {
|
|
313
|
+
deleteTranslations.run(projectId, row.key, row.context);
|
|
314
|
+
return deleteTextnode.run(row.id, projectId);
|
|
315
|
+
})();
|
|
316
|
+
return { ok: true, deleted: result.changes };
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=textnodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textnodes.js","sourceRoot":"","sources":["../../server/routes/textnodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../server/routes/translations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,wBAA8B,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,iBAsO5F"}
|