transduck 0.5.3 → 0.6.1
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/dist/backend.d.ts +1 -0
- package/dist/backend.js +6 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +65 -12
- package/dist/config.d.ts +2 -0
- package/dist/config.js +3 -0
- package/dist/handler.d.ts +2 -0
- package/dist/handler.js +79 -41
- package/dist/index.d.ts +17 -2
- package/dist/index.js +191 -92
- package/dist/providers/claude-api.d.ts +1 -0
- package/dist/providers/claude-api.js +11 -0
- package/dist/providers/claude-code.d.ts +1 -0
- package/dist/providers/claude-code.js +6 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/openai-provider.d.ts +1 -0
- package/dist/providers/openai-provider.js +17 -0
- package/dist/result.d.ts +19 -0
- package/dist/result.js +26 -0
- package/dist/shared-store.d.ts +18 -0
- package/dist/shared-store.js +126 -0
- package/package.json +8 -2
- package/src/backend.ts +10 -0
- package/src/cli.ts +65 -12
- package/src/config.ts +5 -0
- package/src/handler.ts +81 -54
- package/src/index.ts +277 -98
- package/src/providers/claude-api.ts +16 -0
- package/src/providers/claude-code.ts +10 -0
- package/src/providers/index.ts +6 -0
- package/src/providers/openai-provider.ts +24 -0
- package/src/result.ts +30 -0
- package/src/shared-store.ts +157 -0
- package/tests/ait.test.ts +152 -14
- package/tests/backend.test.ts +34 -1
- package/tests/cli.test.ts +33 -0
- package/tests/config.test.ts +54 -0
- package/tests/result.test.ts +62 -0
- package/tests/shared-store.test.ts +210 -0
package/dist/backend.d.ts
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { TransduckConfig } from './config.js';
|
|
5
5
|
export { buildMessages, buildPluralMessages } from './providers/prompts.js';
|
|
6
|
+
export declare function detectLanguage(text: string, config: TransduckConfig, _clientOverride?: any): Promise<string>;
|
|
6
7
|
export declare function translate(sourceText: string, sourceLang: string, targetLang: string, projectContext: string, stringContext: string | null, config: TransduckConfig, _clientOverride?: any): Promise<string>;
|
|
7
8
|
export declare function translatePlural(one: string, other: string, sourceLang: string, targetLang: string, projectContext: string, stringContext: string | null, config: TransduckConfig, _clientOverride?: any): Promise<Record<string, string>>;
|
package/dist/backend.js
CHANGED
|
@@ -20,6 +20,12 @@ function checkApiKey(config) {
|
|
|
20
20
|
`Or add it to your .env file.`);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
export async function detectLanguage(text, config, _clientOverride) {
|
|
24
|
+
if (!_clientOverride)
|
|
25
|
+
checkApiKey(config);
|
|
26
|
+
const provider = await getProvider(config);
|
|
27
|
+
return provider.detectLanguage(text, config, _clientOverride);
|
|
28
|
+
}
|
|
23
29
|
export async function translate(sourceText, sourceLang, targetLang, projectContext, stringContext, config, _clientOverride) {
|
|
24
30
|
if (!_clientOverride)
|
|
25
31
|
checkApiKey(config);
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
4
|
export interface InitOptions {
|
|
4
5
|
dir: string;
|
|
@@ -7,6 +8,7 @@ export interface InitOptions {
|
|
|
7
8
|
sourceLang: string;
|
|
8
9
|
targetLangs: string[];
|
|
9
10
|
provider?: number;
|
|
11
|
+
sharedUrl?: string;
|
|
10
12
|
}
|
|
11
13
|
export declare function runInit(opts: InitOptions): Promise<string>;
|
|
12
14
|
export interface TranslateOptions {
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
2
3
|
import { createHash } from 'crypto';
|
|
3
4
|
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
5
|
import { join, dirname } from 'path';
|
|
@@ -6,6 +7,7 @@ import { Command } from 'commander';
|
|
|
6
7
|
import { stringify as yamlStringify } from 'yaml';
|
|
7
8
|
import { loadConfig } from './config.js';
|
|
8
9
|
import { TranslationStore } from './storage.js';
|
|
10
|
+
import { SharedStore } from './shared-store.js';
|
|
9
11
|
import { translate as backendTranslate, translatePlural as backendTranslatePlural } from './backend.js';
|
|
10
12
|
import { validateTranslation, extractPlaceholders } from './validation.js';
|
|
11
13
|
import { getPluralCategory, interpolateVars } from './plural.js';
|
|
@@ -15,10 +17,14 @@ function hash(text) {
|
|
|
15
17
|
}
|
|
16
18
|
export async function runInit(opts) {
|
|
17
19
|
const providerChoice = opts.provider ?? 1;
|
|
20
|
+
const storage = { path: './translations.db' };
|
|
21
|
+
if (opts.sharedUrl) {
|
|
22
|
+
storage.shared_url = opts.sharedUrl;
|
|
23
|
+
}
|
|
18
24
|
const config = {
|
|
19
25
|
project: { name: opts.name, context: opts.context },
|
|
20
26
|
languages: { source: opts.sourceLang.toUpperCase(), targets: opts.targetLangs.map(l => l.toUpperCase()) },
|
|
21
|
-
storage
|
|
27
|
+
storage,
|
|
22
28
|
};
|
|
23
29
|
if (providerChoice === 2) {
|
|
24
30
|
config.backend = {
|
|
@@ -194,6 +200,17 @@ export async function runWarm(opts) {
|
|
|
194
200
|
const targetLangs = opts.langs.map(l => l.toUpperCase());
|
|
195
201
|
const store = new TranslationStore(cfg.storagePath);
|
|
196
202
|
await store.initialize();
|
|
203
|
+
let shared = null;
|
|
204
|
+
if (cfg.sharedUrl) {
|
|
205
|
+
try {
|
|
206
|
+
shared = new SharedStore(cfg.sharedUrl);
|
|
207
|
+
await shared.initialize();
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
console.warn(`[transduck] Could not connect to shared store: ${err.message}`);
|
|
211
|
+
shared = null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
197
214
|
const content = readFileSync(opts.filePath, 'utf-8');
|
|
198
215
|
let entries;
|
|
199
216
|
if (opts.filePath.endsWith('.json')) {
|
|
@@ -237,12 +254,15 @@ export async function runWarm(opts) {
|
|
|
237
254
|
break;
|
|
238
255
|
}
|
|
239
256
|
}
|
|
240
|
-
|
|
257
|
+
const pluralParams = {
|
|
241
258
|
sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
|
|
242
259
|
projectContextHash, stringContextHash, stringContext: entry.context ?? '',
|
|
243
260
|
pluralCategory: cat, translatedText: translatedText,
|
|
244
261
|
model: cfg.backendModel, status: allPresent ? 'translated' : 'failed',
|
|
245
|
-
}
|
|
262
|
+
};
|
|
263
|
+
await store.insertPlural(pluralParams);
|
|
264
|
+
if (shared)
|
|
265
|
+
await shared.insertPlural(pluralParams);
|
|
246
266
|
anyStored = true;
|
|
247
267
|
}
|
|
248
268
|
if (anyStored)
|
|
@@ -270,19 +290,25 @@ export async function runWarm(opts) {
|
|
|
270
290
|
try {
|
|
271
291
|
const result = await backendTranslate(entry.text, cfg.sourceLang, lang, cfg.projectContext, entry.context ?? null, cfg);
|
|
272
292
|
if (validateTranslation(entry.text, result)) {
|
|
273
|
-
|
|
293
|
+
const insertParams = {
|
|
274
294
|
sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
|
|
275
295
|
projectContextHash, stringContextHash, stringContext: entry.context ?? '',
|
|
276
296
|
translatedText: result, model: cfg.backendModel, status: 'translated',
|
|
277
|
-
}
|
|
297
|
+
};
|
|
298
|
+
await store.insert(insertParams);
|
|
299
|
+
if (shared)
|
|
300
|
+
await shared.insert(insertParams);
|
|
278
301
|
translated++;
|
|
279
302
|
}
|
|
280
303
|
else {
|
|
281
|
-
|
|
304
|
+
const insertParams = {
|
|
282
305
|
sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
|
|
283
306
|
projectContextHash, stringContextHash, stringContext: entry.context ?? '',
|
|
284
307
|
translatedText: result, model: cfg.backendModel, status: 'failed',
|
|
285
|
-
}
|
|
308
|
+
};
|
|
309
|
+
await store.insert(insertParams);
|
|
310
|
+
if (shared)
|
|
311
|
+
await shared.insert(insertParams);
|
|
286
312
|
failed++;
|
|
287
313
|
}
|
|
288
314
|
}
|
|
@@ -293,6 +319,8 @@ export async function runWarm(opts) {
|
|
|
293
319
|
}
|
|
294
320
|
}
|
|
295
321
|
store.close();
|
|
322
|
+
if (shared)
|
|
323
|
+
await shared.close();
|
|
296
324
|
return `Translated: ${translated} | Skipped: ${skipped} | Failed: ${failed}`;
|
|
297
325
|
}
|
|
298
326
|
export async function runScan(opts) {
|
|
@@ -479,21 +507,44 @@ export async function runStats(opts) {
|
|
|
479
507
|
await store.initialize();
|
|
480
508
|
const st = await store.stats();
|
|
481
509
|
const lines = [
|
|
482
|
-
|
|
483
|
-
`
|
|
510
|
+
'Local store:',
|
|
511
|
+
` Total translations: ${st.totalTranslations}`,
|
|
512
|
+
` Failed translations: ${st.totalFailed}`,
|
|
484
513
|
];
|
|
485
514
|
if (Object.keys(st.byLanguage).length > 0) {
|
|
486
|
-
lines.push('By language:');
|
|
515
|
+
lines.push(' By language:');
|
|
487
516
|
for (const [lang, count] of Object.entries(st.byLanguage).sort()) {
|
|
488
|
-
lines.push(`
|
|
517
|
+
lines.push(` ${lang}: ${count}`);
|
|
489
518
|
}
|
|
490
519
|
}
|
|
491
520
|
store.close();
|
|
521
|
+
if (cfg.sharedUrl) {
|
|
522
|
+
try {
|
|
523
|
+
const shared = new SharedStore(cfg.sharedUrl);
|
|
524
|
+
await shared.initialize();
|
|
525
|
+
const sharedSt = await shared.stats();
|
|
526
|
+
lines.push('');
|
|
527
|
+
lines.push('Shared store:');
|
|
528
|
+
lines.push(` Total translations: ${sharedSt.totalTranslations}`);
|
|
529
|
+
lines.push(` Failed translations: ${sharedSt.totalFailed}`);
|
|
530
|
+
if (Object.keys(sharedSt.byLanguage).length > 0) {
|
|
531
|
+
lines.push(' By language:');
|
|
532
|
+
for (const [lang, count] of Object.entries(sharedSt.byLanguage).sort()) {
|
|
533
|
+
lines.push(` ${lang}: ${count}`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
await shared.close();
|
|
537
|
+
}
|
|
538
|
+
catch (err) {
|
|
539
|
+
lines.push('');
|
|
540
|
+
lines.push(`Shared store: error connecting (${err.message})`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
492
543
|
return lines.join('\n');
|
|
493
544
|
}
|
|
494
545
|
// CLI entry point
|
|
495
546
|
const program = new Command();
|
|
496
|
-
program.name('transduck').description('AI-native translation tool').version('0.
|
|
547
|
+
program.name('transduck').description('AI-native translation tool').version('0.6.1');
|
|
497
548
|
program.command('init')
|
|
498
549
|
.description('Initialize a new transduck project')
|
|
499
550
|
.action(async () => {
|
|
@@ -505,6 +556,7 @@ program.command('init')
|
|
|
505
556
|
const context = await ask('Project context: ');
|
|
506
557
|
const sourceLang = await ask('Source language (e.g. EN): ');
|
|
507
558
|
const targetsRaw = await ask('Target languages (comma-separated): ');
|
|
559
|
+
const sharedUrl = await ask('Shared Postgres URL (optional, press Enter to skip): ');
|
|
508
560
|
console.log('\nTranslation provider:');
|
|
509
561
|
console.log(' 1. OpenAI (requires API key)');
|
|
510
562
|
console.log(' 2. Claude API (requires API key)');
|
|
@@ -516,6 +568,7 @@ program.command('init')
|
|
|
516
568
|
dir, name, context, sourceLang,
|
|
517
569
|
targetLangs: targetsRaw.split(',').map(s => s.trim()),
|
|
518
570
|
provider: providerChoice,
|
|
571
|
+
sharedUrl: sharedUrl.trim() || undefined,
|
|
519
572
|
});
|
|
520
573
|
console.log(output);
|
|
521
574
|
const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
1
2
|
export interface TransduckConfig {
|
|
2
3
|
projectName: string;
|
|
3
4
|
projectContext: string;
|
|
@@ -10,6 +11,7 @@ export interface TransduckConfig {
|
|
|
10
11
|
backendModel: string;
|
|
11
12
|
backendTimeout: number;
|
|
12
13
|
backendMaxRetries: number;
|
|
14
|
+
sharedUrl: string | null;
|
|
13
15
|
readOnly: boolean;
|
|
14
16
|
}
|
|
15
17
|
export declare function loadConfig(path?: string): TransduckConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
1
2
|
import { readFileSync, existsSync } from 'fs';
|
|
2
3
|
import { resolve, dirname, join } from 'path';
|
|
3
4
|
import { parse as parseYaml } from 'yaml';
|
|
@@ -36,6 +37,7 @@ export function loadConfig(path) {
|
|
|
36
37
|
const backendModel = backend.model ?? 'gpt-4.1-mini';
|
|
37
38
|
const backendTimeout = backend.timeout_seconds ?? 10;
|
|
38
39
|
const backendMaxRetries = backend.max_retries ?? 2;
|
|
40
|
+
const sharedUrl = process.env.TRANSDUCK_SHARED_URL || raw.storage?.shared_url || null;
|
|
39
41
|
let readOnly = raw.runtime?.read_only ?? false;
|
|
40
42
|
if (provider === 'claude_code') {
|
|
41
43
|
readOnly = true;
|
|
@@ -46,6 +48,7 @@ export function loadConfig(path) {
|
|
|
46
48
|
sourceLang: String(raw.languages.source).toUpperCase(),
|
|
47
49
|
targetLangs: raw.languages.targets.map((l) => String(l).toUpperCase()),
|
|
48
50
|
storagePath,
|
|
51
|
+
sharedUrl,
|
|
49
52
|
provider,
|
|
50
53
|
apiKeyEnv,
|
|
51
54
|
tokenEnv,
|
package/dist/handler.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
interface TranslationRequestString {
|
|
2
2
|
text: string;
|
|
3
3
|
context?: string;
|
|
4
|
+
sourceLang?: string;
|
|
4
5
|
}
|
|
5
6
|
interface TranslationRequestPlural {
|
|
6
7
|
one: string;
|
|
7
8
|
other: string;
|
|
8
9
|
context?: string | null;
|
|
10
|
+
sourceLang?: string;
|
|
9
11
|
}
|
|
10
12
|
export interface TranslationRequest {
|
|
11
13
|
language: string;
|
package/dist/handler.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import { loadConfig } from './config.js';
|
|
3
3
|
import { TranslationStore } from './storage.js';
|
|
4
|
+
import { SharedStore } from './shared-store.js';
|
|
4
5
|
import { translate as backendTranslate, translatePlural as backendTranslatePlural } from './backend.js';
|
|
5
6
|
import { validateTranslation } from './validation.js';
|
|
6
7
|
function hash(text) {
|
|
7
8
|
return createHash('sha256').update(text).digest('hex');
|
|
8
9
|
}
|
|
9
10
|
let _store = null;
|
|
11
|
+
let _sharedStore = null;
|
|
10
12
|
async function getStore(configPath) {
|
|
11
13
|
if (!_store) {
|
|
12
14
|
const cfg = loadConfig(configPath);
|
|
@@ -15,51 +17,76 @@ async function getStore(configPath) {
|
|
|
15
17
|
}
|
|
16
18
|
return _store;
|
|
17
19
|
}
|
|
20
|
+
async function getSharedStore(configPath) {
|
|
21
|
+
if (_sharedStore)
|
|
22
|
+
return _sharedStore;
|
|
23
|
+
const cfg = loadConfig(configPath);
|
|
24
|
+
if (!cfg.sharedUrl)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
_sharedStore = new SharedStore(cfg.sharedUrl);
|
|
28
|
+
await _sharedStore.initialize();
|
|
29
|
+
return _sharedStore;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
18
35
|
/** @internal Reset the singleton store — for testing only. */
|
|
19
36
|
export function _resetHandlerStore() {
|
|
20
37
|
if (_store) {
|
|
21
38
|
_store.close();
|
|
22
39
|
}
|
|
23
40
|
_store = null;
|
|
41
|
+
_sharedStore = null;
|
|
24
42
|
}
|
|
25
43
|
export async function handleTranslationRequest(body, configPath) {
|
|
26
44
|
const cfg = loadConfig(configPath);
|
|
27
45
|
const store = await getStore(configPath);
|
|
46
|
+
const shared = await getSharedStore(configPath);
|
|
28
47
|
const targetLang = body.language.toUpperCase();
|
|
29
48
|
const projectContextHash = hash(cfg.projectContext);
|
|
30
49
|
const translations = {};
|
|
31
50
|
const plurals = {};
|
|
32
51
|
// Translate regular strings
|
|
33
52
|
for (const item of body.strings ?? []) {
|
|
53
|
+
const sourceLang = item.sourceLang?.toUpperCase() ?? cfg.sourceLang;
|
|
34
54
|
const stringContextHash = hash(item.context ?? '');
|
|
35
55
|
const key = `${item.text}||${item.context ?? ''}`;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
stringContextHash,
|
|
43
|
-
});
|
|
56
|
+
const lookupParams = {
|
|
57
|
+
sourceText: item.text, sourceLang, targetLang,
|
|
58
|
+
projectContextHash, stringContextHash,
|
|
59
|
+
};
|
|
60
|
+
// Tier 1: local cache
|
|
61
|
+
const cached = await store.lookup(lookupParams);
|
|
44
62
|
if (cached !== null) {
|
|
45
63
|
translations[key] = cached;
|
|
46
64
|
continue;
|
|
47
65
|
}
|
|
66
|
+
// Tier 2: shared store
|
|
67
|
+
if (shared) {
|
|
68
|
+
const sharedCached = await shared.lookup(lookupParams);
|
|
69
|
+
if (sharedCached !== null) {
|
|
70
|
+
// Propagate to local
|
|
71
|
+
await store.insert({
|
|
72
|
+
...lookupParams, stringContext: item.context ?? '',
|
|
73
|
+
translatedText: sharedCached, model: cfg.backendModel, status: 'translated',
|
|
74
|
+
});
|
|
75
|
+
translations[key] = sharedCached;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
48
79
|
// Backend call
|
|
49
80
|
try {
|
|
50
|
-
const translated = await backendTranslate(item.text,
|
|
81
|
+
const translated = await backendTranslate(item.text, sourceLang, targetLang, cfg.projectContext, item.context ?? null, cfg);
|
|
51
82
|
if (validateTranslation(item.text, translated)) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
translatedText: translated,
|
|
60
|
-
model: cfg.backendModel,
|
|
61
|
-
status: 'translated',
|
|
62
|
-
});
|
|
83
|
+
const insertParams = {
|
|
84
|
+
...lookupParams, stringContext: item.context ?? '',
|
|
85
|
+
translatedText: translated, model: cfg.backendModel, status: 'translated',
|
|
86
|
+
};
|
|
87
|
+
await store.insert(insertParams);
|
|
88
|
+
if (shared)
|
|
89
|
+
await shared.insert(insertParams);
|
|
63
90
|
translations[key] = translated;
|
|
64
91
|
}
|
|
65
92
|
else {
|
|
@@ -72,37 +99,48 @@ export async function handleTranslationRequest(body, configPath) {
|
|
|
72
99
|
}
|
|
73
100
|
// Translate plurals
|
|
74
101
|
for (const item of body.plurals ?? []) {
|
|
102
|
+
const sourceLang = item.sourceLang?.toUpperCase() ?? cfg.sourceLang;
|
|
75
103
|
const stringContextHash = hash(item.context ?? '');
|
|
76
104
|
const sourceKey = item.one + '\x00' + item.other;
|
|
77
105
|
const responseKey = `${sourceKey}||${item.context ?? ''}`;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
stringContextHash,
|
|
85
|
-
});
|
|
106
|
+
const lookupParams = {
|
|
107
|
+
sourceText: sourceKey, sourceLang, targetLang,
|
|
108
|
+
projectContextHash, stringContextHash,
|
|
109
|
+
};
|
|
110
|
+
// Tier 1: local cache
|
|
111
|
+
const cachedForms = await store.lookupPlural(lookupParams);
|
|
86
112
|
if (Object.keys(cachedForms).length > 0) {
|
|
87
113
|
plurals[responseKey] = cachedForms;
|
|
88
114
|
continue;
|
|
89
115
|
}
|
|
116
|
+
// Tier 2: shared store
|
|
117
|
+
if (shared) {
|
|
118
|
+
const sharedForms = await shared.lookupPlural(lookupParams);
|
|
119
|
+
if (Object.keys(sharedForms).length > 0) {
|
|
120
|
+
// Propagate to local
|
|
121
|
+
for (const [cat, text] of Object.entries(sharedForms)) {
|
|
122
|
+
await store.insertPlural({
|
|
123
|
+
...lookupParams, stringContext: item.context ?? '',
|
|
124
|
+
pluralCategory: cat, translatedText: text,
|
|
125
|
+
model: cfg.backendModel, status: 'translated',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
plurals[responseKey] = sharedForms;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
90
132
|
// Backend call
|
|
91
133
|
try {
|
|
92
|
-
const forms = await backendTranslatePlural(item.one, item.other,
|
|
134
|
+
const forms = await backendTranslatePlural(item.one, item.other, sourceLang, targetLang, cfg.projectContext, item.context ?? null, cfg);
|
|
93
135
|
for (const [cat, translatedText] of Object.entries(forms)) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
translatedText: translatedText,
|
|
103
|
-
model: cfg.backendModel,
|
|
104
|
-
status: 'translated',
|
|
105
|
-
});
|
|
136
|
+
const insertParams = {
|
|
137
|
+
...lookupParams, stringContext: item.context ?? '',
|
|
138
|
+
pluralCategory: cat, translatedText: translatedText,
|
|
139
|
+
model: cfg.backendModel, status: 'translated',
|
|
140
|
+
};
|
|
141
|
+
await store.insertPlural(insertParams);
|
|
142
|
+
if (shared)
|
|
143
|
+
await shared.insertPlural(insertParams);
|
|
106
144
|
}
|
|
107
145
|
plurals[responseKey] = forms;
|
|
108
146
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import { type TransduckConfig } from './config.js';
|
|
2
2
|
import { TranslationStore } from './storage.js';
|
|
3
|
+
import { SharedStore } from './shared-store.js';
|
|
4
|
+
import { TranslationResult } from './result.js';
|
|
3
5
|
export declare function initialize(config?: TransduckConfig): Promise<void>;
|
|
4
6
|
export declare function setLanguage(lang: string): void;
|
|
5
7
|
export declare function _resetState(): void;
|
|
6
8
|
export declare function _getStore(): TranslationStore | null;
|
|
7
|
-
export declare function
|
|
9
|
+
export declare function _getSharedStore(): SharedStore | null;
|
|
10
|
+
export declare function _setSharedStore(shared: SharedStore | null): void;
|
|
11
|
+
export interface AitOptions {
|
|
12
|
+
context?: string;
|
|
13
|
+
vars?: Record<string, string | number>;
|
|
14
|
+
sourceLang?: string;
|
|
15
|
+
background?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function ait(sourceText: string, contextOrOpts?: string | AitOptions, vars?: Record<string, string | number>): Promise<TranslationResult>;
|
|
8
18
|
export { createTransDuckHandler } from './handler.js';
|
|
19
|
+
export { TranslationResult } from './result.js';
|
|
20
|
+
export { SharedStore } from './shared-store.js';
|
|
21
|
+
export declare function detectLanguage(text: string): Promise<string>;
|
|
9
22
|
export declare function aitPlural(one: string, other: string, count: number, opts?: {
|
|
10
23
|
context?: string;
|
|
11
24
|
vars?: Record<string, string | number>;
|
|
12
|
-
|
|
25
|
+
sourceLang?: string;
|
|
26
|
+
background?: boolean;
|
|
27
|
+
}): Promise<TranslationResult>;
|