@geolonia/yuuhitsu 0.1.17 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/provider/claude.d.ts +7 -1
- package/dist/provider/claude.d.ts.map +1 -1
- package/dist/provider/claude.js +60 -0
- package/dist/provider/claude.js.map +1 -1
- package/dist/provider/interface.d.ts +27 -0
- package/dist/provider/interface.d.ts.map +1 -1
- package/dist/tasks/translate.d.ts +31 -40
- package/dist/tasks/translate.d.ts.map +1 -1
- package/dist/tasks/translate.js +318 -403
- package/dist/tasks/translate.js.map +1 -1
- package/package.json +8 -1
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { AIProvider, ChatRequest, ChatResponse, StreamChunk } from "./interface.js";
|
|
1
|
+
import type { AIProvider, ChatRequest, ChatResponse, StreamChunk, StructuredTranslateRequest, StructuredTranslateResponse } from "./interface.js";
|
|
2
2
|
export declare class ClaudeProvider implements AIProvider {
|
|
3
3
|
private client;
|
|
4
4
|
private model;
|
|
5
5
|
constructor(model: string);
|
|
6
6
|
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
7
7
|
chatStream(request: ChatRequest): AsyncIterable<StreamChunk>;
|
|
8
|
+
/**
|
|
9
|
+
* Translate segments using Anthropic tool_use (structured output).
|
|
10
|
+
* Forces Claude to return a JSON object matching the translation schema —
|
|
11
|
+
* no prose wrapping, no schema deviations.
|
|
12
|
+
*/
|
|
13
|
+
translateStructured(request: StructuredTranslateRequest): Promise<StructuredTranslateResponse>;
|
|
8
14
|
}
|
|
9
15
|
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AA2BxB,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAYnB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAiChD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC;IA8BnE;;;;OAIG;IACG,mBAAmB,CACvB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,2BAA2B,CAAC;CA2CxC"}
|
package/dist/provider/claude.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
const TRANSLATION_TOOL_NAME = "record_translations";
|
|
3
|
+
const TRANSLATION_TOOL = {
|
|
4
|
+
name: TRANSLATION_TOOL_NAME,
|
|
5
|
+
description: "Record the translated text segments in structured JSON format",
|
|
6
|
+
input_schema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
translations: {
|
|
10
|
+
type: "array",
|
|
11
|
+
items: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
id: { type: "integer", description: "Segment ID (must match input ID exactly)" },
|
|
15
|
+
text: { type: "string", description: "Translated text for this segment" },
|
|
16
|
+
},
|
|
17
|
+
required: ["id", "text"],
|
|
18
|
+
},
|
|
19
|
+
description: "Translated segments — one entry per input segment, ID must match",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ["translations"],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
2
25
|
export class ClaudeProvider {
|
|
3
26
|
client;
|
|
4
27
|
model;
|
|
@@ -65,5 +88,42 @@ export class ClaudeProvider {
|
|
|
65
88
|
}
|
|
66
89
|
yield { content: "", done: true };
|
|
67
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Translate segments using Anthropic tool_use (structured output).
|
|
93
|
+
* Forces Claude to return a JSON object matching the translation schema —
|
|
94
|
+
* no prose wrapping, no schema deviations.
|
|
95
|
+
*/
|
|
96
|
+
async translateStructured(request) {
|
|
97
|
+
const response = await this.client.messages.create({
|
|
98
|
+
model: request.model || this.model,
|
|
99
|
+
max_tokens: request.maxTokens ?? 4096,
|
|
100
|
+
system: request.systemPrompt,
|
|
101
|
+
messages: [
|
|
102
|
+
{
|
|
103
|
+
role: "user",
|
|
104
|
+
content: JSON.stringify({ segments: request.segments }),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
tools: [TRANSLATION_TOOL],
|
|
108
|
+
tool_choice: { type: "tool", name: TRANSLATION_TOOL_NAME },
|
|
109
|
+
});
|
|
110
|
+
const toolUseBlock = response.content.find((b) => b.type === "tool_use");
|
|
111
|
+
if (!toolUseBlock) {
|
|
112
|
+
throw new Error(`[yuuhitsu] ClaudeProvider.translateStructured: no tool_use block in response` +
|
|
113
|
+
` (stop_reason: ${response.stop_reason})`);
|
|
114
|
+
}
|
|
115
|
+
const input = toolUseBlock.input;
|
|
116
|
+
if (!Array.isArray(input.translations)) {
|
|
117
|
+
throw new Error(`[yuuhitsu] ClaudeProvider.translateStructured: translations field is missing or not an array`);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
translations: input.translations,
|
|
121
|
+
usage: {
|
|
122
|
+
promptTokens: response.usage.input_tokens,
|
|
123
|
+
completionTokens: response.usage.output_tokens,
|
|
124
|
+
totalTokens: response.usage.input_tokens + response.usage.output_tokens,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
68
128
|
}
|
|
69
129
|
//# sourceMappingURL=claude.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/provider/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,8 +23,35 @@ export interface StreamChunk {
|
|
|
23
23
|
content: string;
|
|
24
24
|
done: boolean;
|
|
25
25
|
}
|
|
26
|
+
/** Request for structured output translation (tool_use path). */
|
|
27
|
+
export interface StructuredTranslateRequest {
|
|
28
|
+
segments: Array<{
|
|
29
|
+
id: number;
|
|
30
|
+
text: string;
|
|
31
|
+
}>;
|
|
32
|
+
systemPrompt: string;
|
|
33
|
+
model?: string;
|
|
34
|
+
maxTokens?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Response from structured output translation. */
|
|
37
|
+
export interface StructuredTranslateResponse {
|
|
38
|
+
translations: Array<{
|
|
39
|
+
id: number;
|
|
40
|
+
text: string;
|
|
41
|
+
}>;
|
|
42
|
+
usage: {
|
|
43
|
+
promptTokens: number;
|
|
44
|
+
completionTokens: number;
|
|
45
|
+
totalTokens: number;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
26
48
|
export interface AIProvider {
|
|
27
49
|
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
28
50
|
chatStream(request: ChatRequest): AsyncIterable<StreamChunk>;
|
|
51
|
+
/**
|
|
52
|
+
* Structured output translation via provider-native JSON schema enforcement.
|
|
53
|
+
* Optional: implemented by Claude. Gemini and Ollama fall back to text mode.
|
|
54
|
+
*/
|
|
55
|
+
translateStructured?(request: StructuredTranslateRequest): Promise<StructuredTranslateResponse>;
|
|
29
56
|
}
|
|
30
57
|
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/provider/interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/provider/interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,iEAAiE;AACjE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7D;;;OAGG;IACH,mBAAmB,CAAC,CAClB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACzC"}
|
|
@@ -6,45 +6,10 @@ interface FrontmatterSeparation {
|
|
|
6
6
|
body: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Separate frontmatter from Markdown content
|
|
9
|
+
* Separate frontmatter from Markdown content.
|
|
10
10
|
* Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
|
|
11
|
-
* @param content - Full Markdown content
|
|
12
|
-
* @returns Object with separated frontmatter and body
|
|
13
11
|
*/
|
|
14
12
|
export declare function separateFrontmatter(content: string): FrontmatterSeparation;
|
|
15
|
-
interface CodeProtection {
|
|
16
|
-
text: string;
|
|
17
|
-
map: Map<string, string>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Replace fenced code blocks and inline code with placeholders.
|
|
21
|
-
* Uses a line-by-line parser instead of regex to avoid V8 stack overflow
|
|
22
|
-
* on files with many code blocks (backreference + [\s\S]*? causes recursive backtracking).
|
|
23
|
-
*/
|
|
24
|
-
export declare function protectCodeBlocks(content: string): CodeProtection;
|
|
25
|
-
/**
|
|
26
|
-
* Restore placeholders back to original code blocks/inline code.
|
|
27
|
-
*/
|
|
28
|
-
export declare function restoreCodeBlocks(content: string, map: Map<string, string>): string;
|
|
29
|
-
export declare const BLOCK_BOUNDARY_SENTINEL = "<!--BB-->";
|
|
30
|
-
/**
|
|
31
|
-
* Insert block boundary sentinels before structural Markdown elements
|
|
32
|
-
* (list items, headings, horizontal rules, code fences, code block placeholders).
|
|
33
|
-
* P-A4: prevents newline collapse around structural boundaries during LLM translation.
|
|
34
|
-
* When called after protectCodeBlocks, fenced blocks appear as __CODE_BLOCK_N__ placeholders;
|
|
35
|
-
* the function treats those placeholders as structural to protect fence-adjacent newlines.
|
|
36
|
-
*/
|
|
37
|
-
export declare function protectBlockBoundaries(content: string): string;
|
|
38
|
-
/**
|
|
39
|
-
* Remove block boundary sentinels and restore newlines lost during LLM translation.
|
|
40
|
-
* Uses a 3-pass strategy plus Layer 3 list-aware fallback (P-A4 v3):
|
|
41
|
-
* Pass 1: normalize LLM-deformed variants (e.g. <!-- BB -->) to exact sentinel form
|
|
42
|
-
* Pass 2: split + restore newlines (handles both clean and collapsed sentinel cases)
|
|
43
|
-
* Pass 3: post-restore warning for residual sentinel-like patterns (silent failure prevention)
|
|
44
|
-
* Layer 3: detect list items collapsed onto one line ("- A- B") and split them back
|
|
45
|
-
* Applied unconditionally — handles the case where LLM deleted ALL sentinels
|
|
46
|
-
*/
|
|
47
|
-
export declare function restoreBlockBoundaries(content: string): string;
|
|
48
13
|
export interface TranslateOptions {
|
|
49
14
|
provider: AIProvider;
|
|
50
15
|
inputPath: string;
|
|
@@ -69,8 +34,8 @@ export interface TranslateResult {
|
|
|
69
34
|
*/
|
|
70
35
|
export declare function findHeadingPositions(lines: string[], level: number): number[];
|
|
71
36
|
/**
|
|
72
|
-
* Split lines at the given positions into chunks
|
|
73
|
-
*
|
|
37
|
+
* Split lines at the given positions into chunks. Segments exceeding maxChunkLines
|
|
38
|
+
* are further split using ### headings or safeSplitLines.
|
|
74
39
|
*/
|
|
75
40
|
export declare function splitAtPositions(lines: string[], positions: number[], maxChunkLines: number): string[];
|
|
76
41
|
/**
|
|
@@ -79,8 +44,7 @@ export declare function splitAtPositions(lines: string[], positions: number[], m
|
|
|
79
44
|
*/
|
|
80
45
|
export declare function safeSplitLines(lines: string[], maxChunkLines: number): string[];
|
|
81
46
|
/**
|
|
82
|
-
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk
|
|
83
|
-
* as long as the merged result does not exceed maxLines.
|
|
47
|
+
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk.
|
|
84
48
|
*/
|
|
85
49
|
export declare function mergeSmallChunks(chunks: string[], maxLines: number): string[];
|
|
86
50
|
/**
|
|
@@ -88,6 +52,33 @@ export declare function mergeSmallChunks(chunks: string[], maxLines: number): st
|
|
|
88
52
|
* Falls back to safe line-count splitting when no headings are present.
|
|
89
53
|
*/
|
|
90
54
|
export declare function splitIntoChunks(content: string, maxChunkLines?: number): string[];
|
|
55
|
+
interface CodeProtection {
|
|
56
|
+
text: string;
|
|
57
|
+
map: Map<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Replace fenced code blocks and inline code with placeholders.
|
|
61
|
+
* Used by glossary-fix.ts to protect code blocks before text replacement.
|
|
62
|
+
*/
|
|
63
|
+
export declare function protectCodeBlocks(content: string): CodeProtection;
|
|
64
|
+
/**
|
|
65
|
+
* Restore placeholders back to original code blocks/inline code.
|
|
66
|
+
*/
|
|
67
|
+
export declare function restoreCodeBlocks(content: string, map: Map<string, string>): string;
|
|
68
|
+
/**
|
|
69
|
+
* Translate a Markdown file using AST-based approach.
|
|
70
|
+
*
|
|
71
|
+
* Architecture (0.2.0):
|
|
72
|
+
* 1. Separate frontmatter (preserved verbatim)
|
|
73
|
+
* 2. Split body into chunks by heading boundaries
|
|
74
|
+
* 3. For each chunk: parse to AST → extract text nodes → translate via LLM → write back
|
|
75
|
+
* 4. Serialize AST → markdown → concatenate → write output
|
|
76
|
+
*
|
|
77
|
+
* Key properties:
|
|
78
|
+
* - Code blocks (fenced and inline) are never sent to LLM (AST handles them deterministically)
|
|
79
|
+
* - Markdown structure (headings, lists, tables, HR) is preserved by AST round-trip
|
|
80
|
+
* - No sentinel injection or removal needed
|
|
81
|
+
*/
|
|
91
82
|
export declare function translateFile(options: TranslateOptions): Promise<TranslateResult>;
|
|
92
83
|
export {};
|
|
93
84
|
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAM3C,UAAU,qBAAqB;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAa1E;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAa7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CAyBV;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAyB/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,aAAa,SAA0B,GACtC,MAAM,EAAE,CAcV;AAMD,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA8CjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAYnF;AAkRD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CA+E1B"}
|
package/dist/tasks/translate.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
2
|
import { dirname, basename, extname, join } from "path";
|
|
3
|
+
import { remark } from "remark";
|
|
4
|
+
import remarkGfm from "remark-gfm";
|
|
5
|
+
import { visit } from "unist-util-visit";
|
|
3
6
|
import { buildGlossaryPrompt } from "./glossary.js";
|
|
4
7
|
export const DEFAULT_MAX_CHUNK_LINES = 300;
|
|
5
8
|
const MIN_CHUNK_LINES = 50;
|
|
9
|
+
// P-A1: minimum ratio of output characters to input characters (truncation check)
|
|
10
|
+
const MIN_OUTPUT_RATIO = 0.3;
|
|
6
11
|
/**
|
|
7
|
-
* Separate frontmatter from Markdown content
|
|
12
|
+
* Separate frontmatter from Markdown content.
|
|
8
13
|
* Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
|
|
9
|
-
* @param content - Full Markdown content
|
|
10
|
-
* @returns Object with separated frontmatter and body
|
|
11
14
|
*/
|
|
12
15
|
export function separateFrontmatter(content) {
|
|
13
|
-
// Normalize CRLF to LF for regex matching
|
|
14
16
|
const normalized = content.replace(/\r\n/g, "\n");
|
|
15
|
-
// Match frontmatter (two alternations to keep closing --- on its own line):
|
|
16
|
-
// Case 1: non-empty body: ^---\n ... \n---[ \t]*(\n|$)
|
|
17
|
-
// Case 2: empty body: ^---\n---[ \t]*(\n|$)
|
|
18
|
-
// Using alternation avoids the \n? ambiguity that allows --- to match mid-line.
|
|
19
17
|
const frontmatterRegex = /^---\n([\s\S]*?)\n---[ \t]*(\n|$)|^---\n---[ \t]*(\n|$)/;
|
|
20
18
|
const match = normalized.match(frontmatterRegex);
|
|
21
19
|
if (match) {
|
|
@@ -26,359 +24,7 @@ export function separateFrontmatter(content) {
|
|
|
26
24
|
}
|
|
27
25
|
return { frontmatter: null, body: normalized };
|
|
28
26
|
}
|
|
29
|
-
|
|
30
|
-
* Replace fenced code blocks and inline code with placeholders.
|
|
31
|
-
* Uses a line-by-line parser instead of regex to avoid V8 stack overflow
|
|
32
|
-
* on files with many code blocks (backreference + [\s\S]*? causes recursive backtracking).
|
|
33
|
-
*/
|
|
34
|
-
export function protectCodeBlocks(content) {
|
|
35
|
-
const map = new Map();
|
|
36
|
-
let blockIndex = 0;
|
|
37
|
-
let inlineIndex = 0;
|
|
38
|
-
// Step 1: Replace fenced code blocks using line-by-line parsing
|
|
39
|
-
const lines = content.split("\n");
|
|
40
|
-
const resultLines = [];
|
|
41
|
-
let fenceOpen = null; // the backtick sequence that opened the current block
|
|
42
|
-
let blockLines = [];
|
|
43
|
-
for (const line of lines) {
|
|
44
|
-
const fenceMatch = line.match(/^(`{3,})/);
|
|
45
|
-
if (fenceOpen === null) {
|
|
46
|
-
// Not inside a code block
|
|
47
|
-
if (fenceMatch) {
|
|
48
|
-
// Opening fence found
|
|
49
|
-
fenceOpen = fenceMatch[1];
|
|
50
|
-
blockLines = [line];
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
resultLines.push(line);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
// Inside a code block — look for closing fence with same or more backticks
|
|
58
|
-
blockLines.push(line);
|
|
59
|
-
if (fenceMatch && fenceMatch[1].length >= fenceOpen.length && line.trim() === fenceMatch[1]) {
|
|
60
|
-
// Closing fence found — store as single-line placeholder (no padding).
|
|
61
|
-
// Padding was previously used to preserve line count, but it caused chunk
|
|
62
|
-
// boundaries to fall inside the placeholder's whitespace region, leading to
|
|
63
|
-
// non-deterministic LLM output when the code block exceeded --max-chunk-lines.
|
|
64
|
-
const original = blockLines.join("\n") + "\n";
|
|
65
|
-
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
66
|
-
map.set(placeholder, original);
|
|
67
|
-
resultLines.push(placeholder);
|
|
68
|
-
fenceOpen = null;
|
|
69
|
-
blockLines = [];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// If we ended inside an unclosed fence, emit lines as-is
|
|
74
|
-
if (fenceOpen !== null) {
|
|
75
|
-
resultLines.push(...blockLines);
|
|
76
|
-
}
|
|
77
|
-
let result = resultLines.join("\n");
|
|
78
|
-
// Step 2: Replace inline code (single backtick, not within code blocks)
|
|
79
|
-
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
80
|
-
const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
|
|
81
|
-
map.set(placeholder, match);
|
|
82
|
-
return placeholder;
|
|
83
|
-
});
|
|
84
|
-
return { text: result, map };
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Restore placeholders back to original code blocks/inline code.
|
|
88
|
-
*/
|
|
89
|
-
export function restoreCodeBlocks(content, map) {
|
|
90
|
-
let result = content;
|
|
91
|
-
for (const [placeholder, original] of map.entries()) {
|
|
92
|
-
if (original.endsWith("\n")) {
|
|
93
|
-
// Fenced code block: original already has trailing \n — just replace, one \n total.
|
|
94
|
-
result = result.split(placeholder + "\n").join(original);
|
|
95
|
-
result = result.split(placeholder).join(original);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// Inline code: original has NO trailing \n. Preserve any \n that follows the placeholder
|
|
99
|
-
// so that newlines inserted by restoreBlockBoundaries (Layer 3) are not consumed.
|
|
100
|
-
// e.g. "__INLINE_CODE_0__\n- next item" → "`code`\n- next item" (not "`code`- next item")
|
|
101
|
-
result = result.split(placeholder + "\n").join(original + "\n");
|
|
102
|
-
result = result.split(placeholder).join(original);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
export const BLOCK_BOUNDARY_SENTINEL = "<!--BB-->";
|
|
108
|
-
// Temporary escape for pre-existing <!--BB--> literals in user content.
|
|
109
|
-
// Uses a character sequence unlikely to appear in markdown documents.
|
|
110
|
-
const ESCAPED_SENTINEL = "\x01BB\x01";
|
|
111
|
-
// Fallback regex: catches LLM-deformed variants (e.g. <!-- BB -->, <!--BB__-->, <!--BBx-->)
|
|
112
|
-
const SENTINEL_FALLBACK = /<!--\s*BB[a-zA-Z0-9_-]*\s*-->/g;
|
|
113
|
-
// Broad check: detects severely-deformed residuals not caught by SENTINEL_FALLBACK
|
|
114
|
-
const SENTINEL_RESIDUAL_CHECK = /<!--[\s\S]*?BB[\s\S]*?-->/g;
|
|
115
|
-
/**
|
|
116
|
-
* Insert block boundary sentinels before structural Markdown elements
|
|
117
|
-
* (list items, headings, horizontal rules, code fences, code block placeholders).
|
|
118
|
-
* P-A4: prevents newline collapse around structural boundaries during LLM translation.
|
|
119
|
-
* When called after protectCodeBlocks, fenced blocks appear as __CODE_BLOCK_N__ placeholders;
|
|
120
|
-
* the function treats those placeholders as structural to protect fence-adjacent newlines.
|
|
121
|
-
*/
|
|
122
|
-
export function protectBlockBoundaries(content) {
|
|
123
|
-
// Escape all sentinel-like patterns (exact + variants) to prevent control-marker confusion.
|
|
124
|
-
// SENTINEL_FALLBACK covers <!--BB-->, <!-- BB -->, <!--BBx-->, <!--BB-x-->, etc.
|
|
125
|
-
// On restore, these all round-trip back to <!--BB--> (minor cosmetic vs. content deletion).
|
|
126
|
-
const escaped = content.replace(SENTINEL_FALLBACK, ESCAPED_SENTINEL);
|
|
127
|
-
const lines = escaped.split("\n");
|
|
128
|
-
const result = [];
|
|
129
|
-
for (const line of lines) {
|
|
130
|
-
const isListItem = /^\s*[-*+]\s/.test(line) || // unordered list
|
|
131
|
-
/^\s*\d+\.\s/.test(line); // ordered list
|
|
132
|
-
const isOtherStructural = !isListItem && (/^ {0,3}#{1,6}\s/.test(line) || // heading (CommonMark: 0-3 leading spaces)
|
|
133
|
-
/^ {0,3}-{3,}\s*$/.test(line) || // hr (dash, 0-3 leading spaces)
|
|
134
|
-
/^ {0,3}\*{3,}\s*$/.test(line) || // hr (asterisk, 0-3 leading spaces)
|
|
135
|
-
/^ {0,3}_{3,}\s*$/.test(line) || // hr (underscore, 0-3 leading spaces)
|
|
136
|
-
/^\s*`{3,}/.test(line) || // fenced code (backtick)
|
|
137
|
-
/^\s*~{3,}/.test(line) || // fenced code (tilde)
|
|
138
|
-
/^__CODE_BLOCK_\d+__$/.test(line.trim()) // code block placeholder (after protectCodeBlocks)
|
|
139
|
-
);
|
|
140
|
-
if (isListItem) {
|
|
141
|
-
// P-A4 v3: double sentinel BEFORE each list item to resist LLM collapse.
|
|
142
|
-
// 0.1.16 used a single sentinel; LLM deleted it and collapsed items to one line.
|
|
143
|
-
// Two sentinels before each item mean the LLM must delete both to collapse — higher bar.
|
|
144
|
-
// After-sentinels are intentionally omitted to preserve clean round-trip (no trailing \n).
|
|
145
|
-
result.push(BLOCK_BOUNDARY_SENTINEL);
|
|
146
|
-
result.push(BLOCK_BOUNDARY_SENTINEL);
|
|
147
|
-
result.push(line);
|
|
148
|
-
}
|
|
149
|
-
else if (isOtherStructural) {
|
|
150
|
-
result.push(BLOCK_BOUNDARY_SENTINEL);
|
|
151
|
-
result.push(line);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
result.push(line);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return result.join("\n");
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Remove block boundary sentinels and restore newlines lost during LLM translation.
|
|
161
|
-
* Uses a 3-pass strategy plus Layer 3 list-aware fallback (P-A4 v3):
|
|
162
|
-
* Pass 1: normalize LLM-deformed variants (e.g. <!-- BB -->) to exact sentinel form
|
|
163
|
-
* Pass 2: split + restore newlines (handles both clean and collapsed sentinel cases)
|
|
164
|
-
* Pass 3: post-restore warning for residual sentinel-like patterns (silent failure prevention)
|
|
165
|
-
* Layer 3: detect list items collapsed onto one line ("- A- B") and split them back
|
|
166
|
-
* Applied unconditionally — handles the case where LLM deleted ALL sentinels
|
|
167
|
-
*/
|
|
168
|
-
export function restoreBlockBoundaries(content) {
|
|
169
|
-
// Pass 1: normalize variant sentinels introduced by LLM deformation (cmd_389 Root Cause A/B)
|
|
170
|
-
const normalized = content.replace(SENTINEL_FALLBACK, BLOCK_BOUNDARY_SENTINEL);
|
|
171
|
-
let restored;
|
|
172
|
-
// Pass 2: split + restore newlines
|
|
173
|
-
if (!normalized.includes(BLOCK_BOUNDARY_SENTINEL)) {
|
|
174
|
-
// No exact sentinels: fall through to Pass 3 + Layer 3 (handles fully-deleted sentinel case)
|
|
175
|
-
restored = normalized;
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const parts = normalized.split(BLOCK_BOUNDARY_SENTINEL);
|
|
179
|
-
restored = parts[0];
|
|
180
|
-
for (let i = 1; i < parts.length; i++) {
|
|
181
|
-
// Strip a leading newline from next part (present when LLM preserved sentinel on its own line)
|
|
182
|
-
const stripped = parts[i].replace(/^\n/, "");
|
|
183
|
-
if (restored.length === 0) {
|
|
184
|
-
// Sentinel was at the very start of content — no preceding text to separate from
|
|
185
|
-
restored = stripped;
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
// Ensure restored ends with exactly one newline before appending next part
|
|
189
|
-
restored = restored.replace(/\n?$/, "\n") + stripped;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// Pass 3: post-restore warning for patterns not caught by SENTINEL_FALLBACK.
|
|
194
|
-
// Runs for BOTH the sentinel-present and no-sentinel paths so fully-deformed output
|
|
195
|
-
// is still flagged. Check before unescaping to avoid false positives from user <!--BB-->.
|
|
196
|
-
const residuals = restored.match(SENTINEL_RESIDUAL_CHECK);
|
|
197
|
-
if (residuals && residuals.length > 0) {
|
|
198
|
-
console.warn(`[yuuhitsu] restoreBlockBoundaries: ${residuals.length} residual sentinel-like pattern(s) detected after restore:`, residuals.slice(0, 5));
|
|
199
|
-
}
|
|
200
|
-
// Unescape any pre-existing <!--BB--> that were escaped before protection
|
|
201
|
-
if (restored.includes(ESCAPED_SENTINEL)) {
|
|
202
|
-
restored = restored.split(ESCAPED_SENTINEL).join(BLOCK_BOUNDARY_SENTINEL);
|
|
203
|
-
}
|
|
204
|
-
// Layer 3 (P-A4 v3): list-aware fallback — detect inline list concatenation that
|
|
205
|
-
// survived Layer 1+2 (LLM joined "- A\n- B" into "- A- B" on a single line).
|
|
206
|
-
// Applied unconditionally: handles the worst case where ALL sentinels were deleted.
|
|
207
|
-
// Uses /gm flag: ^ anchors to line start per line (multiline mode).
|
|
208
|
-
//
|
|
209
|
-
// Two sub-patterns:
|
|
210
|
-
// (a) Spaced: "- A- B" or "- A - B" — requires whitespace after 2nd marker (original).
|
|
211
|
-
// (b) Placeholder-end: "- A: __INLINE_CODE_0__-B" — inline code placeholder at end of
|
|
212
|
-
// previous item followed directly by next list marker (no space). This is the pattern
|
|
213
|
-
// LLM produces when translating to Japanese (Japanese text has no space after marker).
|
|
214
|
-
// (?<!\s) guard: require the char immediately before the 2nd marker to be non-whitespace.
|
|
215
|
-
// This prevents false-positive splits on prose like "- Linux - macOS support" where the
|
|
216
|
-
// inline "- " is preceded by a space (valid prose) rather than collapsed item text.
|
|
217
|
-
// True collapse ("- A- B") has NO space before the 2nd marker → lookbehind passes.
|
|
218
|
-
const LIST_INLINE_MERGE_UNORDERED = /(^\s*[-*+]\s[^\n]*?)(?<!\s)([-*+]\s)/gm;
|
|
219
|
-
const LIST_INLINE_MERGE_ORDERED = /(^\s*\d+\.\s[^\n]*?)(?<!\s)(\d+\.\s)/gm;
|
|
220
|
-
// Placeholder-end pattern: matches code-placeholder end (\d+__) immediately before list marker.
|
|
221
|
-
// Inserts "\n" + space (standard list-item format: "- content") so the new line passes
|
|
222
|
-
// /^\s*[-*+]\s/ checks in integration tests.
|
|
223
|
-
// (?=[^a-z]) guard avoids false positives for "__CODE__-style" (lowercase word hyphens).
|
|
224
|
-
// e.g. "__INLINE_CODE_0__-次の項目" → "__INLINE_CODE_0__\n- 次の項目"
|
|
225
|
-
const LIST_INLINE_MERGE_PLACEHOLDER_UNORDERED = /(\d+__)([-*+])(?=[^a-z])/gm;
|
|
226
|
-
const LIST_INLINE_MERGE_PLACEHOLDER_ORDERED = /(\d+__)(\d+\.)(?=[^a-z])/gm;
|
|
227
|
-
// Apply iteratively: JavaScript replace() scans left-to-right in the original string,
|
|
228
|
-
// so "- A- B- C" needs two passes (first splits A-B, second splits B-C on the new line).
|
|
229
|
-
let layer3applied = false;
|
|
230
|
-
let prev;
|
|
231
|
-
do {
|
|
232
|
-
prev = restored;
|
|
233
|
-
restored = restored.replace(LIST_INLINE_MERGE_UNORDERED, (_match, p1, p2) => {
|
|
234
|
-
layer3applied = true;
|
|
235
|
-
return `${p1}\n${p2}`;
|
|
236
|
-
});
|
|
237
|
-
restored = restored.replace(LIST_INLINE_MERGE_ORDERED, (_match, p1, p2) => {
|
|
238
|
-
layer3applied = true;
|
|
239
|
-
return `${p1}\n${p2}`;
|
|
240
|
-
});
|
|
241
|
-
restored = restored.replace(LIST_INLINE_MERGE_PLACEHOLDER_UNORDERED, (_match, p1, p2) => {
|
|
242
|
-
layer3applied = true;
|
|
243
|
-
return `${p1}\n${p2} `; // trailing space ensures valid "- content" list-item format
|
|
244
|
-
});
|
|
245
|
-
restored = restored.replace(LIST_INLINE_MERGE_PLACEHOLDER_ORDERED, (_match, p1, p2) => {
|
|
246
|
-
layer3applied = true;
|
|
247
|
-
return `${p1}\n${p2} `;
|
|
248
|
-
});
|
|
249
|
-
} while (restored !== prev);
|
|
250
|
-
if (layer3applied) {
|
|
251
|
-
console.warn("[yuuhitsu] restoreBlockBoundaries: Layer 3 list-aware fallback applied — " +
|
|
252
|
-
"LLM concatenated list items inline. Layer 1+2 sentinels were insufficient.");
|
|
253
|
-
}
|
|
254
|
-
return restored;
|
|
255
|
-
}
|
|
256
|
-
const DEFAULT_TEMPLATE = `You are a professional translator. Translate the following Markdown document to {{targetLanguage}}.
|
|
257
|
-
|
|
258
|
-
Rules:
|
|
259
|
-
- Preserve all Markdown formatting (headings, links, code blocks, tables, lists)
|
|
260
|
-
- Do not translate code blocks, URLs, or file paths
|
|
261
|
-
- Do not translate frontmatter keys (only translate values where appropriate)
|
|
262
|
-
- Maintain the same document structure
|
|
263
|
-
- Produce natural, fluent text in the target language
|
|
264
|
-
- Every opening \`\`\` you write MUST be followed by a language identifier on the same line (e.g., \`\`\`json, \`\`\`bash, \`\`\`typescript)
|
|
265
|
-
- If the language is unknown, use \`\`\`text — never emit a bare opening \`\`\`
|
|
266
|
-
|
|
267
|
-
CRITICAL - Link and URL preservation:
|
|
268
|
-
- NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
|
|
269
|
-
- NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
|
|
270
|
-
- NEVER convert external URLs to different language versions.
|
|
271
|
-
- If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
|
|
272
|
-
- Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
|
|
273
|
-
- Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
|
|
274
|
-
|
|
275
|
-
Additional rules for Japanese translation:
|
|
276
|
-
- Use full-width punctuation: 。、?! (not .,?!)
|
|
277
|
-
- Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
|
|
278
|
-
- Use natural Japanese terms for technical words where appropriate (e.g., "registration" → "登録", "subscription" → "サブスクリプション")
|
|
279
|
-
- Keep product names, proper nouns, and abbreviations unchanged (e.g., Vela, FIWARE, NGSIv2, NGSI-LD, MCP)
|
|
280
|
-
|
|
281
|
-
Example — code fence with language identifier:
|
|
282
|
-
Bad: \`\`\` echo hello \`\`\`
|
|
283
|
-
Good: \`\`\`bash echo hello \`\`\``;
|
|
284
|
-
function buildPrompt(content, targetLang, hasPlaceholders, hasSentinels, templateContent, glossaryConfig) {
|
|
285
|
-
const template = templateContent || DEFAULT_TEMPLATE;
|
|
286
|
-
let systemPrompt = template
|
|
287
|
-
.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
288
|
-
.replace(/\{\{content\}\}/g, "");
|
|
289
|
-
if (glossaryConfig) {
|
|
290
|
-
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
291
|
-
if (glossarySection) {
|
|
292
|
-
systemPrompt += glossarySection;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
if (hasSentinels) {
|
|
296
|
-
systemPrompt +=
|
|
297
|
-
"\n\n## Block boundary markers (P-A4 v2)\n\n" +
|
|
298
|
-
"Lines containing the marker `<!--BB-->` are **block boundary markers** inserted\n" +
|
|
299
|
-
"by the translation pipeline to preserve newlines around structural elements.\n\n" +
|
|
300
|
-
"Rules for `<!--BB-->` markers (HTML comment form):\n" +
|
|
301
|
-
"- Output every `<!--BB-->` marker **verbatim and unchanged** in your translation.\n" +
|
|
302
|
-
"- Each marker must remain on its own line, in the same position relative to\n" +
|
|
303
|
-
" surrounding content.\n" +
|
|
304
|
-
"- Do not translate, remove, paraphrase, modify, normalize whitespace inside, or\n" +
|
|
305
|
-
" rename these markers.\n" +
|
|
306
|
-
"- Do not add new `<!--BB-->` markers; only preserve existing ones.\n\n" +
|
|
307
|
-
"Good example (correct preservation):\n" +
|
|
308
|
-
" Input:\n" +
|
|
309
|
-
" <!--BB-->\n" +
|
|
310
|
-
" - List item one\n" +
|
|
311
|
-
" <!--BB-->\n" +
|
|
312
|
-
" - List item two\n" +
|
|
313
|
-
" <!--BB-->\n" +
|
|
314
|
-
" ## Section heading\n" +
|
|
315
|
-
" Output:\n" +
|
|
316
|
-
" <!--BB-->\n" +
|
|
317
|
-
" - リスト項目その一\n" +
|
|
318
|
-
" <!--BB-->\n" +
|
|
319
|
-
" - リスト項目その二\n" +
|
|
320
|
-
" <!--BB-->\n" +
|
|
321
|
-
" ## セクション見出し\n\n" +
|
|
322
|
-
"Bad examples (DO NOT do these):\n" +
|
|
323
|
-
" - <!--BB--> ❌ → <!--BB__--> (added suffix — FORBIDDEN)\n" +
|
|
324
|
-
" - <!--BB--> ❌ → <!-- BB --> (added internal whitespace — FORBIDDEN)\n" +
|
|
325
|
-
" - <!--BB--> ❌ → <!--bb--> (case change — FORBIDDEN)\n" +
|
|
326
|
-
" - <!--BB--> ❌ → (omitted) (deleted — FORBIDDEN)\n" +
|
|
327
|
-
" - <!--BB--> ❌ → <!--BB-x--> (added suffix — FORBIDDEN)\n\n" +
|
|
328
|
-
"Preserve the marker exactly: 9 characters, opening `<!--`, content `BB`,\n" +
|
|
329
|
-
"closing `-->`, no whitespace, no case changes, no suffixes.\n\n" +
|
|
330
|
-
"## List boundary protection (P-A4 v3 list addendum)\n\n" +
|
|
331
|
-
"For list items (lines starting with `-`, `*`, `+`, or `1.`),\n" +
|
|
332
|
-
"`<!--BB-->` markers appear **multiple times in a row** (e.g., two consecutive\n" +
|
|
333
|
-
"`<!--BB-->` lines). This is intentional — preserve ALL of them.\n\n" +
|
|
334
|
-
"Bad example (DO NOT do this):\n" +
|
|
335
|
-
" <!--BB-->\n" +
|
|
336
|
-
" <!--BB-->\n" +
|
|
337
|
-
" - Item A\n" +
|
|
338
|
-
" <!--BB-->\n" +
|
|
339
|
-
" <!--BB-->\n" +
|
|
340
|
-
" - Item B\n\n" +
|
|
341
|
-
" ❌ becomes: - Item A- Item B (list items on one line — FORBIDDEN)\n\n" +
|
|
342
|
-
"Good example (keep each item on its own line):\n" +
|
|
343
|
-
" <!--BB-->\n" +
|
|
344
|
-
" <!--BB-->\n" +
|
|
345
|
-
" - アイテムA\n" +
|
|
346
|
-
" <!--BB-->\n" +
|
|
347
|
-
" <!--BB-->\n" +
|
|
348
|
-
" - アイテムB\n\n" +
|
|
349
|
-
"Key rules for lists:\n" +
|
|
350
|
-
"- Each list item MUST remain on its own line.\n" +
|
|
351
|
-
"- NEVER join two list items into one line (e.g., `- A- B` is FORBIDDEN).\n" +
|
|
352
|
-
"- Preserve ALL `<!--BB-->` markers, even when they appear consecutively.\n\n" +
|
|
353
|
-
"Bad example (DO NOT do this) — inline code list collapse:\n" +
|
|
354
|
-
" - Item A: `value 1`\n" +
|
|
355
|
-
" - Item B: `value 2`\n\n" +
|
|
356
|
-
" ❌ becomes: - Item A: `value 1`- Item B: `value 2` (FORBIDDEN, space before marker)\n" +
|
|
357
|
-
" ❌ becomes: - Item A: `value 1`-Item B: `value 2` (FORBIDDEN, no space)\n\n" +
|
|
358
|
-
"Good example: each list item must remain on its own line, even when items contain inline code:\n" +
|
|
359
|
-
" - アイテムA: `value 1`\n" +
|
|
360
|
-
" - アイテムB: `value 2`";
|
|
361
|
-
}
|
|
362
|
-
if (hasPlaceholders) {
|
|
363
|
-
systemPrompt +=
|
|
364
|
-
"\n\nIMPORTANT - Placeholder preservation:\n" +
|
|
365
|
-
"- Tokens matching __CODE_BLOCK_N__ or __INLINE_CODE_N__ are placeholders for code blocks/inline code.\n" +
|
|
366
|
-
"- Output them VERBATIM and UNCHANGED. Do NOT translate, modify, or remove them.\n" +
|
|
367
|
-
"- Example: if input has __CODE_BLOCK_0__, output must contain __CODE_BLOCK_0__ exactly.";
|
|
368
|
-
}
|
|
369
|
-
return [
|
|
370
|
-
{ role: "system", content: systemPrompt },
|
|
371
|
-
{ role: "user", content },
|
|
372
|
-
];
|
|
373
|
-
}
|
|
374
|
-
function resolveOutputPath(inputPath, targetLang, outputPath) {
|
|
375
|
-
if (outputPath)
|
|
376
|
-
return outputPath;
|
|
377
|
-
const dir = dirname(inputPath);
|
|
378
|
-
const ext = extname(inputPath);
|
|
379
|
-
const base = basename(inputPath, ext);
|
|
380
|
-
return join(dir, `${base}.${targetLang}${ext}`);
|
|
381
|
-
}
|
|
27
|
+
// ─── Chunking utilities (kept for splitIntoChunks export) ───────────────────
|
|
382
28
|
/**
|
|
383
29
|
* Find positions (line indices) of Markdown headings at the given level,
|
|
384
30
|
* excluding lines inside fenced code blocks or table rows.
|
|
@@ -389,7 +35,7 @@ export function findHeadingPositions(lines, level) {
|
|
|
389
35
|
const prefix = "#".repeat(level) + " ";
|
|
390
36
|
for (let i = 0; i < lines.length; i++) {
|
|
391
37
|
const line = lines[i];
|
|
392
|
-
if (
|
|
38
|
+
if (/^(`{3,}|~{3,})/.test(line))
|
|
393
39
|
inCodeBlock = !inCodeBlock;
|
|
394
40
|
if (inCodeBlock)
|
|
395
41
|
continue;
|
|
@@ -401,8 +47,8 @@ export function findHeadingPositions(lines, level) {
|
|
|
401
47
|
return positions;
|
|
402
48
|
}
|
|
403
49
|
/**
|
|
404
|
-
* Split lines at the given positions into chunks
|
|
405
|
-
*
|
|
50
|
+
* Split lines at the given positions into chunks. Segments exceeding maxChunkLines
|
|
51
|
+
* are further split using ### headings or safeSplitLines.
|
|
406
52
|
*/
|
|
407
53
|
export function splitAtPositions(lines, positions, maxChunkLines) {
|
|
408
54
|
const result = [];
|
|
@@ -417,8 +63,6 @@ export function splitAtPositions(lines, positions, maxChunkLines) {
|
|
|
417
63
|
continue;
|
|
418
64
|
if (segmentLines.length > maxChunkLines) {
|
|
419
65
|
const subPositions = findHeadingPositions(segmentLines, 3);
|
|
420
|
-
// Filter out position 0: splitting at the start doesn't reduce segment size
|
|
421
|
-
// and causes infinite recursion when the only heading is at position 0.
|
|
422
66
|
const effectivePositions = subPositions.filter((p) => p > 0);
|
|
423
67
|
if (effectivePositions.length > 0) {
|
|
424
68
|
result.push(...splitAtPositions(segmentLines, effectivePositions, maxChunkLines));
|
|
@@ -443,12 +87,8 @@ export function safeSplitLines(lines, maxChunkLines) {
|
|
|
443
87
|
let inCodeBlock = false;
|
|
444
88
|
for (let i = 0; i < lines.length; i++) {
|
|
445
89
|
const line = lines[i];
|
|
446
|
-
const isFence =
|
|
90
|
+
const isFence = /^(`{3,}|~{3,})/.test(line);
|
|
447
91
|
const isTableLine = line.startsWith("|");
|
|
448
|
-
// Check split eligibility BEFORE toggling fence state:
|
|
449
|
-
// - never split inside a code block
|
|
450
|
-
// - never split ON a fence line (would separate opening/closing ``` from their block)
|
|
451
|
-
// - never split ON a table row
|
|
452
92
|
const canSplitHere = !inCodeBlock && !isFence && !isTableLine;
|
|
453
93
|
if (isFence)
|
|
454
94
|
inCodeBlock = !inCodeBlock;
|
|
@@ -463,8 +103,7 @@ export function safeSplitLines(lines, maxChunkLines) {
|
|
|
463
103
|
return chunks.filter((c) => c.trim().length > 0);
|
|
464
104
|
}
|
|
465
105
|
/**
|
|
466
|
-
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk
|
|
467
|
-
* as long as the merged result does not exceed maxLines.
|
|
106
|
+
* Merge chunks smaller than MIN_CHUNK_LINES into the previous chunk.
|
|
468
107
|
*/
|
|
469
108
|
export function mergeSmallChunks(chunks, maxLines) {
|
|
470
109
|
if (chunks.length <= 1)
|
|
@@ -500,9 +139,290 @@ export function splitIntoChunks(content, maxChunkLines = DEFAULT_MAX_CHUNK_LINES
|
|
|
500
139
|
}
|
|
501
140
|
return safeSplitLines(lines, maxChunkLines);
|
|
502
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Replace fenced code blocks and inline code with placeholders.
|
|
144
|
+
* Used by glossary-fix.ts to protect code blocks before text replacement.
|
|
145
|
+
*/
|
|
146
|
+
export function protectCodeBlocks(content) {
|
|
147
|
+
const map = new Map();
|
|
148
|
+
let blockIndex = 0;
|
|
149
|
+
let inlineIndex = 0;
|
|
150
|
+
const lines = content.split("\n");
|
|
151
|
+
const resultLines = [];
|
|
152
|
+
let fenceOpen = null;
|
|
153
|
+
let blockLines = [];
|
|
154
|
+
for (const line of lines) {
|
|
155
|
+
const fenceMatch = line.match(/^(`{3,})/);
|
|
156
|
+
if (fenceOpen === null) {
|
|
157
|
+
if (fenceMatch) {
|
|
158
|
+
fenceOpen = fenceMatch[1];
|
|
159
|
+
blockLines = [line];
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
resultLines.push(line);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
blockLines.push(line);
|
|
167
|
+
if (fenceMatch && fenceMatch[1].length >= fenceOpen.length && line.trim() === fenceMatch[1]) {
|
|
168
|
+
const original = blockLines.join("\n") + "\n";
|
|
169
|
+
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
170
|
+
map.set(placeholder, original);
|
|
171
|
+
resultLines.push(placeholder);
|
|
172
|
+
fenceOpen = null;
|
|
173
|
+
blockLines = [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (fenceOpen !== null) {
|
|
178
|
+
resultLines.push(...blockLines);
|
|
179
|
+
}
|
|
180
|
+
let result = resultLines.join("\n");
|
|
181
|
+
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
182
|
+
const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
|
|
183
|
+
map.set(placeholder, match);
|
|
184
|
+
return placeholder;
|
|
185
|
+
});
|
|
186
|
+
return { text: result, map };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Restore placeholders back to original code blocks/inline code.
|
|
190
|
+
*/
|
|
191
|
+
export function restoreCodeBlocks(content, map) {
|
|
192
|
+
let result = content;
|
|
193
|
+
for (const [placeholder, original] of map.entries()) {
|
|
194
|
+
if (original.endsWith("\n")) {
|
|
195
|
+
result = result.split(placeholder + "\n").join(original);
|
|
196
|
+
result = result.split(placeholder).join(original);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
result = result.split(placeholder + "\n").join(original + "\n");
|
|
200
|
+
result = result.split(placeholder).join(original);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Extract all translatable text nodes from an mdast AST.
|
|
207
|
+
* remark AST guarantees text nodes cannot be inside code/inlineCode nodes,
|
|
208
|
+
* so we only skip empty/whitespace-only nodes.
|
|
209
|
+
*/
|
|
210
|
+
function extractTextNodes(ast) {
|
|
211
|
+
const nodes = [];
|
|
212
|
+
visit(ast, "text", (node) => {
|
|
213
|
+
if (!node.value.trim())
|
|
214
|
+
return;
|
|
215
|
+
nodes.push({ node, id: nodes.length });
|
|
216
|
+
});
|
|
217
|
+
return nodes;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Build system prompt for text-mode batch translation (Gemini / Ollama fallback).
|
|
221
|
+
* Includes JSON format instructions since we're relying on the LLM to output JSON.
|
|
222
|
+
*/
|
|
223
|
+
function buildBatchSystemPrompt(targetLang, templateContent, glossaryConfig) {
|
|
224
|
+
const basePrompt = templateContent
|
|
225
|
+
? templateContent.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
226
|
+
: `You are a professional translator. Translate text segments to ${targetLang}.
|
|
227
|
+
|
|
228
|
+
Rules:
|
|
229
|
+
- Translate only the text content; do not add or remove punctuation structure
|
|
230
|
+
- Preserve proper nouns, code identifiers, URLs, and file paths unchanged
|
|
231
|
+
- Produce natural, fluent text in the target language
|
|
232
|
+
- For Japanese: use full-width punctuation (。、?!), add half-width spaces around English words/numbers
|
|
233
|
+
- Keep product names, abbreviations, and technical terms unchanged (e.g., NGSI-LD, MCP, GeoJSON)`;
|
|
234
|
+
let prompt = basePrompt;
|
|
235
|
+
if (glossaryConfig) {
|
|
236
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
237
|
+
if (glossarySection)
|
|
238
|
+
prompt += glossarySection;
|
|
239
|
+
}
|
|
240
|
+
prompt += `
|
|
241
|
+
|
|
242
|
+
## Translation format
|
|
243
|
+
|
|
244
|
+
You will receive a JSON object with a "segments" array.
|
|
245
|
+
Each segment has an "id" (integer) and "text" (string to translate).
|
|
246
|
+
|
|
247
|
+
Return ONLY a valid JSON object with a "translations" array.
|
|
248
|
+
Each translation must have the same "id" and the translated "text".
|
|
249
|
+
Do not include any explanation, markdown, or text outside the JSON object.
|
|
250
|
+
|
|
251
|
+
Example input:
|
|
252
|
+
{"segments": [{"id": 0, "text": "Hello world"}, {"id": 1, "text": "This is a test."}]}
|
|
253
|
+
|
|
254
|
+
Example output:
|
|
255
|
+
{"translations": [{"id": 0, "text": "こんにちは世界"}, {"id": 1, "text": "これはテストです。"}]}`;
|
|
256
|
+
return prompt;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Build system prompt for structured output translation (Claude tool_use path).
|
|
260
|
+
* No JSON format instructions needed — the tool schema enforces the response shape.
|
|
261
|
+
*/
|
|
262
|
+
function buildStructuredSystemPrompt(targetLang, templateContent, glossaryConfig) {
|
|
263
|
+
const basePrompt = templateContent
|
|
264
|
+
? templateContent.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
265
|
+
: `You are a professional translator. Translate each text segment to ${targetLang}.
|
|
266
|
+
|
|
267
|
+
Rules:
|
|
268
|
+
- Translate only the text content; do not alter structure or punctuation outside the text
|
|
269
|
+
- Preserve proper nouns, code identifiers, URLs, and file paths unchanged
|
|
270
|
+
- Produce natural, fluent text in the target language
|
|
271
|
+
- For Japanese: use full-width punctuation (。、?!), add half-width spaces around English words/numbers
|
|
272
|
+
- Keep product names, abbreviations, and technical terms unchanged (e.g., NGSI-LD, MCP, GeoJSON)
|
|
273
|
+
- Each segment is independent; translate it on its own`;
|
|
274
|
+
let prompt = basePrompt;
|
|
275
|
+
if (glossaryConfig) {
|
|
276
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
277
|
+
if (glossarySection)
|
|
278
|
+
prompt += glossarySection;
|
|
279
|
+
}
|
|
280
|
+
return prompt;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Parse translation JSON response from LLM (text mode fallback).
|
|
284
|
+
* Handles both clean JSON and JSON embedded in prose (extracts first {...} block).
|
|
285
|
+
*/
|
|
286
|
+
function parseTranslationResponse(raw) {
|
|
287
|
+
const trimmed = raw.trim();
|
|
288
|
+
try {
|
|
289
|
+
return JSON.parse(trimmed);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Extract first JSON object if LLM added prose around it
|
|
293
|
+
const jsonMatch = trimmed.match(/\{[\s\S]*\}/);
|
|
294
|
+
if (jsonMatch) {
|
|
295
|
+
return JSON.parse(jsonMatch[0]);
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`Failed to parse translation response: ${trimmed.slice(0, 200)}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function assertValidTranslations(value) {
|
|
301
|
+
if (!Array.isArray(value) ||
|
|
302
|
+
value.some((item) => {
|
|
303
|
+
if (typeof item !== "object" || item === null)
|
|
304
|
+
return true;
|
|
305
|
+
const candidate = item;
|
|
306
|
+
return typeof candidate.id !== "number" || typeof candidate.text !== "string";
|
|
307
|
+
})) {
|
|
308
|
+
throw new Error("[yuuhitsu] translateBatch: invalid translation payload — expected Array<{id: number, text: string}>");
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Translate a batch of text segments using the provider.
|
|
313
|
+
*
|
|
314
|
+
* - If the provider implements `translateStructured` (Claude): uses tool_use to
|
|
315
|
+
* enforce the JSON schema at the API level, guaranteeing 1:1 ID mapping.
|
|
316
|
+
* - Otherwise: falls back to text-mode JSON prompt (Gemini / Ollama).
|
|
317
|
+
*
|
|
318
|
+
* In both paths the 1:1 ID mapping is validated and an error is thrown on mismatch.
|
|
319
|
+
*/
|
|
320
|
+
async function translateBatch(provider, nodes, targetLang, templateContent, glossaryConfig) {
|
|
321
|
+
if (nodes.length === 0) {
|
|
322
|
+
return { usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 } };
|
|
323
|
+
}
|
|
324
|
+
const segments = nodes.map(({ node, id }) => ({ id, text: node.value }));
|
|
325
|
+
// P-A1: track total input character count for truncation detection
|
|
326
|
+
const totalInputChars = segments.reduce((sum, s) => sum + s.text.length, 0);
|
|
327
|
+
let translations;
|
|
328
|
+
let usage;
|
|
329
|
+
if (provider.translateStructured) {
|
|
330
|
+
// Structured output path: provider (Claude) enforces JSON schema via tool_use
|
|
331
|
+
const systemPrompt = buildStructuredSystemPrompt(targetLang, templateContent, glossaryConfig);
|
|
332
|
+
const result = await provider.translateStructured({ segments, systemPrompt });
|
|
333
|
+
assertValidTranslations(result.translations);
|
|
334
|
+
translations = result.translations;
|
|
335
|
+
usage = result.usage;
|
|
336
|
+
// P-A1: warn on truncation (compare translated chars to input chars)
|
|
337
|
+
const totalOutputChars = translations.reduce((sum, t) => sum + t.text.length, 0);
|
|
338
|
+
if (totalInputChars > 0 && totalOutputChars < totalInputChars * MIN_OUTPUT_RATIO) {
|
|
339
|
+
console.warn(`[yuuhitsu] translateBatch: output may be truncated ` +
|
|
340
|
+
`(input chars: ${totalInputChars}, output chars: ${totalOutputChars})`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
// Text mode fallback: Gemini / Ollama
|
|
345
|
+
const systemPrompt = buildBatchSystemPrompt(targetLang, templateContent, glossaryConfig);
|
|
346
|
+
const messages = [
|
|
347
|
+
{ role: "system", content: systemPrompt },
|
|
348
|
+
{ role: "user", content: JSON.stringify({ segments }) },
|
|
349
|
+
];
|
|
350
|
+
const response = await provider.chat({ model: "", messages });
|
|
351
|
+
const parsed = parseTranslationResponse(response.content);
|
|
352
|
+
assertValidTranslations(parsed.translations);
|
|
353
|
+
// P-A1: warn on truncation (compare translated text chars, not raw JSON string length)
|
|
354
|
+
const totalOutputChars = parsed.translations.reduce((sum, t) => sum + t.text.length, 0);
|
|
355
|
+
if (totalInputChars > 0 && totalOutputChars < totalInputChars * MIN_OUTPUT_RATIO) {
|
|
356
|
+
console.warn(`[yuuhitsu] translateBatch: output may be truncated ` +
|
|
357
|
+
`(input chars: ${totalInputChars}, output chars: ${totalOutputChars})`);
|
|
358
|
+
}
|
|
359
|
+
translations = parsed.translations;
|
|
360
|
+
usage = response.usage;
|
|
361
|
+
}
|
|
362
|
+
// Validate strict 1:1 ID mapping (both paths):
|
|
363
|
+
// - no duplicate output IDs (Map silently overwrites; we must detect before)
|
|
364
|
+
// - no unexpected IDs (IDs not present in the input set)
|
|
365
|
+
// - no missing IDs (input ID absent from output)
|
|
366
|
+
const inputIds = new Set(nodes.map(({ id }) => id));
|
|
367
|
+
const seenOutputIds = new Set();
|
|
368
|
+
const duplicateIds = [];
|
|
369
|
+
const unexpectedIds = [];
|
|
370
|
+
for (const t of translations) {
|
|
371
|
+
if (seenOutputIds.has(t.id)) {
|
|
372
|
+
duplicateIds.push(t.id);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
seenOutputIds.add(t.id);
|
|
376
|
+
}
|
|
377
|
+
if (!inputIds.has(t.id)) {
|
|
378
|
+
unexpectedIds.push(t.id);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (duplicateIds.length > 0) {
|
|
382
|
+
throw new Error(`[yuuhitsu] translateBatch: duplicate IDs in response (IDs: ${duplicateIds.join(", ")})`);
|
|
383
|
+
}
|
|
384
|
+
if (unexpectedIds.length > 0) {
|
|
385
|
+
throw new Error(`[yuuhitsu] translateBatch: unexpected IDs in response (IDs: ${unexpectedIds.join(", ")})`);
|
|
386
|
+
}
|
|
387
|
+
const translationMap = new Map(translations.map((t) => [t.id, t.text]));
|
|
388
|
+
const missingIds = nodes.filter(({ id }) => !translationMap.has(id)).map(({ id }) => id);
|
|
389
|
+
if (missingIds.length > 0) {
|
|
390
|
+
throw new Error(`[yuuhitsu] translateBatch: partial translation — ${missingIds.length} node(s) missing` +
|
|
391
|
+
` from response (IDs: ${missingIds.join(", ")})`);
|
|
392
|
+
}
|
|
393
|
+
// Apply translations back to AST nodes
|
|
394
|
+
for (const { node, id } of nodes) {
|
|
395
|
+
const translated = translationMap.get(id);
|
|
396
|
+
if (translated !== undefined && translated.trim()) {
|
|
397
|
+
node.value = translated;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return { usage };
|
|
401
|
+
}
|
|
402
|
+
function resolveOutputPath(inputPath, targetLang, outputPath) {
|
|
403
|
+
if (outputPath)
|
|
404
|
+
return outputPath;
|
|
405
|
+
const dir = dirname(inputPath);
|
|
406
|
+
const ext = extname(inputPath);
|
|
407
|
+
const base = basename(inputPath, ext);
|
|
408
|
+
return join(dir, `${base}.${targetLang}${ext}`);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Translate a Markdown file using AST-based approach.
|
|
412
|
+
*
|
|
413
|
+
* Architecture (0.2.0):
|
|
414
|
+
* 1. Separate frontmatter (preserved verbatim)
|
|
415
|
+
* 2. Split body into chunks by heading boundaries
|
|
416
|
+
* 3. For each chunk: parse to AST → extract text nodes → translate via LLM → write back
|
|
417
|
+
* 4. Serialize AST → markdown → concatenate → write output
|
|
418
|
+
*
|
|
419
|
+
* Key properties:
|
|
420
|
+
* - Code blocks (fenced and inline) are never sent to LLM (AST handles them deterministically)
|
|
421
|
+
* - Markdown structure (headings, lists, tables, HR) is preserved by AST round-trip
|
|
422
|
+
* - No sentinel injection or removal needed
|
|
423
|
+
*/
|
|
503
424
|
export async function translateFile(options) {
|
|
504
|
-
const { provider, inputPath, targetLang, templateContent, glossaryConfig, maxChunkLines } = options;
|
|
505
|
-
// Read input file
|
|
425
|
+
const { provider, inputPath, targetLang, templateContent, glossaryConfig, maxChunkLines, } = options;
|
|
506
426
|
let content;
|
|
507
427
|
try {
|
|
508
428
|
content = readFileSync(inputPath, "utf-8");
|
|
@@ -513,46 +433,41 @@ export async function translateFile(options) {
|
|
|
513
433
|
}
|
|
514
434
|
throw err;
|
|
515
435
|
}
|
|
516
|
-
// Check for empty file
|
|
517
436
|
if (content.trim().length === 0) {
|
|
518
437
|
throw new Error(`Input file is empty: ${inputPath}`);
|
|
519
438
|
}
|
|
520
439
|
const resolvedOutput = resolveOutputPath(inputPath, targetLang, options.outputPath);
|
|
521
|
-
// Ensure output directory exists
|
|
522
440
|
mkdirSync(dirname(resolvedOutput), { recursive: true });
|
|
523
|
-
// Separate frontmatter from body
|
|
524
441
|
const { frontmatter, body } = separateFrontmatter(content);
|
|
525
|
-
//
|
|
526
|
-
const
|
|
527
|
-
const
|
|
528
|
-
// Protect block boundaries: insert %%BB%% sentinels before structural elements (P-A4)
|
|
529
|
-
const bodyWithSentinels = protectBlockBoundaries(protectedBody);
|
|
530
|
-
const hasSentinels = bodyWithSentinels.includes(BLOCK_BOUNDARY_SENTINEL);
|
|
531
|
-
// Split body into chunks if needed (frontmatter is never sent to LLM)
|
|
532
|
-
const chunks = splitIntoChunks(bodyWithSentinels, maxChunkLines);
|
|
533
|
-
const translatedParts = [];
|
|
442
|
+
// Split body into text chunks (heading-based, same as before)
|
|
443
|
+
const chunks = splitIntoChunks(body, maxChunkLines ?? DEFAULT_MAX_CHUNK_LINES);
|
|
444
|
+
const translatedChunks = [];
|
|
534
445
|
let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
535
446
|
for (const chunk of chunks) {
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
447
|
+
// Parse chunk to AST (code blocks, inline code become typed nodes → never reach LLM)
|
|
448
|
+
const processor = remark().use(remarkGfm);
|
|
449
|
+
const ast = processor.parse(chunk);
|
|
450
|
+
// Extract translatable text nodes
|
|
451
|
+
const textNodes = extractTextNodes(ast);
|
|
452
|
+
if (textNodes.length > 0) {
|
|
453
|
+
const { usage } = await translateBatch(provider, textNodes, targetLang, templateContent, glossaryConfig);
|
|
454
|
+
totalUsage.promptTokens += usage.promptTokens;
|
|
455
|
+
totalUsage.completionTokens += usage.completionTokens;
|
|
456
|
+
totalUsage.totalTokens += usage.totalTokens;
|
|
457
|
+
}
|
|
458
|
+
// Serialize AST back to markdown
|
|
459
|
+
const translatedChunk = processor.stringify(ast);
|
|
460
|
+
translatedChunks.push(translatedChunk);
|
|
545
461
|
}
|
|
546
|
-
//
|
|
547
|
-
//
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
462
|
+
// Join chunks: normalize each chunk to exactly one trailing newline
|
|
463
|
+
// (preserves trailing spaces for Markdown hard line breaks), then join
|
|
464
|
+
// with a single "\n" so chunk boundaries produce exactly one blank line.
|
|
465
|
+
const translatedBody = translatedChunks
|
|
466
|
+
.map((c) => c.replace(/\n+$/, "\n"))
|
|
467
|
+
.join("\n");
|
|
552
468
|
const translatedContent = frontmatter
|
|
553
469
|
? frontmatter + translatedBody
|
|
554
470
|
: translatedBody;
|
|
555
|
-
// Write output
|
|
556
471
|
writeFileSync(resolvedOutput, translatedContent, "utf-8");
|
|
557
472
|
return {
|
|
558
473
|
outputPath: resolvedOutput,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geolonia/yuuhitsu",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "右筆 (Yuuhitsu) - AI-powered document operations CLI. Translate, generate, and sync documents using Claude, Gemini, or Ollama.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
"dotenv": "^16.4.0",
|
|
37
37
|
"fast-glob": "^3.3.3",
|
|
38
38
|
"openai": "^4.77.0",
|
|
39
|
+
"remark": "^15.0.1",
|
|
40
|
+
"remark-gfm": "^4.0.1",
|
|
41
|
+
"unist-util-visit": "^5.1.0",
|
|
39
42
|
"yaml": "^2.7.0"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
@@ -43,5 +46,9 @@
|
|
|
43
46
|
"tsx": "^4.19.0",
|
|
44
47
|
"typescript": "^5.7.0",
|
|
45
48
|
"vitest": "^3.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"registry": "https://registry.npmjs.org/"
|
|
46
53
|
}
|
|
47
54
|
}
|