@geolonia/yuuhitsu 0.1.0 → 0.1.2
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/LICENSE +0 -0
- package/README.md +114 -0
- package/dist/cli/commands/glossary.d.ts +3 -0
- package/dist/cli/commands/glossary.d.ts.map +1 -0
- package/dist/cli/commands/glossary.js +110 -0
- package/dist/cli/commands/glossary.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +82 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/translate.d.ts +0 -0
- package/dist/cli/commands/translate.d.ts.map +1 -1
- package/dist/cli/commands/translate.js +53 -26
- package/dist/cli/commands/translate.js.map +1 -1
- package/dist/cli/index.d.ts +0 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +0 -0
- package/dist/errors.d.ts.map +0 -0
- package/dist/errors.js +0 -0
- package/dist/errors.js.map +0 -0
- package/dist/logger.d.ts +0 -0
- package/dist/logger.d.ts.map +0 -0
- package/dist/logger.js +0 -0
- package/dist/logger.js.map +0 -0
- package/dist/provider/claude.d.ts +0 -0
- package/dist/provider/claude.d.ts.map +0 -0
- package/dist/provider/claude.js +0 -0
- package/dist/provider/claude.js.map +0 -0
- package/dist/provider/gemini.d.ts +0 -0
- package/dist/provider/gemini.d.ts.map +0 -0
- package/dist/provider/gemini.js +0 -0
- package/dist/provider/gemini.js.map +0 -0
- package/dist/provider/index.d.ts +0 -0
- package/dist/provider/index.d.ts.map +0 -0
- package/dist/provider/index.js +0 -0
- package/dist/provider/index.js.map +0 -0
- package/dist/provider/interface.d.ts +0 -0
- package/dist/provider/interface.d.ts.map +0 -0
- package/dist/provider/interface.js +0 -0
- package/dist/provider/interface.js.map +0 -0
- package/dist/provider/ollama.d.ts +0 -0
- package/dist/provider/ollama.d.ts.map +0 -0
- package/dist/provider/ollama.js +0 -0
- package/dist/provider/ollama.js.map +0 -0
- package/dist/tasks/batch-translate.d.ts +46 -0
- package/dist/tasks/batch-translate.d.ts.map +1 -0
- package/dist/tasks/batch-translate.js +174 -0
- package/dist/tasks/batch-translate.js.map +1 -0
- package/dist/tasks/glossary.d.ts +41 -0
- package/dist/tasks/glossary.d.ts.map +1 -0
- package/dist/tasks/glossary.js +273 -0
- package/dist/tasks/glossary.js.map +1 -0
- package/dist/tasks/stream.d.ts +0 -0
- package/dist/tasks/stream.d.ts.map +0 -0
- package/dist/tasks/stream.js +0 -0
- package/dist/tasks/stream.js.map +0 -0
- package/dist/tasks/translate.d.ts +27 -0
- package/dist/tasks/translate.d.ts.map +1 -1
- package/dist/tasks/translate.js +101 -7
- package/dist/tasks/translate.js.map +1 -1
- package/package.json +14 -8
- package/src/templates/fix-links.md +0 -0
- package/src/templates/generate-docs.md +0 -0
- package/src/templates/generate-tests.md +0 -0
- package/src/templates/research.md +0 -0
- package/src/templates/sync-docs.md +0 -0
- package/src/templates/translate.md +8 -0
package/dist/tasks/translate.js
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
2
|
import { dirname, basename, extname, join } from "path";
|
|
3
|
+
import { buildGlossaryPrompt } from "./glossary.js";
|
|
3
4
|
const CHUNK_SIZE = 50 * 1024; // 50KB
|
|
5
|
+
/**
|
|
6
|
+
* Separate frontmatter from Markdown content
|
|
7
|
+
* Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
|
|
8
|
+
* @param content - Full Markdown content
|
|
9
|
+
* @returns Object with separated frontmatter and body
|
|
10
|
+
*/
|
|
11
|
+
export function separateFrontmatter(content) {
|
|
12
|
+
// Normalize CRLF to LF for regex matching
|
|
13
|
+
const normalized = content.replace(/\r\n/g, "\n");
|
|
14
|
+
// Match frontmatter (two alternations to keep closing --- on its own line):
|
|
15
|
+
// Case 1: non-empty body: ^---\n ... \n---[ \t]*(\n|$)
|
|
16
|
+
// Case 2: empty body: ^---\n---[ \t]*(\n|$)
|
|
17
|
+
// Using alternation avoids the \n? ambiguity that allows --- to match mid-line.
|
|
18
|
+
const frontmatterRegex = /^---\n([\s\S]*?)\n---[ \t]*(\n|$)|^---\n---[ \t]*(\n|$)/;
|
|
19
|
+
const match = normalized.match(frontmatterRegex);
|
|
20
|
+
if (match) {
|
|
21
|
+
const matchedLength = match[0].length;
|
|
22
|
+
const frontmatter = normalized.slice(0, matchedLength);
|
|
23
|
+
const body = normalized.slice(matchedLength);
|
|
24
|
+
return { frontmatter, body };
|
|
25
|
+
}
|
|
26
|
+
return { frontmatter: null, body: normalized };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Replace fenced code blocks and inline code with placeholders.
|
|
30
|
+
* Fenced blocks (``` or ````+) take priority over inline code.
|
|
31
|
+
*/
|
|
32
|
+
export function protectCodeBlocks(content) {
|
|
33
|
+
const map = new Map();
|
|
34
|
+
let blockIndex = 0;
|
|
35
|
+
let inlineIndex = 0;
|
|
36
|
+
// Step 1: Replace fenced code blocks (4+ backticks before 3-backtick blocks)
|
|
37
|
+
// Matches ````+ ... ```` or ``` ... ``` (non-greedy, multiline)
|
|
38
|
+
// Preserve the original line count by repeating newlines so subsequent line numbers stay correct.
|
|
39
|
+
let result = content.replace(/(`{3,})[^\n]*\n[\s\S]*?\1[ \t]*(\n|$)/g, (match) => {
|
|
40
|
+
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
41
|
+
map.set(placeholder, match);
|
|
42
|
+
const newlineCount = (match.match(/\n/g) ?? []).length;
|
|
43
|
+
return placeholder + "\n".repeat(newlineCount);
|
|
44
|
+
});
|
|
45
|
+
// Step 2: Replace inline code (single backtick, not within code blocks)
|
|
46
|
+
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
47
|
+
const placeholder = `__INLINE_CODE_${inlineIndex++}__`;
|
|
48
|
+
map.set(placeholder, match);
|
|
49
|
+
return placeholder;
|
|
50
|
+
});
|
|
51
|
+
return { text: result, map };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Restore placeholders back to original code blocks/inline code.
|
|
55
|
+
*/
|
|
56
|
+
export function restoreCodeBlocks(content, map) {
|
|
57
|
+
let result = content;
|
|
58
|
+
// Restore fenced code blocks (may have trailing newline added by protect)
|
|
59
|
+
for (const [placeholder, original] of map.entries()) {
|
|
60
|
+
// The placeholder may appear with or without trailing newline
|
|
61
|
+
result = result.split(placeholder + "\n").join(original);
|
|
62
|
+
result = result.split(placeholder).join(original);
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
4
66
|
const DEFAULT_TEMPLATE = `You are a professional translator. Translate the following Markdown document to {{targetLanguage}}.
|
|
5
67
|
|
|
6
68
|
Rules:
|
|
@@ -10,16 +72,37 @@ Rules:
|
|
|
10
72
|
- Maintain the same document structure
|
|
11
73
|
- Produce natural, fluent text in the target language
|
|
12
74
|
|
|
75
|
+
CRITICAL - Link and URL preservation:
|
|
76
|
+
- NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
|
|
77
|
+
- NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
|
|
78
|
+
- NEVER convert external URLs to different language versions.
|
|
79
|
+
- If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
|
|
80
|
+
- Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
|
|
81
|
+
- Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
|
|
82
|
+
|
|
13
83
|
Additional rules for Japanese translation:
|
|
14
84
|
- Use full-width punctuation: 。、?! (not .,?!)
|
|
15
85
|
- Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
|
|
16
86
|
- Use natural Japanese terms for technical words where appropriate (e.g., "registration" → "登録", "subscription" → "サブスクリプション")
|
|
17
87
|
- Keep product names, proper nouns, and abbreviations unchanged (e.g., Vela, FIWARE, NGSIv2, NGSI-LD, MCP)`;
|
|
18
|
-
function buildPrompt(content, targetLang, templateContent) {
|
|
88
|
+
function buildPrompt(content, targetLang, hasPlaceholders, templateContent, glossaryConfig) {
|
|
19
89
|
const template = templateContent || DEFAULT_TEMPLATE;
|
|
20
|
-
|
|
90
|
+
let systemPrompt = template
|
|
21
91
|
.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
22
92
|
.replace(/\{\{content\}\}/g, "");
|
|
93
|
+
if (glossaryConfig) {
|
|
94
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
95
|
+
if (glossarySection) {
|
|
96
|
+
systemPrompt += glossarySection;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (hasPlaceholders) {
|
|
100
|
+
systemPrompt +=
|
|
101
|
+
"\n\nIMPORTANT - Placeholder preservation:\n" +
|
|
102
|
+
"- Tokens matching __CODE_BLOCK_N__ or __INLINE_CODE_N__ are placeholders for code blocks/inline code.\n" +
|
|
103
|
+
"- Output them VERBATIM and UNCHANGED. Do NOT translate, modify, or remove them.\n" +
|
|
104
|
+
"- Example: if input has __CODE_BLOCK_0__, output must contain __CODE_BLOCK_0__ exactly.";
|
|
105
|
+
}
|
|
23
106
|
return [
|
|
24
107
|
{ role: "system", content: systemPrompt },
|
|
25
108
|
{ role: "user", content },
|
|
@@ -55,7 +138,7 @@ function splitIntoChunks(content) {
|
|
|
55
138
|
return chunks;
|
|
56
139
|
}
|
|
57
140
|
export async function translateFile(options) {
|
|
58
|
-
const { provider, inputPath, targetLang, templateContent } = options;
|
|
141
|
+
const { provider, inputPath, targetLang, templateContent, glossaryConfig } = options;
|
|
59
142
|
// Read input file
|
|
60
143
|
let content;
|
|
61
144
|
try {
|
|
@@ -74,12 +157,17 @@ export async function translateFile(options) {
|
|
|
74
157
|
const resolvedOutput = resolveOutputPath(inputPath, targetLang, options.outputPath);
|
|
75
158
|
// Ensure output directory exists
|
|
76
159
|
mkdirSync(dirname(resolvedOutput), { recursive: true });
|
|
77
|
-
//
|
|
78
|
-
const
|
|
160
|
+
// Separate frontmatter from body
|
|
161
|
+
const { frontmatter, body } = separateFrontmatter(content);
|
|
162
|
+
// Protect code blocks: replace with placeholders before sending to LLM
|
|
163
|
+
const { text: protectedBody, map: codeMap } = protectCodeBlocks(body);
|
|
164
|
+
const hasPlaceholders = codeMap.size > 0;
|
|
165
|
+
// Split body into chunks if needed (frontmatter is never sent to LLM)
|
|
166
|
+
const chunks = splitIntoChunks(protectedBody);
|
|
79
167
|
const translatedParts = [];
|
|
80
168
|
let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
81
169
|
for (const chunk of chunks) {
|
|
82
|
-
const messages = buildPrompt(chunk, targetLang, templateContent);
|
|
170
|
+
const messages = buildPrompt(chunk, targetLang, hasPlaceholders, templateContent, glossaryConfig);
|
|
83
171
|
const response = await provider.chat({
|
|
84
172
|
model: "",
|
|
85
173
|
messages,
|
|
@@ -89,7 +177,13 @@ export async function translateFile(options) {
|
|
|
89
177
|
totalUsage.completionTokens += response.usage.completionTokens;
|
|
90
178
|
totalUsage.totalTokens += response.usage.totalTokens;
|
|
91
179
|
}
|
|
92
|
-
|
|
180
|
+
// Restore code blocks from placeholders
|
|
181
|
+
const translatedBodyWithPlaceholders = translatedParts.join("");
|
|
182
|
+
const translatedBody = restoreCodeBlocks(translatedBodyWithPlaceholders, codeMap);
|
|
183
|
+
// Recombine frontmatter with translated body
|
|
184
|
+
const translatedContent = frontmatter
|
|
185
|
+
? frontmatter + translatedBody
|
|
186
|
+
: translatedBody;
|
|
93
187
|
// Write output
|
|
94
188
|
writeFileSync(resolvedOutput, translatedContent, "utf-8");
|
|
95
189
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGxD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO;
|
|
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.1.
|
|
3
|
+
"version": "0.1.2",
|
|
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": {
|
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
"test:watch": "vitest",
|
|
15
15
|
"lint": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
|
-
"keywords": [
|
|
17
|
+
"keywords": [
|
|
18
|
+
"ai",
|
|
19
|
+
"cli",
|
|
20
|
+
"translation",
|
|
21
|
+
"documentation"
|
|
22
|
+
],
|
|
18
23
|
"license": "MIT",
|
|
19
24
|
"files": [
|
|
20
25
|
"dist",
|
|
@@ -25,16 +30,17 @@
|
|
|
25
30
|
"dependencies": {
|
|
26
31
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
27
32
|
"@google/genai": "^0.7.0",
|
|
28
|
-
"
|
|
33
|
+
"chalk": "^5.4.0",
|
|
29
34
|
"commander": "^13.0.0",
|
|
30
|
-
"yaml": "^2.7.0",
|
|
31
35
|
"dotenv": "^16.4.0",
|
|
32
|
-
"
|
|
36
|
+
"fast-glob": "^3.3.3",
|
|
37
|
+
"openai": "^4.77.0",
|
|
38
|
+
"yaml": "^2.7.0"
|
|
33
39
|
},
|
|
34
40
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
"typescript": "^5.7.0",
|
|
41
|
+
"@types/node": "^22.0.0",
|
|
37
42
|
"tsx": "^4.19.0",
|
|
38
|
-
"
|
|
43
|
+
"typescript": "^5.7.0",
|
|
44
|
+
"vitest": "^3.0.0"
|
|
39
45
|
}
|
|
40
46
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -7,6 +7,14 @@ Rules:
|
|
|
7
7
|
- Maintain the same document structure
|
|
8
8
|
- Produce natural, fluent text in the target language
|
|
9
9
|
|
|
10
|
+
CRITICAL - Link and URL preservation:
|
|
11
|
+
- NEVER modify any URLs or link paths. Keep all href/src values exactly as-is.
|
|
12
|
+
- NEVER change internal link paths (e.g., /ja/..., /en/..., ./relative-path). Preserve them verbatim.
|
|
13
|
+
- NEVER convert external URLs to different language versions.
|
|
14
|
+
- If the source has [text](/ja/changelog), the output must keep the same path, only translate the link text if needed.
|
|
15
|
+
- Example: [紹介](/ja/intro) → translate "紹介" but keep "/ja/intro" unchanged
|
|
16
|
+
- Example: [MDN](https://developer.mozilla.org/ja/) → keep the /ja/ in URL, translate "MDN" if needed
|
|
17
|
+
|
|
10
18
|
Additional rules for Japanese translation:
|
|
11
19
|
- Use full-width punctuation: 。、?! (not .,?!)
|
|
12
20
|
- Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
|