@thor123141245r/ai-translate 0.0.0 → 1.0.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/README.md +161 -71
- package/README.zh-CN.md +194 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +77 -0
- package/dist/cli.js.map +1 -1
- package/dist/i18n/align.d.ts +3 -0
- package/dist/i18n/align.d.ts.map +1 -0
- package/dist/i18n/align.js +46 -0
- package/dist/i18n/align.js.map +1 -0
- package/dist/i18n/cache.d.ts +14 -0
- package/dist/i18n/cache.d.ts.map +1 -0
- package/dist/i18n/cache.js +36 -0
- package/dist/i18n/cache.js.map +1 -0
- package/dist/i18n/command.d.ts +7 -0
- package/dist/i18n/command.d.ts.map +1 -0
- package/dist/i18n/command.js +84 -0
- package/dist/i18n/command.js.map +1 -0
- package/dist/i18n/extract.d.ts +7 -0
- package/dist/i18n/extract.d.ts.map +1 -0
- package/dist/i18n/extract.js +24 -0
- package/dist/i18n/extract.js.map +1 -0
- package/dist/i18n/json-path.d.ts +7 -0
- package/dist/i18n/json-path.d.ts.map +1 -0
- package/dist/i18n/json-path.js +61 -0
- package/dist/i18n/json-path.js.map +1 -0
- package/dist/i18n/parse.d.ts +6 -0
- package/dist/i18n/parse.d.ts.map +1 -0
- package/dist/i18n/parse.js +44 -0
- package/dist/i18n/parse.js.map +1 -0
- package/dist/i18n/placeholders.d.ts +7 -0
- package/dist/i18n/placeholders.d.ts.map +1 -0
- package/dist/i18n/placeholders.js +44 -0
- package/dist/i18n/placeholders.js.map +1 -0
- package/dist/i18n/prompt.d.ts +13 -0
- package/dist/i18n/prompt.d.ts.map +1 -0
- package/dist/i18n/prompt.js +37 -0
- package/dist/i18n/prompt.js.map +1 -0
- package/dist/i18n/translate.d.ts +29 -0
- package/dist/i18n/translate.d.ts.map +1 -0
- package/dist/i18n/translate.js +199 -0
- package/dist/i18n/translate.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/.agentdocs/code-changes/2026-01-22/AI/347/277/273/350/257/221/345/231/250TS/345/256/236/347/216/260-/345/256/236/347/216/260.md +0 -22
- package/.agentdocs/code-changes/2026-01-23/CLI/345/210/206/345/217/221-npx/345/256/236/347/216/260.md +0 -18
- package/.agentdocs/code-changes/2026-01-23/sora-watermask-remover-/345/233/275/351/231/205/345/214/226/347/277/273/350/257/221-/345/256/236/347/216/260.md +0 -37
- package/.agentdocs/code-changes/2026-01-23//351/205/215/347/275/256/350/257/273/345/217/226-/347/216/257/345/242/203/345/217/230/351/207/217/344/274/230/345/205/210-/345/256/236/347/216/260.md +0 -22
- package/.agentdocs/plans/2026-01-22/AI/347/277/273/350/257/221/345/231/250TS/345/256/236/347/216/260-/344/274/230/345/214/226/346/226/271/346/241/210.md +0 -67
- package/.agentdocs/plans/2026-01-23/CLI/345/210/206/345/217/221-npx/346/226/271/346/241/210.md +0 -60
- package/.agentdocs/plans/2026-01-23/sora-watermask-remover-/345/233/275/351/231/205/345/214/226/347/277/273/350/257/221-/344/274/230/345/214/226/346/226/271/346/241/210.md +0 -51
- package/.agentdocs/plans/2026-01-23//351/205/215/347/275/256/350/257/273/345/217/226-/347/216/257/345/242/203/345/217/230/351/207/217/344/274/230/345/205/210-/344/274/230/345/214/226/346/226/271/346/241/210.md +0 -80
- package/SKILL.md +0 -103
- package/src/asyncTransform.ts +0 -31
- package/src/bin/ai-translate.ts +0 -5
- package/src/cli.ts +0 -313
- package/src/index.ts +0 -9
- package/src/logger.ts +0 -3
- package/src/model.ts +0 -139
- package/src/prompt.ts +0 -71
- package/src/split.ts +0 -111
- package/src/utils.ts +0 -15
- package/tsconfig.json +0 -19
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { logger } from '../logger.js';
|
|
4
|
+
import { alignStructure } from './align.js';
|
|
5
|
+
import { extractLeafStrings } from './extract.js';
|
|
6
|
+
import { getAtPath, setAtPath, pathToString } from './json-path.js';
|
|
7
|
+
import { protectPlaceholders, restorePlaceholders } from './placeholders.js';
|
|
8
|
+
import { TranslationCache } from './cache.js';
|
|
9
|
+
import { i18nBatchPromptInvoke, i18nRepairPromptInvoke } from './prompt.js';
|
|
10
|
+
import { parseJsonArray } from './parse.js';
|
|
11
|
+
import { getLanguageName } from '../prompt.js';
|
|
12
|
+
const log = logger('i18n');
|
|
13
|
+
const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;
|
|
14
|
+
const deepClone = (v) => JSON.parse(JSON.stringify(v));
|
|
15
|
+
const readJsonFile = (file) => {
|
|
16
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
17
|
+
return JSON.parse(raw);
|
|
18
|
+
};
|
|
19
|
+
const writeJsonFile = (file, obj) => {
|
|
20
|
+
fs.writeFileSync(file, JSON.stringify(obj, null, 2) + '\n', 'utf-8');
|
|
21
|
+
};
|
|
22
|
+
const chunkUnits = (units, maxItems, maxChars) => {
|
|
23
|
+
const batches = [];
|
|
24
|
+
let cur = [];
|
|
25
|
+
let curChars = 0;
|
|
26
|
+
const pushCur = () => {
|
|
27
|
+
if (!cur.length)
|
|
28
|
+
return;
|
|
29
|
+
batches.push(cur);
|
|
30
|
+
cur = [];
|
|
31
|
+
curChars = 0;
|
|
32
|
+
};
|
|
33
|
+
for (const u of units) {
|
|
34
|
+
const estimated = u.protectedText.length + 40;
|
|
35
|
+
if (cur.length >= maxItems || (cur.length > 0 && curChars + estimated > maxChars)) {
|
|
36
|
+
pushCur();
|
|
37
|
+
}
|
|
38
|
+
cur.push(u);
|
|
39
|
+
curChars += estimated;
|
|
40
|
+
}
|
|
41
|
+
pushCur();
|
|
42
|
+
return batches;
|
|
43
|
+
};
|
|
44
|
+
const buildCacheKey = (opts) => `${opts.sourceLang}|${opts.targetLang}|${pathToString(opts.path)}|${opts.text}`;
|
|
45
|
+
const translateBatch = async (opts) => {
|
|
46
|
+
const itemsJson = JSON.stringify(opts.items);
|
|
47
|
+
const messages = await i18nBatchPromptInvoke({
|
|
48
|
+
sourceLanguage: opts.sourceLanguage,
|
|
49
|
+
targetLanguage: opts.targetLanguage,
|
|
50
|
+
itemsJson
|
|
51
|
+
});
|
|
52
|
+
const result = await opts.model.invoke(messages);
|
|
53
|
+
try {
|
|
54
|
+
return parseJsonArray(String(result.content ?? ''));
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// One repair attempt: ask the model to output valid JSON only.
|
|
58
|
+
const expectedIds = opts.items.map((it) => it.id);
|
|
59
|
+
const repair = await i18nRepairPromptInvoke({
|
|
60
|
+
sourceLanguage: opts.sourceLanguage,
|
|
61
|
+
targetLanguage: opts.targetLanguage,
|
|
62
|
+
expectedIds,
|
|
63
|
+
badOutput: String(result.content ?? '')
|
|
64
|
+
});
|
|
65
|
+
const repaired = await opts.model.invoke(repair);
|
|
66
|
+
return parseJsonArray(String(repaired.content ?? ''));
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
export const translateI18nDir = async (opts) => {
|
|
70
|
+
const { baseDir, sourceLang, targets, mode, dryRun = false, fileName, batchMaxItems = 40, batchMaxChars = 6000, cacheFile } = opts.options;
|
|
71
|
+
if (!targets.length)
|
|
72
|
+
throw new Error('targets is required');
|
|
73
|
+
const sourceFileName = fileName || `${sourceLang}.json`;
|
|
74
|
+
const sourceFile = path.resolve(baseDir, sourceFileName);
|
|
75
|
+
if (!fs.existsSync(sourceFile)) {
|
|
76
|
+
throw new Error(`source file not found: ${sourceFile}`);
|
|
77
|
+
}
|
|
78
|
+
const cache = new TranslationCache(cacheFile);
|
|
79
|
+
cache.load();
|
|
80
|
+
const sourceJson = readJsonFile(sourceFile);
|
|
81
|
+
const sourceLeaves = extractLeafStrings(sourceJson);
|
|
82
|
+
const stats = [];
|
|
83
|
+
for (const targetLang of targets) {
|
|
84
|
+
const targetFileName = `${targetLang}.json`;
|
|
85
|
+
const targetFile = path.resolve(baseDir, targetFileName);
|
|
86
|
+
const targetJsonRaw = fs.existsSync(targetFile) ? readJsonFile(targetFile) : undefined;
|
|
87
|
+
const alignedTarget = alignStructure(sourceJson, targetJsonRaw, mode);
|
|
88
|
+
const targetJson = deepClone(alignedTarget);
|
|
89
|
+
const units = [];
|
|
90
|
+
let skippedExisting = 0;
|
|
91
|
+
let usedCache = 0;
|
|
92
|
+
for (let i = 0; i < sourceLeaves.length; i++) {
|
|
93
|
+
const { path: p, value: sourceText } = sourceLeaves[i];
|
|
94
|
+
if (!sourceText || sourceText.trim() === '')
|
|
95
|
+
continue;
|
|
96
|
+
const existing = getAtPath(targetJson, p);
|
|
97
|
+
if (mode === 'fill' && isNonEmptyString(existing)) {
|
|
98
|
+
skippedExisting++;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const cacheKey = buildCacheKey({
|
|
102
|
+
sourceLang,
|
|
103
|
+
targetLang,
|
|
104
|
+
path: p,
|
|
105
|
+
text: sourceText
|
|
106
|
+
});
|
|
107
|
+
const cached = cache.get(cacheKey);
|
|
108
|
+
if (cached) {
|
|
109
|
+
usedCache++;
|
|
110
|
+
setAtPath(targetJson, p, cached);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const { tokens, protectedText } = protectPlaceholders(sourceText);
|
|
114
|
+
const id = `k${String(units.length + 1).padStart(6, '0')}`;
|
|
115
|
+
units.push({
|
|
116
|
+
id,
|
|
117
|
+
path: p,
|
|
118
|
+
sourceText,
|
|
119
|
+
protectedText,
|
|
120
|
+
tokens
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const totalStrings = sourceLeaves.filter((x) => x.value.trim().length > 0).length;
|
|
124
|
+
if (dryRun) {
|
|
125
|
+
stats.push({
|
|
126
|
+
targetLang,
|
|
127
|
+
sourceFile,
|
|
128
|
+
targetFile,
|
|
129
|
+
totalStrings,
|
|
130
|
+
skippedExisting,
|
|
131
|
+
toTranslate: units.length,
|
|
132
|
+
translated: 0,
|
|
133
|
+
failed: 0,
|
|
134
|
+
usedCache
|
|
135
|
+
});
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const batches = chunkUnits(units, batchMaxItems, batchMaxChars);
|
|
139
|
+
let translated = 0;
|
|
140
|
+
let failed = 0;
|
|
141
|
+
for (let bi = 0; bi < batches.length; bi++) {
|
|
142
|
+
const batch = batches[bi];
|
|
143
|
+
const items = batch.map((u) => ({ id: u.id, text: u.protectedText }));
|
|
144
|
+
try {
|
|
145
|
+
const out = await translateBatch({
|
|
146
|
+
model: opts.model,
|
|
147
|
+
sourceLanguage: getLanguageName(sourceLang),
|
|
148
|
+
targetLanguage: getLanguageName(targetLang),
|
|
149
|
+
items
|
|
150
|
+
});
|
|
151
|
+
const outMap = new Map(out.map((x) => [x.id, x.text]));
|
|
152
|
+
for (const u of batch) {
|
|
153
|
+
const translatedText = outMap.get(u.id);
|
|
154
|
+
if (!translatedText) {
|
|
155
|
+
failed++;
|
|
156
|
+
// fall back to English to keep JSON valid and predictable
|
|
157
|
+
setAtPath(targetJson, u.path, u.sourceText);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const restored = restorePlaceholders(translatedText, u.tokens);
|
|
161
|
+
setAtPath(targetJson, u.path, restored);
|
|
162
|
+
translated++;
|
|
163
|
+
const cacheKey = buildCacheKey({
|
|
164
|
+
sourceLang,
|
|
165
|
+
targetLang,
|
|
166
|
+
path: u.path,
|
|
167
|
+
text: u.sourceText
|
|
168
|
+
});
|
|
169
|
+
cache.set(cacheKey, restored);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
log.error({ err, targetLang, batch: bi + 1, batches: batches.length });
|
|
174
|
+
// degrade: keep source for this batch
|
|
175
|
+
for (const u of batch) {
|
|
176
|
+
failed++;
|
|
177
|
+
setAtPath(targetJson, u.path, u.sourceText);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
writeJsonFile(targetFile, targetJson);
|
|
182
|
+
stats.push({
|
|
183
|
+
targetLang,
|
|
184
|
+
sourceFile,
|
|
185
|
+
targetFile,
|
|
186
|
+
totalStrings,
|
|
187
|
+
skippedExisting,
|
|
188
|
+
toTranslate: units.length,
|
|
189
|
+
translated,
|
|
190
|
+
failed,
|
|
191
|
+
usedCache
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
if (!dryRun) {
|
|
195
|
+
cache.save();
|
|
196
|
+
}
|
|
197
|
+
return stats;
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/i18n/translate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { AiTranslateTransform, modelFactory } from './model.js';
|
|
2
2
|
export { promptInvoke, languages } from './prompt.js';
|
|
3
3
|
export { TextSplitterStream, recursiveChunkTextSplitter, getFormatByExtension } from './split.js';
|
|
4
|
+
export { translateI18nDir } from './i18n/translate.js';
|
|
4
5
|
export type { Metadata, ModelFactoryOptions } from './model.js';
|
|
5
6
|
export type { TextSplitterParams, Separator } from './split.js';
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAC/D,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAC/D,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AiTranslateTransform, modelFactory } from './model.js';
|
|
2
2
|
export { promptInvoke, languages } from './prompt.js';
|
|
3
3
|
export { TextSplitterStream, recursiveChunkTextSplitter, getFormatByExtension } from './split.js';
|
|
4
|
+
export { translateI18nDir } from './i18n/translate.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thor123141245r/ai-translate",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"default": "./dist/index.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"README.zh-CN.md"
|
|
24
|
+
],
|
|
20
25
|
"scripts": {
|
|
21
26
|
"build": "tsc -p tsconfig.json",
|
|
22
27
|
"dev:cli": "tsx src/bin/ai-translate.ts",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-22 23:35
|
|
2
|
-
|
|
3
|
-
# 变更概述
|
|
4
|
-
基于方案实现 TypeScript 版本的 AI 翻译器:按官方库结构复刻核心流程,补齐模块分层、CLI 入口、配置与日志策略,并提供最小验证脚本与中文说明。
|
|
5
|
-
|
|
6
|
-
# 变更清单
|
|
7
|
-
- [x] 引入并对齐 ai-translate 的核心 API 与流程
|
|
8
|
-
- [x] 新增 TypeScript 目录结构与模块实现
|
|
9
|
-
- [x] 新增 CLI 或脚本入口
|
|
10
|
-
- [x] 配置与日志策略落地
|
|
11
|
-
- [x] 中文使用文档更新
|
|
12
|
-
- [x] 最小测试或验证脚本补齐
|
|
13
|
-
|
|
14
|
-
# 关键设计对齐
|
|
15
|
-
- 模块分层:配置解析层、翻译执行层、文件读写层、日志层
|
|
16
|
-
- 复用优先:最大限度遵循官方库结构与命名
|
|
17
|
-
- 日志策略:开发环境整对象打印,生产环境精简敏感信息
|
|
18
|
-
|
|
19
|
-
# 待确认事项状态
|
|
20
|
-
- 是否要求完全对齐官方库的所有导出与命令参数:未确认
|
|
21
|
-
- 是否需要发布为独立 npm 包:未确认
|
|
22
|
-
- 是否要兼容现有 Python 脚本的输入格式:未确认
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-23 04:18
|
|
2
|
-
|
|
3
|
-
# 变更概述
|
|
4
|
-
为 CLI 增加可通过 npx/pnpx 直接执行的分发配置,更新包名与发布设置,并补充中文使用说明。
|
|
5
|
-
|
|
6
|
-
# 变更清单
|
|
7
|
-
- [x] package.json 发布与 bin 配置调整
|
|
8
|
-
- [x] README 增加 npx/pnpx 使用说明
|
|
9
|
-
- [x] 本地构建与验证
|
|
10
|
-
|
|
11
|
-
# 关键设计对齐
|
|
12
|
-
- bin 入口保持 ai-translate
|
|
13
|
-
- npm 包名为 @thor123141245r/ai-translate
|
|
14
|
-
- 发布为 public
|
|
15
|
-
|
|
16
|
-
# 待确认事项状态
|
|
17
|
-
- 采用哪个 npm 包名:@thor123141245r/ai-translate(已确认)
|
|
18
|
-
- 是否允许发布到 npm:允许,public(已确认)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
作者: Codex | 创建时间: 2026-01-23 21:35
|
|
2
|
-
|
|
3
|
-
# sora-watermask-remover 国际化翻译实现
|
|
4
|
-
|
|
5
|
-
## 变更概述
|
|
6
|
-
- 使用脚本 `sentence_json_translator.py` 基于 `en.json` 翻译并覆盖目录内全部语言文件
|
|
7
|
-
- 保持受保护关键词 `sora watermask remover` 原样
|
|
8
|
-
- 保留专有名词与产品名:Sora、Sora2 Cloud、OpenAI Pro、HD、15s
|
|
9
|
-
|
|
10
|
-
## 执行方式
|
|
11
|
-
- 脚本位置:`/Users/thor/.codex/skills/i18n-copywriter/scripts/sentence_json_translator.py`
|
|
12
|
-
- 目标目录:`/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover`
|
|
13
|
-
- 运行参数要点:
|
|
14
|
-
- `--overwrite` 全量覆盖
|
|
15
|
-
- `--protected-terms "sora watermask remover,Sora,Sora2 Cloud,OpenAI Pro,HD,15s"`
|
|
16
|
-
- 由于接口偶发 SSL 握手失败,启用 `CONTENT_LOCALIZE_INSECURE=1` 并提高重试次数
|
|
17
|
-
|
|
18
|
-
## 涉及文件
|
|
19
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/ar.json`
|
|
20
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/de.json`
|
|
21
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/es.json`
|
|
22
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/fr.json`
|
|
23
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/he.json`
|
|
24
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/hi.json`
|
|
25
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/id.json`
|
|
26
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/ja.json`
|
|
27
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/km.json`
|
|
28
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/ru.json`
|
|
29
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/th.json`
|
|
30
|
-
- `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover/zh.json`
|
|
31
|
-
|
|
32
|
-
## 验证
|
|
33
|
-
- JSON 解析检查通过
|
|
34
|
-
- key 集合与 `en.json` 完全一致
|
|
35
|
-
|
|
36
|
-
## 备注
|
|
37
|
-
- 本次翻译为脚本输出结果,如需人工润色可在此基础上微调
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-23 21:06
|
|
2
|
-
|
|
3
|
-
# 实现说明
|
|
4
|
-
- 新增运行时配置解析 让 apiKey 与 baseUrl 优先取环境变量
|
|
5
|
-
- 调整模型工厂 避免空 apiKey 覆盖 SDK 默认环境变量读取
|
|
6
|
-
- README 增补环境变量优先级与变量名说明
|
|
7
|
-
|
|
8
|
-
# 变更清单
|
|
9
|
-
- src/cli.ts
|
|
10
|
-
- 新增 baseUrl schema
|
|
11
|
-
- 新增 resolveRuntimeConfig 处理环境变量优先级
|
|
12
|
-
- src/model.ts
|
|
13
|
-
- apiKey baseUrl 仅在有效值时注入
|
|
14
|
-
- openai deepseek 使用 configuration baseURL
|
|
15
|
-
- ollama 使用 baseUrl
|
|
16
|
-
- README.md
|
|
17
|
-
- 增加环境变量优先级与变量列表
|
|
18
|
-
|
|
19
|
-
# 自测要点
|
|
20
|
-
- 设置环境变量后 即使配置文件不同仍以环境变量为准
|
|
21
|
-
- 未设置环境变量时 使用配置文件
|
|
22
|
-
- 不设置 apiKey 时 SDK 自动读取自身环境变量
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-22 23:30
|
|
2
|
-
|
|
3
|
-
# 背景
|
|
4
|
-
当前项目只有 Python 脚本实现。需要参考 `ai-translate` 的源码,在本仓库实现一套 TypeScript 版本,保证功能对齐与可复用。
|
|
5
|
-
|
|
6
|
-
# 目标
|
|
7
|
-
- 基于官方库源码,实现等价的 TypeScript 模块与对外 API
|
|
8
|
-
- 保持结构清晰可维护,避免超 500 行文件
|
|
9
|
-
- 形成可执行的本地脚本与最小测试覆盖
|
|
10
|
-
|
|
11
|
-
# 范围
|
|
12
|
-
- 新增 TypeScript 实现与必要的运行脚本
|
|
13
|
-
- 新增或更新配置与文档
|
|
14
|
-
- 不改动数据库迁移文件
|
|
15
|
-
|
|
16
|
-
# 方案概述
|
|
17
|
-
以“标准化与生态复用”为优先策略:先安装并审阅 `ai-translate` 源码,梳理其导出接口与核心流程,再在本仓库实现等价模块与 CLI 或脚本入口,确保行为与输入输出一致。
|
|
18
|
-
|
|
19
|
-
```mermaid
|
|
20
|
-
flowchart TD
|
|
21
|
-
A[安装依赖] --> B[读取源码]
|
|
22
|
-
B --> C[整理接口]
|
|
23
|
-
C --> D[设计模块]
|
|
24
|
-
D --> E[实现功能]
|
|
25
|
-
E --> F[编写测试]
|
|
26
|
-
F --> G[更新文档]
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
# 关键设计
|
|
30
|
-
- 模块分层:配置解析层、翻译执行层、文件读写层、日志层
|
|
31
|
-
- 复用策略:最大限度遵循官方库结构与命名,避免自研偏离
|
|
32
|
-
- 日志策略:开发环境整对象打印,生产环境精简敏感信息
|
|
33
|
-
|
|
34
|
-
```mermaid
|
|
35
|
-
flowchart LR
|
|
36
|
-
A[输入源文件] --> B[解析配置]
|
|
37
|
-
B --> C[调用翻译引擎]
|
|
38
|
-
C --> D[写入目标文件]
|
|
39
|
-
D --> E[输出结果]
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
# 实施步骤
|
|
43
|
-
1. 安装 `ai-translate` 并定位源码入口
|
|
44
|
-
2. 梳理导出 API 与关键执行流程
|
|
45
|
-
3. 设计 TypeScript 目录结构与模块边界
|
|
46
|
-
4. 实现核心功能并补齐类型定义
|
|
47
|
-
5. 编写最小可用测试或验证脚本
|
|
48
|
-
6. 补充中文说明文档与使用示例
|
|
49
|
-
|
|
50
|
-
# 验收标准
|
|
51
|
-
- 与官方库的核心功能等价,输入输出一致
|
|
52
|
-
- 新增 ts 文件均小于 500 行
|
|
53
|
-
- 可以通过脚本完成一次实际翻译流程
|
|
54
|
-
- 中文文档完整可读
|
|
55
|
-
|
|
56
|
-
# 需求清单
|
|
57
|
-
- [ ] 安装并分析 `ai-translate` 源码
|
|
58
|
-
- [ ] TypeScript 版本的核心翻译功能
|
|
59
|
-
- [ ] CLI 或脚本入口
|
|
60
|
-
- [ ] 配置与日志策略
|
|
61
|
-
- [ ] 中文使用文档
|
|
62
|
-
- [ ] 基础测试或验证脚本
|
|
63
|
-
|
|
64
|
-
# 待确认事项
|
|
65
|
-
- 是否要求完全对齐官方库的所有导出与命令参数 (需用户确认)
|
|
66
|
-
- 是否需要发布为独立 npm 包 (需用户确认)
|
|
67
|
-
- 是否要兼容现有 Python 脚本的输入格式 (需用户确认)
|
package/.agentdocs/plans/2026-01-23/CLI/345/210/206/345/217/221-npx/346/226/271/346/241/210.md
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-23 04:10
|
|
2
|
-
|
|
3
|
-
# 背景
|
|
4
|
-
当前仓库已具备 `ai-translate` CLI,但还未完成可通过 `npx/pnpx` 直接执行的分发形态。
|
|
5
|
-
|
|
6
|
-
# 目标
|
|
7
|
-
- 让用户通过 `npx` 或 `pnpx` 直接执行 `ai-translate` CLI
|
|
8
|
-
- 保持单人团队可维护规模
|
|
9
|
-
- 维持现有接口与配置逻辑
|
|
10
|
-
|
|
11
|
-
# 范围
|
|
12
|
-
- package.json 配置与发布相关设置
|
|
13
|
-
- 文档更新
|
|
14
|
-
- 不涉及迁移文件
|
|
15
|
-
|
|
16
|
-
# 方案概述
|
|
17
|
-
1) 规范包名与 bin 输出,使 `npx <包名>` 直接可用
|
|
18
|
-
2) 调整发布配置,避免 private 阻断
|
|
19
|
-
3) 在 README 增加 `npx/pnpx` 使用说明
|
|
20
|
-
|
|
21
|
-
```mermaid
|
|
22
|
-
flowchart TD
|
|
23
|
-
A[确认包名] --> B[配置 bin]
|
|
24
|
-
B --> C[取消私有设置]
|
|
25
|
-
C --> D[更新文档]
|
|
26
|
-
D --> E[本地验证]
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
# 关键设计
|
|
30
|
-
- bin 入口保持 `ai-translate` 命令
|
|
31
|
-
- `npx` 触发时使用包名执行(需 npm 包名可用)
|
|
32
|
-
- `pnpx` 行为与 `npx` 一致
|
|
33
|
-
|
|
34
|
-
```mermaid
|
|
35
|
-
flowchart LR
|
|
36
|
-
A[用户执行 npx] --> B[下载包]
|
|
37
|
-
B --> C[执行 bin]
|
|
38
|
-
C --> D[调用 CLI]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
# 实施步骤
|
|
42
|
-
1. 确认 npm 包名与发布范围
|
|
43
|
-
2. 调整 package.json: name、private、bin、exports
|
|
44
|
-
3. README 添加 npx 与 pnpx 的示例
|
|
45
|
-
4. 本地 build 与 npx 验证
|
|
46
|
-
|
|
47
|
-
# 验收标准
|
|
48
|
-
- `npx <包名>` 可直接执行
|
|
49
|
-
- `pnpx <包名>` 可直接执行
|
|
50
|
-
- README 有中文使用说明
|
|
51
|
-
|
|
52
|
-
# 需求清单
|
|
53
|
-
- [ ] 确认包名与是否发布
|
|
54
|
-
- [ ] 完成 package.json 配置
|
|
55
|
-
- [ ] README 更新
|
|
56
|
-
- [ ] 本地验证
|
|
57
|
-
|
|
58
|
-
# 待确认事项
|
|
59
|
-
- 采用哪个 npm 包名 (需用户确认)
|
|
60
|
-
- 是否允许发布到 npm(需用户确认)
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
作者: Codex | 创建时间: 2026-01-23 21:15
|
|
2
|
-
|
|
3
|
-
# sora-watermask-remover 国际化翻译优化方案
|
|
4
|
-
|
|
5
|
-
## 背景与目标
|
|
6
|
-
当前目录 `/Users/thor/Github/sora2.cloud-main/src/i18n/pages/sora-watermask-remover` 下存在多语言 JSON。需要以 `en.json` 为单一事实来源,对所有语言文件进行完整本地化翻译与一致性校验,确保营销页面文案统一、可发布、且受保护关键词不被误译。
|
|
7
|
-
|
|
8
|
-
## 范围
|
|
9
|
-
- 仅处理该目录下 i18n JSON 文案内容
|
|
10
|
-
- 不改动业务逻辑与组件
|
|
11
|
-
- 不新增迁移文件
|
|
12
|
-
|
|
13
|
-
## 受保护关键词策略
|
|
14
|
-
- 从 `en.json` 与项目命名中抽取品牌与关键词
|
|
15
|
-
- 受保护关键词在任何语言中保持英文原样
|
|
16
|
-
|
|
17
|
-
## 方案概述
|
|
18
|
-
1. 读取 `en.json`,确认 key 结构与文案目标
|
|
19
|
-
2. 建立受保护关键词清单并确认
|
|
20
|
-
3. 对比所有语言文件,补齐缺失 key 并对齐结构
|
|
21
|
-
4. 逐语言翻译与本地化,避免硬翻译品牌与关键词
|
|
22
|
-
5. 运行 key 一致性检查与占位符检查
|
|
23
|
-
|
|
24
|
-
## 流程图
|
|
25
|
-
```mermaid
|
|
26
|
-
flowchart TD
|
|
27
|
-
A[读取英文文案] --> B[整理受保护关键词]
|
|
28
|
-
B --> C[对齐所有语言结构]
|
|
29
|
-
C --> D[逐语言本地化翻译]
|
|
30
|
-
D --> E[一致性与占位符检查]
|
|
31
|
-
E --> F[输出最终多语言文件]
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 影响评估
|
|
35
|
-
- 仅修改 JSON 文案内容
|
|
36
|
-
- 不涉及代码逻辑与运行时行为
|
|
37
|
-
|
|
38
|
-
## 验证方案
|
|
39
|
-
- 运行 `scripts/check_i18n_keys.py` 校验 key 一致性
|
|
40
|
-
- 抽样核对受保护关键词与占位符
|
|
41
|
-
|
|
42
|
-
## 需求清单
|
|
43
|
-
- [ ] 完整翻译并本地化所有语言 JSON
|
|
44
|
-
- [ ] 受保护关键词保持英文原样
|
|
45
|
-
- [ ] 所有语言与 `en.json` key 完全一致
|
|
46
|
-
- [ ] 输出可直接发布的营销文案
|
|
47
|
-
|
|
48
|
-
## 待确认事项
|
|
49
|
-
- 目标语言清单是否为目录内全部语言文件(ar de es fr he hi id ja km ru th zh)(需用户确认)
|
|
50
|
-
- 受保护关键词清单与大小写规则(如 Sora 2 Sora2 Cloud OpenAI Pro HD 15s sora watermask remover)(需用户确认)
|
|
51
|
-
- 文案语气与风格偏好(理性简洁或强转化促销)(需用户确认)
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
作者:Codex|创建时间:2026-01-23 21:06
|
|
2
|
-
|
|
3
|
-
# 目标
|
|
4
|
-
- 让 apiKey 与 baseUrl 优先从环境变量读取
|
|
5
|
-
- 兼容已有配置文件与 CLI 写入配置
|
|
6
|
-
- 明确并文档化配置优先级与环境变量名称
|
|
7
|
-
|
|
8
|
-
# 方案概述
|
|
9
|
-
- 新增统一的配置解析流程
|
|
10
|
-
- 以 环境变量 为最高优先级 其次配置文件 最后默认值
|
|
11
|
-
- 仅在有值时向模型构造函数注入 apiKey 与 baseUrl 避免空值覆盖
|
|
12
|
-
|
|
13
|
-
```mermaid
|
|
14
|
-
flowchart TD
|
|
15
|
-
A[启动命令] --> B[读取环境变量]
|
|
16
|
-
B --> C[读取配置文件]
|
|
17
|
-
C --> D[合并配置]
|
|
18
|
-
D --> E[构建模型]
|
|
19
|
-
E --> F[执行翻译]
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
# 配置优先级
|
|
23
|
-
- 环境变量优先级高于配置文件
|
|
24
|
-
- 配置文件高于代码默认值
|
|
25
|
-
- 未设置的字段不写入模型参数
|
|
26
|
-
|
|
27
|
-
```mermaid
|
|
28
|
-
flowchart LR
|
|
29
|
-
A[环境变量有值] --> D[使用环境变量]
|
|
30
|
-
B[环境变量无值] --> C[读取配置]
|
|
31
|
-
C --> D
|
|
32
|
-
D --> E[合并默认值]
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
# 环境变量规划
|
|
36
|
-
- 通用变量
|
|
37
|
-
- AI_TRANSLATE_API_KEY
|
|
38
|
-
- AI_TRANSLATE_BASE_URL
|
|
39
|
-
- 兼容主流 SDK 变量
|
|
40
|
-
- OPENAI_API_KEY
|
|
41
|
-
- OPENAI_BASE_URL
|
|
42
|
-
- ANTHROPIC_API_KEY
|
|
43
|
-
- MISTRAL_API_KEY
|
|
44
|
-
- DEEPSEEK_API_KEY
|
|
45
|
-
- OLLAMA_BASE_URL
|
|
46
|
-
|
|
47
|
-
```mermaid
|
|
48
|
-
sequenceDiagram
|
|
49
|
-
participant CLI
|
|
50
|
-
participant 配置管理
|
|
51
|
-
participant 模型工厂
|
|
52
|
-
CLI->>配置管理: 读取环境变量
|
|
53
|
-
配置管理->>配置管理: 合并配置文件
|
|
54
|
-
配置管理->>模型工厂: 输出最终配置
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
# 影响范围
|
|
58
|
-
- src/cli.ts
|
|
59
|
-
- 新增 baseUrl schema
|
|
60
|
-
- 引入配置解析函数
|
|
61
|
-
- src/model.ts
|
|
62
|
-
- 去除空 apiKey 注入
|
|
63
|
-
- 按 provider 注入 baseUrl
|
|
64
|
-
- README.md
|
|
65
|
-
- 增补环境变量说明与优先级
|
|
66
|
-
|
|
67
|
-
# 实施步骤
|
|
68
|
-
1. 新增配置解析函数并接入 CLI
|
|
69
|
-
2. 调整模型工厂的 apiKey 与 baseUrl 注入策略
|
|
70
|
-
3. 更新 README 使用说明与示例
|
|
71
|
-
|
|
72
|
-
# 验收清单
|
|
73
|
-
- [ ] 设置环境变量后 即使配置文件不同仍以环境变量生效
|
|
74
|
-
- [ ] 未设置环境变量时 使用配置文件值
|
|
75
|
-
- [ ] 未配置 apiKey 时不再覆盖 SDK 默认取值逻辑
|
|
76
|
-
- [ ] README 清晰说明优先级与变量名称
|
|
77
|
-
|
|
78
|
-
# 待确认事项
|
|
79
|
-
- [ ] 是否接受新增 AI_TRANSLATE_API_KEY 与 AI_TRANSLATE_BASE_URL 作为通用环境变量 (需用户确认)
|
|
80
|
-
- [ ] 是否需要同时支持 provider 专属 baseUrl 变量 如 DEEPSEEK_BASE_URL (需用户确认)
|