@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.
Files changed (92) hide show
  1. package/README.md +284 -0
  2. package/bin/loco.js +5 -0
  3. package/dist/assets/index-CGo6e-bA.js +59 -0
  4. package/dist/assets/index-DBcQDZ75.css +1 -0
  5. package/dist/index.html +13 -0
  6. package/dist-server/app.d.ts +3 -0
  7. package/dist-server/app.d.ts.map +1 -0
  8. package/dist-server/app.js +154 -0
  9. package/dist-server/app.js.map +1 -0
  10. package/dist-server/config.d.ts +16 -0
  11. package/dist-server/config.d.ts.map +1 -0
  12. package/dist-server/config.js +41 -0
  13. package/dist-server/config.js.map +1 -0
  14. package/dist-server/db/index.d.ts +8 -0
  15. package/dist-server/db/index.d.ts.map +1 -0
  16. package/dist-server/db/index.js +28 -0
  17. package/dist-server/db/index.js.map +1 -0
  18. package/dist-server/db/schema.d.ts +851 -0
  19. package/dist-server/db/schema.d.ts.map +1 -0
  20. package/dist-server/db/schema.js +65 -0
  21. package/dist-server/db/schema.js.map +1 -0
  22. package/dist-server/db/seed.d.ts +14 -0
  23. package/dist-server/db/seed.d.ts.map +1 -0
  24. package/dist-server/db/seed.js +229 -0
  25. package/dist-server/db/seed.js.map +1 -0
  26. package/dist-server/index.d.ts +2 -0
  27. package/dist-server/index.d.ts.map +1 -0
  28. package/dist-server/index.js +31 -0
  29. package/dist-server/index.js.map +1 -0
  30. package/dist-server/routes/ai-jobs.d.ts +5 -0
  31. package/dist-server/routes/ai-jobs.d.ts.map +1 -0
  32. package/dist-server/routes/ai-jobs.js +141 -0
  33. package/dist-server/routes/ai-jobs.js.map +1 -0
  34. package/dist-server/routes/backup.d.ts +5 -0
  35. package/dist-server/routes/backup.d.ts.map +1 -0
  36. package/dist-server/routes/backup.js +125 -0
  37. package/dist-server/routes/backup.js.map +1 -0
  38. package/dist-server/routes/chrome-extension.d.ts +5 -0
  39. package/dist-server/routes/chrome-extension.d.ts.map +1 -0
  40. package/dist-server/routes/chrome-extension.js +140 -0
  41. package/dist-server/routes/chrome-extension.js.map +1 -0
  42. package/dist-server/routes/export.d.ts +5 -0
  43. package/dist-server/routes/export.d.ts.map +1 -0
  44. package/dist-server/routes/export.js +95 -0
  45. package/dist-server/routes/export.js.map +1 -0
  46. package/dist-server/routes/languages.d.ts +5 -0
  47. package/dist-server/routes/languages.d.ts.map +1 -0
  48. package/dist-server/routes/languages.js +36 -0
  49. package/dist-server/routes/languages.js.map +1 -0
  50. package/dist-server/routes/project.d.ts +5 -0
  51. package/dist-server/routes/project.d.ts.map +1 -0
  52. package/dist-server/routes/project.js +151 -0
  53. package/dist-server/routes/project.js.map +1 -0
  54. package/dist-server/routes/prompts.d.ts +5 -0
  55. package/dist-server/routes/prompts.d.ts.map +1 -0
  56. package/dist-server/routes/prompts.js +90 -0
  57. package/dist-server/routes/prompts.js.map +1 -0
  58. package/dist-server/routes/screenshots.d.ts +5 -0
  59. package/dist-server/routes/screenshots.d.ts.map +1 -0
  60. package/dist-server/routes/screenshots.js +71 -0
  61. package/dist-server/routes/screenshots.js.map +1 -0
  62. package/dist-server/routes/textnodes.d.ts +5 -0
  63. package/dist-server/routes/textnodes.d.ts.map +1 -0
  64. package/dist-server/routes/textnodes.js +318 -0
  65. package/dist-server/routes/textnodes.js.map +1 -0
  66. package/dist-server/routes/translations.d.ts +5 -0
  67. package/dist-server/routes/translations.d.ts.map +1 -0
  68. package/dist-server/routes/translations.js +224 -0
  69. package/dist-server/routes/translations.js.map +1 -0
  70. package/dist-server/scripts/backup.d.ts +2 -0
  71. package/dist-server/scripts/backup.d.ts.map +1 -0
  72. package/dist-server/scripts/backup.js +26 -0
  73. package/dist-server/scripts/backup.js.map +1 -0
  74. package/dist-server/services/ai-translation.d.ts +21 -0
  75. package/dist-server/services/ai-translation.d.ts.map +1 -0
  76. package/dist-server/services/ai-translation.js +137 -0
  77. package/dist-server/services/ai-translation.js.map +1 -0
  78. package/dist-server/services/job-manager.d.ts +67 -0
  79. package/dist-server/services/job-manager.d.ts.map +1 -0
  80. package/dist-server/services/job-manager.js +159 -0
  81. package/dist-server/services/job-manager.js.map +1 -0
  82. package/dist-server/services/slot-pattern.d.ts +16 -0
  83. package/dist-server/services/slot-pattern.d.ts.map +1 -0
  84. package/dist-server/services/slot-pattern.js +68 -0
  85. package/dist-server/services/slot-pattern.js.map +1 -0
  86. package/dist-server/utils/network.d.ts +2 -0
  87. package/dist-server/utils/network.d.ts.map +1 -0
  88. package/dist-server/utils/network.js +16 -0
  89. package/dist-server/utils/network.js.map +1 -0
  90. package/package.json +47 -0
  91. package/public/loco.js +2386 -0
  92. 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,5 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export default function screenshotsRoutes(app: FastifyInstance, opts: {
3
+ project: any;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=screenshots.d.ts.map
@@ -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":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAoB,EAAE,IAAsB;IAE1F,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE;QAC3B,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,aAAa,CAAC;YACrB,OAAO,EAAE,yBAAyB;YAClC,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACvB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC/B;gBACD,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;aAChC;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;wBACvB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;aACF;SACF;KACF,EAAE,CAAC,GAAQ,EAAE,EAAE;QACd,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QACrC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,OAAO,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;QACzG,IAAI,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,mBAAmB;YAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;QAC7F,KAAK,CAAC,OAAO,CAAC;;;;KAIb,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,CAAC;QACxE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE;QAC1B,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,aAAa,CAAC;YACrB,OAAO,EAAE,8BAA8B;YACvC,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBACvC,QAAQ,EAAE,CAAC,KAAK,CAAC;aAClB;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;wBACxC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC/B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;aACF;SACF;KACF,EAAE,CAAC,GAAQ,EAAE,EAAE;QACd,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,uFAAuF,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAA4D,CAAC;QACnM,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export default function textnodesRoutes(app: FastifyInstance, opts: {
3
+ project: any;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=textnodes.d.ts.map
@@ -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,5 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export default function translationsRoutes(app: FastifyInstance, opts: {
3
+ project: any;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=translations.d.ts.map
@@ -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"}