@geolonia/yuuhitsu 0.1.1 → 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/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/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -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/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/translate.d.ts +2 -0
- package/dist/tasks/translate.d.ts.map +1 -1
- package/dist/tasks/translate.js +13 -4
- package/dist/tasks/translate.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ AI-powered document operations CLI
|
|
|
9
9
|
### Key Capabilities
|
|
10
10
|
|
|
11
11
|
- **Markdown Translation**: Translate documents while preserving structure, code blocks, and formatting
|
|
12
|
+
- **Glossary Management**: Maintain consistent terminology across all translations with a project-level glossary
|
|
12
13
|
- **Multi-Provider Support**: Switch between Claude (Anthropic), Gemini (Google), and Ollama (local) with a single config line change
|
|
13
14
|
- **Streaming Output**: See translation progress in real-time
|
|
14
15
|
- **Dry-Run Mode**: Preview operations without making API calls
|
|
@@ -23,6 +24,18 @@ AI-powered document operations CLI
|
|
|
23
24
|
- Support for large files with automatic chunking
|
|
24
25
|
- Real-time streaming output
|
|
25
26
|
- Retry logic with exponential backoff for API failures
|
|
27
|
+
- Automatic glossary lookup during translation (when `glossary` is configured)
|
|
28
|
+
|
|
29
|
+
### Glossary Management (Available Now)
|
|
30
|
+
|
|
31
|
+
Maintain a project-level glossary to enforce consistent terminology across all translations.
|
|
32
|
+
|
|
33
|
+
- **`glossary init`**: Generate a `glossary.yaml` skeleton with example terms
|
|
34
|
+
- **`glossary check`**: Detect forbidden or inconsistent terms in a document
|
|
35
|
+
- **`glossary sync`**: Report translation coverage across all configured languages and create stubs for missing entries
|
|
36
|
+
- **`glossary review`**: Generate a Markdown report of all glossary terms and their translations
|
|
37
|
+
|
|
38
|
+
When a `glossary` path is set in `yuuhitsu.config.yaml`, the `translate` command automatically injects the glossary into the AI prompt, ensuring canonical terms are used and forbidden variants are avoided.
|
|
26
39
|
|
|
27
40
|
### Coming Soon
|
|
28
41
|
|
|
@@ -68,6 +81,7 @@ model: claude-sonnet-4-5-20250929
|
|
|
68
81
|
# Optional Settings
|
|
69
82
|
outputDir: ./translated
|
|
70
83
|
templates: ./templates
|
|
84
|
+
glossary: ./glossary.yaml # Path to glossary file (enables auto-injection during translation)
|
|
71
85
|
log:
|
|
72
86
|
enabled: true
|
|
73
87
|
path: ./yuuhitsu.log
|
|
@@ -124,6 +138,106 @@ yuuhitsu translate \
|
|
|
124
138
|
--model claude-sonnet-4-5-20250929
|
|
125
139
|
```
|
|
126
140
|
|
|
141
|
+
### `glossary`
|
|
142
|
+
|
|
143
|
+
Manage the project glossary for terminology consistency.
|
|
144
|
+
|
|
145
|
+
#### `glossary init`
|
|
146
|
+
|
|
147
|
+
Generate a `glossary.yaml` skeleton in the current directory.
|
|
148
|
+
|
|
149
|
+
**Options:**
|
|
150
|
+
|
|
151
|
+
- `--output <path>`: Output path for the glossary file (default: `glossary.yaml`)
|
|
152
|
+
- `--force`: Overwrite an existing glossary file
|
|
153
|
+
|
|
154
|
+
**Example:**
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
yuuhitsu glossary init
|
|
158
|
+
yuuhitsu glossary init --output ./docs/glossary.yaml
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `glossary check`
|
|
162
|
+
|
|
163
|
+
Detect forbidden or inconsistent terminology in a document.
|
|
164
|
+
|
|
165
|
+
**Options:**
|
|
166
|
+
|
|
167
|
+
- `--input <file>` (required): Document file to check
|
|
168
|
+
- `--glossary <path>` (required): Glossary file path
|
|
169
|
+
- `--lang <code>` (required): Language code to check (e.g., `ja`, `en`)
|
|
170
|
+
|
|
171
|
+
**Example:**
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `glossary sync`
|
|
178
|
+
|
|
179
|
+
Report translation coverage and create stubs for missing entries.
|
|
180
|
+
|
|
181
|
+
**Options:**
|
|
182
|
+
|
|
183
|
+
- `--glossary <path>` (required): Glossary file path
|
|
184
|
+
|
|
185
|
+
**Example:**
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
yuuhitsu glossary sync --glossary glossary.yaml
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### `glossary review`
|
|
192
|
+
|
|
193
|
+
Generate a Markdown report of all glossary terms and their translations.
|
|
194
|
+
|
|
195
|
+
**Options:**
|
|
196
|
+
|
|
197
|
+
- `--glossary <path>` (required): Glossary file path
|
|
198
|
+
- `--output <path>`: Save the report to a file (Markdown)
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
yuuhitsu glossary review --glossary glossary.yaml
|
|
204
|
+
yuuhitsu glossary review --glossary glossary.yaml --output glossary-report.md
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Glossary File Format
|
|
208
|
+
|
|
209
|
+
The `glossary.yaml` file defines canonical terms, their translations, and forbidden variants:
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
version: 1
|
|
213
|
+
languages: [ja, en]
|
|
214
|
+
terms:
|
|
215
|
+
- canonical: "API"
|
|
216
|
+
type: noun
|
|
217
|
+
translations:
|
|
218
|
+
ja: "API"
|
|
219
|
+
en: "API"
|
|
220
|
+
do_not_use:
|
|
221
|
+
ja: ["API", "えーぴーあい"]
|
|
222
|
+
- canonical: "webhook"
|
|
223
|
+
type: noun
|
|
224
|
+
translations:
|
|
225
|
+
ja: "Webhook"
|
|
226
|
+
en: "webhook"
|
|
227
|
+
do_not_use:
|
|
228
|
+
ja: ["ウェブフック"]
|
|
229
|
+
en: ["web hook"]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
| Field | Description |
|
|
233
|
+
|-------|-------------|
|
|
234
|
+
| `version` | Schema version (currently `1`) |
|
|
235
|
+
| `languages` | List of language codes managed by this glossary |
|
|
236
|
+
| `terms[].canonical` | The authoritative (source-language) term |
|
|
237
|
+
| `terms[].type` | Term type (e.g., `noun`, `verb`) |
|
|
238
|
+
| `terms[].translations` | Map of language code → translated term |
|
|
239
|
+
| `terms[].do_not_use` | Map of language code → list of forbidden variants |
|
|
240
|
+
|
|
127
241
|
## Development
|
|
128
242
|
|
|
129
243
|
```bash
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/glossary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0IpC,eAAO,MAAM,eAAe,SAKJ,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { writeFileSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { initGlossary, checkGlossary, syncGlossary, reviewGlossary, } from "../../tasks/glossary.js";
|
|
6
|
+
import { formatError } from "../../errors.js";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// glossary init
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const initCmd = new Command("init")
|
|
11
|
+
.description("Generate a glossary.yaml skeleton")
|
|
12
|
+
.option("--output <path>", "Output path for glossary file", "glossary.yaml")
|
|
13
|
+
.option("--force", "Overwrite existing glossary file")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const outputPath = resolve(process.cwd(), opts.output);
|
|
16
|
+
try {
|
|
17
|
+
initGlossary(outputPath, opts.force || undefined);
|
|
18
|
+
process.stdout.write(`${chalk.green("✓")} Glossary file created: ${outputPath}\n`);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
process.stderr.write(formatError(err) + "\n");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// glossary check
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
const checkCmd = new Command("check")
|
|
29
|
+
.description("Detect terminology inconsistencies in a document")
|
|
30
|
+
.requiredOption("--input <file>", "Document file to check")
|
|
31
|
+
.requiredOption("--glossary <path>", "Glossary file path")
|
|
32
|
+
.requiredOption("--lang <code>", "Language code to check (e.g., ja, en)")
|
|
33
|
+
.action(async (opts) => {
|
|
34
|
+
try {
|
|
35
|
+
const issues = checkGlossary(opts.input, opts.glossary, opts.lang);
|
|
36
|
+
if (issues.length === 0) {
|
|
37
|
+
process.stdout.write(`${chalk.green("✓")} No issues found in ${opts.input}\n`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write(`${chalk.yellow("⚠")} Found ${issues.length} terminology issue(s) in ${opts.input}:\n\n`);
|
|
41
|
+
for (const issue of issues) {
|
|
42
|
+
process.stdout.write(` Line ${issue.line}: "${chalk.red(issue.forbidden)}" → use "${chalk.green(issue.canonical)}"\n`);
|
|
43
|
+
}
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
process.stderr.write(formatError(err) + "\n");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// glossary sync
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
const syncCmd = new Command("sync")
|
|
55
|
+
.description("Sync glossary with translation files and report coverage")
|
|
56
|
+
.requiredOption("--glossary <path>", "Glossary file path")
|
|
57
|
+
.action(async (opts) => {
|
|
58
|
+
try {
|
|
59
|
+
const result = syncGlossary(opts.glossary);
|
|
60
|
+
process.stdout.write(`${chalk.green("✓")} Glossary sync report\n\n` +
|
|
61
|
+
` Total terms: ${result.totalTerms}\n`);
|
|
62
|
+
for (const [lang, terms] of Object.entries(result.termsByLanguage)) {
|
|
63
|
+
process.stdout.write(` ${lang}: ${terms.length} / ${result.totalTerms} terms translated\n`);
|
|
64
|
+
}
|
|
65
|
+
if (result.missingTranslations.length > 0) {
|
|
66
|
+
process.stdout.write(`\n${chalk.yellow("⚠")} Missing translations:\n`);
|
|
67
|
+
for (const missing of result.missingTranslations) {
|
|
68
|
+
process.stdout.write(` "${missing.canonical}" missing: ${missing.missingLanguages.join(", ")}\n`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
process.stderr.write(formatError(err) + "\n");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// glossary review
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
const reviewCmd = new Command("review")
|
|
81
|
+
.description("Generate a glossary review report")
|
|
82
|
+
.requiredOption("--glossary <path>", "Glossary file path")
|
|
83
|
+
.option("--output <path>", "Save report to file (Markdown)")
|
|
84
|
+
.action(async (opts) => {
|
|
85
|
+
try {
|
|
86
|
+
const report = reviewGlossary(opts.glossary);
|
|
87
|
+
const markdown = report.toMarkdown();
|
|
88
|
+
if (opts.output) {
|
|
89
|
+
writeFileSync(opts.output, markdown, "utf-8");
|
|
90
|
+
process.stdout.write(`${chalk.green("✓")} Review report saved to ${opts.output}\n`);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
process.stdout.write(markdown);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
process.stderr.write(formatError(err) + "\n");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// glossary (parent command)
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
export const glossaryCommand = new Command("glossary")
|
|
105
|
+
.description("Manage glossary for terminology consistency")
|
|
106
|
+
.addCommand(initCmd)
|
|
107
|
+
.addCommand(checkCmd)
|
|
108
|
+
.addCommand(syncCmd)
|
|
109
|
+
.addCommand(reviewCmd);
|
|
110
|
+
//# sourceMappingURL=glossary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.js","sourceRoot":"","sources":["../../../src/cli/commands/glossary.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAsB9B,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import { formatError } from "../errors.js";
|
|
7
7
|
import { translateCommand } from "./commands/translate.js";
|
|
8
8
|
import { initCommand } from "./commands/init.js";
|
|
9
|
+
import { glossaryCommand } from "./commands/glossary.js";
|
|
9
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
11
|
function getVersion() {
|
|
11
12
|
try {
|
|
@@ -27,6 +28,7 @@ program
|
|
|
27
28
|
// Register commands
|
|
28
29
|
program.addCommand(initCommand);
|
|
29
30
|
program.addCommand(translateCommand);
|
|
31
|
+
program.addCommand(glossaryCommand);
|
|
30
32
|
program.parseAsync(process.argv).catch((err) => {
|
|
31
33
|
process.stderr.write(formatError(err) + "\n");
|
|
32
34
|
process.exit(1);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAC7D,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,oDAAoD,CACrD;KACA,OAAO,CAAC,UAAU,EAAE,CAAC;KACrB,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,wBAAwB,CAAC;KACvE,MAAM,CAAC,WAAW,EAAE,kDAAkD,CAAC;KACvE,MAAM,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;AAEhD,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AAEpC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/config.d.ts
CHANGED
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,mBAAmB,yCAA0C,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,mBAAmB,yCAA0C,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAyDpB"}
|
package/dist/config.js
CHANGED
|
@@ -41,6 +41,12 @@ export async function loadConfig(configPath, envDir) {
|
|
|
41
41
|
config.templates = raw.templates;
|
|
42
42
|
if (raw.outputDir)
|
|
43
43
|
config.outputDir = raw.outputDir;
|
|
44
|
+
if (raw.glossary !== undefined) {
|
|
45
|
+
if (typeof raw.glossary !== "string") {
|
|
46
|
+
throw new Error('Config field "glossary" must be a string path');
|
|
47
|
+
}
|
|
48
|
+
config.glossary = raw.glossary;
|
|
49
|
+
}
|
|
44
50
|
if (raw.log) {
|
|
45
51
|
config.log = {
|
|
46
52
|
enabled: raw.log.enabled ?? false,
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAepE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,UAAkB,EAClB,MAAe;IAEf,0DAA0D;IAC1D,IAAI,MAAM,EAAE,CAAC;QACX,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,YAAY,EAAE,CAAC,CAAC,4BAA4B;IAC9C,CAAC;IAED,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC9B,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,2BAA2B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9F,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACxB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAc;QACxB,QAAQ;QACR,KAAK;KACN,CAAC;IAEF,IAAI,GAAG,CAAC,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;IACpD,IAAI,GAAG,CAAC,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;IACpD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IACjC,CAAC;IACD,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,GAAG;YACX,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK;YACjC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI;SACnB,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface GlossaryTerm {
|
|
2
|
+
canonical: string;
|
|
3
|
+
type: string;
|
|
4
|
+
translations: Record<string, string>;
|
|
5
|
+
do_not_use?: Record<string, string[]>;
|
|
6
|
+
}
|
|
7
|
+
export interface GlossaryConfig {
|
|
8
|
+
version: number;
|
|
9
|
+
languages: string[];
|
|
10
|
+
terms: GlossaryTerm[];
|
|
11
|
+
}
|
|
12
|
+
export interface GlossaryIssue {
|
|
13
|
+
forbidden: string;
|
|
14
|
+
canonical: string;
|
|
15
|
+
line: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MissingTranslation {
|
|
18
|
+
canonical: string;
|
|
19
|
+
missingLanguages: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface SyncResult {
|
|
22
|
+
totalTerms: number;
|
|
23
|
+
termsByLanguage: Record<string, GlossaryTerm[]>;
|
|
24
|
+
missingTranslations: MissingTranslation[];
|
|
25
|
+
stubsCreated: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ReviewReport {
|
|
28
|
+
terms: GlossaryTerm[];
|
|
29
|
+
summary: {
|
|
30
|
+
totalTerms: number;
|
|
31
|
+
languages: string[];
|
|
32
|
+
};
|
|
33
|
+
toMarkdown(): string;
|
|
34
|
+
}
|
|
35
|
+
export declare function loadGlossary(glossaryPath: string): GlossaryConfig | null;
|
|
36
|
+
export declare function initGlossary(outputPath: string, force?: boolean): void;
|
|
37
|
+
export declare function checkGlossary(docPath: string, glossaryPath: string, lang: string): GlossaryIssue[];
|
|
38
|
+
export declare function syncGlossary(glossaryPath: string): SyncResult;
|
|
39
|
+
export declare function reviewGlossary(glossaryPath: string): ReviewReport;
|
|
40
|
+
export declare function buildGlossaryPrompt(glossaryConfig: GlossaryConfig, targetLang: string): string;
|
|
41
|
+
//# sourceMappingURL=glossary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.d.ts","sourceRoot":"","sources":["../../src/tasks/glossary.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAChD,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,UAAU,IAAI,MAAM,CAAC;CACtB;AA+BD,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAqBxE;AAMD,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAQtE;AAMD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GACX,aAAa,EAAE,CAuDjB;AAgED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAoD7D;AAMD,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CA6CjE;AAMD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,MAAM,GACjB,MAAM,CAyBR"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2
|
+
import { parse, stringify } from "yaml";
|
|
3
|
+
import { separateFrontmatter, protectCodeBlocks } from "./translate.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Skeleton template
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
const SKELETON_TEMPLATE = `version: 1
|
|
8
|
+
languages: [ja, en]
|
|
9
|
+
terms:
|
|
10
|
+
- canonical: "API"
|
|
11
|
+
type: noun
|
|
12
|
+
translations:
|
|
13
|
+
ja: "API"
|
|
14
|
+
en: "API"
|
|
15
|
+
do_not_use:
|
|
16
|
+
ja: ["API", "えーぴーあい"]
|
|
17
|
+
# Add more terms below:
|
|
18
|
+
# - canonical: "webhook"
|
|
19
|
+
# type: noun
|
|
20
|
+
# translations:
|
|
21
|
+
# ja: "Webhook"
|
|
22
|
+
# en: "webhook"
|
|
23
|
+
# do_not_use:
|
|
24
|
+
# ja: ["ウェブフック"]
|
|
25
|
+
# en: ["web hook"]
|
|
26
|
+
`;
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// loadGlossary
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
export function loadGlossary(glossaryPath) {
|
|
31
|
+
if (!existsSync(glossaryPath)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const content = readFileSync(glossaryPath, "utf-8");
|
|
35
|
+
const raw = parse(content);
|
|
36
|
+
if (!raw || typeof raw !== "object") {
|
|
37
|
+
throw new Error(`Invalid glossary file: ${glossaryPath}`);
|
|
38
|
+
}
|
|
39
|
+
const schema = raw;
|
|
40
|
+
if (!Array.isArray(schema.terms)) {
|
|
41
|
+
throw new Error(`Glossary file must have a "terms" array: ${glossaryPath}`);
|
|
42
|
+
}
|
|
43
|
+
if (!Array.isArray(schema.languages)) {
|
|
44
|
+
throw new Error(`Glossary file must have a "languages" array: ${glossaryPath}`);
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// initGlossary
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
export function initGlossary(outputPath, force) {
|
|
52
|
+
if (existsSync(outputPath) && !force) {
|
|
53
|
+
throw new Error(`Glossary file already exists: ${outputPath}\nUse --force to overwrite.`);
|
|
54
|
+
}
|
|
55
|
+
writeFileSync(outputPath, SKELETON_TEMPLATE, "utf-8");
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// checkGlossary
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
export function checkGlossary(docPath, glossaryPath, lang) {
|
|
61
|
+
// Load glossary (throws if not found)
|
|
62
|
+
const glossary = loadGlossary(glossaryPath);
|
|
63
|
+
if (!glossary) {
|
|
64
|
+
throw new Error(`Glossary file not found: ${glossaryPath}`);
|
|
65
|
+
}
|
|
66
|
+
// Validate lang parameter
|
|
67
|
+
if (!glossary.languages.includes(lang)) {
|
|
68
|
+
throw new Error(`Language "${lang}" is not defined in glossary. Available: ${glossary.languages.join(", ")}`);
|
|
69
|
+
}
|
|
70
|
+
// Read document (throws if not found)
|
|
71
|
+
let docContent;
|
|
72
|
+
try {
|
|
73
|
+
docContent = readFileSync(docPath, "utf-8");
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
77
|
+
throw new Error(`Document not found: ${docPath}`);
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
// Separate frontmatter (skip it) and get body
|
|
82
|
+
const { frontmatter, body } = separateFrontmatter(docContent);
|
|
83
|
+
const frontmatterLineCount = frontmatter ? frontmatter.split("\n").length - 1 : 0;
|
|
84
|
+
// Protect code blocks and inline code with placeholders to avoid false positives
|
|
85
|
+
const { text: protectedBody } = protectCodeBlocks(body);
|
|
86
|
+
const lines = protectedBody.split("\n");
|
|
87
|
+
const issues = [];
|
|
88
|
+
for (const term of glossary.terms) {
|
|
89
|
+
const forbidden = term.do_not_use?.[lang] ?? [];
|
|
90
|
+
const canonicalTranslation = term.translations[lang];
|
|
91
|
+
for (const forbiddenWord of forbidden) {
|
|
92
|
+
if (forbiddenWord.length === 0)
|
|
93
|
+
continue;
|
|
94
|
+
for (let i = 0; i < lines.length; i++) {
|
|
95
|
+
// Remove URL content before checking to avoid false positives inside URLs
|
|
96
|
+
const lineWithoutUrls = lines[i].replace(/https?:\/\/\S+/g, "");
|
|
97
|
+
if (hasUncoveredOccurrence(lineWithoutUrls, forbiddenWord, canonicalTranslation)) {
|
|
98
|
+
issues.push({
|
|
99
|
+
forbidden: forbiddenWord,
|
|
100
|
+
canonical: term.canonical,
|
|
101
|
+
line: i + 1 + frontmatterLineCount,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return issues;
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Substring-match helpers for checkGlossary
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
/**
|
|
113
|
+
* Returns true if `canonicalTranslation` appears in `line` at a position
|
|
114
|
+
* that "covers" the occurrence of `forbiddenWord` starting at `forbiddenIdx`.
|
|
115
|
+
*
|
|
116
|
+
* Example: canonicalTranslation = "サブスクリプション", forbiddenWord = "サブスク"
|
|
117
|
+
* If "サブスクリプション" appears at position 0 in the line, the "サブスク" occurrence
|
|
118
|
+
* at position 0 is covered and should not be reported as a violation.
|
|
119
|
+
*/
|
|
120
|
+
function isOccurrenceCoveredByCanonical(line, forbiddenIdx, forbiddenWord, canonicalTranslation) {
|
|
121
|
+
if (!canonicalTranslation)
|
|
122
|
+
return false;
|
|
123
|
+
// For each position of forbiddenWord within canonicalTranslation, check
|
|
124
|
+
// whether canonicalTranslation appears at the corresponding position in line.
|
|
125
|
+
let posInCanonical = canonicalTranslation.indexOf(forbiddenWord);
|
|
126
|
+
while (posInCanonical !== -1) {
|
|
127
|
+
const canonicalStart = forbiddenIdx - posInCanonical;
|
|
128
|
+
if (canonicalStart >= 0 &&
|
|
129
|
+
line.slice(canonicalStart, canonicalStart + canonicalTranslation.length) === canonicalTranslation) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
posInCanonical = canonicalTranslation.indexOf(forbiddenWord, posInCanonical + 1);
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns true if `line` contains at least one occurrence of `forbiddenWord`
|
|
138
|
+
* that is NOT covered by `canonicalTranslation` appearing at the same position.
|
|
139
|
+
*/
|
|
140
|
+
function hasUncoveredOccurrence(line, forbiddenWord, canonicalTranslation) {
|
|
141
|
+
if (forbiddenWord.length === 0)
|
|
142
|
+
return false;
|
|
143
|
+
let searchPos = 0;
|
|
144
|
+
while (true) {
|
|
145
|
+
const idx = line.indexOf(forbiddenWord, searchPos);
|
|
146
|
+
if (idx === -1)
|
|
147
|
+
break;
|
|
148
|
+
if (!isOccurrenceCoveredByCanonical(line, idx, forbiddenWord, canonicalTranslation)) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
searchPos = idx + 1;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// syncGlossary
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
export function syncGlossary(glossaryPath) {
|
|
159
|
+
const glossary = loadGlossary(glossaryPath);
|
|
160
|
+
if (!glossary) {
|
|
161
|
+
throw new Error(`Glossary file not found: ${glossaryPath}`);
|
|
162
|
+
}
|
|
163
|
+
const termsByLanguage = {};
|
|
164
|
+
for (const lang of glossary.languages) {
|
|
165
|
+
termsByLanguage[lang] = [];
|
|
166
|
+
}
|
|
167
|
+
const missingTranslations = [];
|
|
168
|
+
for (const term of glossary.terms) {
|
|
169
|
+
const missingLangs = [];
|
|
170
|
+
for (const lang of glossary.languages) {
|
|
171
|
+
if (term.translations[lang]) {
|
|
172
|
+
termsByLanguage[lang].push(term);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
missingLangs.push(lang);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (missingLangs.length > 0) {
|
|
179
|
+
missingTranslations.push({
|
|
180
|
+
canonical: term.canonical,
|
|
181
|
+
missingLanguages: missingLangs,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Write stub placeholders for missing translations
|
|
186
|
+
let stubsCreated = 0;
|
|
187
|
+
if (missingTranslations.length > 0) {
|
|
188
|
+
for (const term of glossary.terms) {
|
|
189
|
+
for (const lang of glossary.languages) {
|
|
190
|
+
if (!term.translations[lang]) {
|
|
191
|
+
term.translations[lang] = "";
|
|
192
|
+
stubsCreated++;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
writeFileSync(glossaryPath, stringify(glossary), "utf-8");
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
totalTerms: glossary.terms.length,
|
|
200
|
+
termsByLanguage,
|
|
201
|
+
missingTranslations,
|
|
202
|
+
stubsCreated,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// reviewGlossary
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
export function reviewGlossary(glossaryPath) {
|
|
209
|
+
const glossary = loadGlossary(glossaryPath);
|
|
210
|
+
if (!glossary) {
|
|
211
|
+
throw new Error(`Glossary file not found: ${glossaryPath}`);
|
|
212
|
+
}
|
|
213
|
+
const report = {
|
|
214
|
+
terms: glossary.terms,
|
|
215
|
+
summary: {
|
|
216
|
+
totalTerms: glossary.terms.length,
|
|
217
|
+
languages: glossary.languages,
|
|
218
|
+
},
|
|
219
|
+
toMarkdown() {
|
|
220
|
+
const lines = [
|
|
221
|
+
"# Glossary Review Report",
|
|
222
|
+
"",
|
|
223
|
+
`**Total Terms:** ${glossary.terms.length}`,
|
|
224
|
+
`**Languages:** ${glossary.languages.join(", ")}`,
|
|
225
|
+
"",
|
|
226
|
+
"## Terms",
|
|
227
|
+
"",
|
|
228
|
+
];
|
|
229
|
+
for (const term of glossary.terms) {
|
|
230
|
+
lines.push(`### ${term.canonical}`);
|
|
231
|
+
lines.push("");
|
|
232
|
+
lines.push(`- **Type:** ${term.type}`);
|
|
233
|
+
lines.push("- **Translations:**");
|
|
234
|
+
for (const [lang, translation] of Object.entries(term.translations)) {
|
|
235
|
+
lines.push(` - \`${lang}\`: ${translation}`);
|
|
236
|
+
}
|
|
237
|
+
if (term.do_not_use && Object.keys(term.do_not_use).length > 0) {
|
|
238
|
+
lines.push("- **Do not use:**");
|
|
239
|
+
for (const [lang, words] of Object.entries(term.do_not_use)) {
|
|
240
|
+
lines.push(` - \`${lang}\`: ${words.join(", ")}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
lines.push("");
|
|
244
|
+
}
|
|
245
|
+
return lines.join("\n");
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
return report;
|
|
249
|
+
}
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
// buildGlossaryPrompt — helper for translate integration
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
export function buildGlossaryPrompt(glossaryConfig, targetLang) {
|
|
254
|
+
const relevantTerms = glossaryConfig.terms.filter((t) => t.translations[targetLang] || t.do_not_use?.[targetLang]);
|
|
255
|
+
if (relevantTerms.length === 0) {
|
|
256
|
+
return "";
|
|
257
|
+
}
|
|
258
|
+
const lines = [
|
|
259
|
+
"",
|
|
260
|
+
"Glossary — use these canonical translations and avoid forbidden terms:",
|
|
261
|
+
];
|
|
262
|
+
for (const term of relevantTerms) {
|
|
263
|
+
const canonical = term.translations[targetLang] ?? term.canonical;
|
|
264
|
+
const forbidden = term.do_not_use?.[targetLang] ?? [];
|
|
265
|
+
let line = `- "${term.canonical}" → "${canonical}"`;
|
|
266
|
+
if (forbidden.length > 0) {
|
|
267
|
+
line += ` (do NOT use: ${forbidden.map((f) => `"${f}"`).join(", ")})`;
|
|
268
|
+
}
|
|
269
|
+
lines.push(line);
|
|
270
|
+
}
|
|
271
|
+
return lines.join("\n");
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=glossary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.js","sourceRoot":"","sources":["../../src/tasks/glossary.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AIProvider } from "../provider/interface.js";
|
|
2
|
+
import type { GlossaryConfig } from "./glossary.js";
|
|
2
3
|
interface FrontmatterSeparation {
|
|
3
4
|
frontmatter: string | null;
|
|
4
5
|
body: string;
|
|
@@ -29,6 +30,7 @@ export interface TranslateOptions {
|
|
|
29
30
|
outputPath?: string;
|
|
30
31
|
targetLang: string;
|
|
31
32
|
templateContent?: string;
|
|
33
|
+
glossaryConfig?: GlossaryConfig;
|
|
32
34
|
}
|
|
33
35
|
export interface TranslateResult {
|
|
34
36
|
outputPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/tasks/translate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,UAAU,qBAAqB;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAmB1E;AAED,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,CAuBjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CASnF;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;CACjC;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;AA+FD,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAkE1B"}
|
package/dist/tasks/translate.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
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
|
|
4
5
|
/**
|
|
5
6
|
* Separate frontmatter from Markdown content
|
|
@@ -34,10 +35,12 @@ export function protectCodeBlocks(content) {
|
|
|
34
35
|
let inlineIndex = 0;
|
|
35
36
|
// Step 1: Replace fenced code blocks (4+ backticks before 3-backtick blocks)
|
|
36
37
|
// Matches ````+ ... ```` or ``` ... ``` (non-greedy, multiline)
|
|
38
|
+
// Preserve the original line count by repeating newlines so subsequent line numbers stay correct.
|
|
37
39
|
let result = content.replace(/(`{3,})[^\n]*\n[\s\S]*?\1[ \t]*(\n|$)/g, (match) => {
|
|
38
40
|
const placeholder = `__CODE_BLOCK_${blockIndex++}__`;
|
|
39
41
|
map.set(placeholder, match);
|
|
40
|
-
|
|
42
|
+
const newlineCount = (match.match(/\n/g) ?? []).length;
|
|
43
|
+
return placeholder + "\n".repeat(newlineCount);
|
|
41
44
|
});
|
|
42
45
|
// Step 2: Replace inline code (single backtick, not within code blocks)
|
|
43
46
|
result = result.replace(/`([^`\n]+)`/g, (match) => {
|
|
@@ -82,11 +85,17 @@ Additional rules for Japanese translation:
|
|
|
82
85
|
- Add half-width spaces around English words and numbers (e.g., "Vela とは", "NGSIv2 は", "3 つの")
|
|
83
86
|
- Use natural Japanese terms for technical words where appropriate (e.g., "registration" → "登録", "subscription" → "サブスクリプション")
|
|
84
87
|
- Keep product names, proper nouns, and abbreviations unchanged (e.g., Vela, FIWARE, NGSIv2, NGSI-LD, MCP)`;
|
|
85
|
-
function buildPrompt(content, targetLang, hasPlaceholders, templateContent) {
|
|
88
|
+
function buildPrompt(content, targetLang, hasPlaceholders, templateContent, glossaryConfig) {
|
|
86
89
|
const template = templateContent || DEFAULT_TEMPLATE;
|
|
87
90
|
let systemPrompt = template
|
|
88
91
|
.replace(/\{\{targetLanguage\}\}/g, targetLang)
|
|
89
92
|
.replace(/\{\{content\}\}/g, "");
|
|
93
|
+
if (glossaryConfig) {
|
|
94
|
+
const glossarySection = buildGlossaryPrompt(glossaryConfig, targetLang);
|
|
95
|
+
if (glossarySection) {
|
|
96
|
+
systemPrompt += glossarySection;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
90
99
|
if (hasPlaceholders) {
|
|
91
100
|
systemPrompt +=
|
|
92
101
|
"\n\nIMPORTANT - Placeholder preservation:\n" +
|
|
@@ -129,7 +138,7 @@ function splitIntoChunks(content) {
|
|
|
129
138
|
return chunks;
|
|
130
139
|
}
|
|
131
140
|
export async function translateFile(options) {
|
|
132
|
-
const { provider, inputPath, targetLang, templateContent } = options;
|
|
141
|
+
const { provider, inputPath, targetLang, templateContent, glossaryConfig } = options;
|
|
133
142
|
// Read input file
|
|
134
143
|
let content;
|
|
135
144
|
try {
|
|
@@ -158,7 +167,7 @@ export async function translateFile(options) {
|
|
|
158
167
|
const translatedParts = [];
|
|
159
168
|
let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
160
169
|
for (const chunk of chunks) {
|
|
161
|
-
const messages = buildPrompt(chunk, targetLang, hasPlaceholders, templateContent);
|
|
170
|
+
const messages = buildPrompt(chunk, targetLang, hasPlaceholders, templateContent, glossaryConfig);
|
|
162
171
|
const response = await provider.chat({
|
|
163
172
|
model: "",
|
|
164
173
|
messages,
|
|
@@ -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;AAOrC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,0CAA0C;IAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAElD,4EAA4E;IAC5E,0DAA0D;IAC1D,mDAAmD;IACnD,gFAAgF;IAChF,MAAM,gBAAgB,GAAG,yDAAyD,CAAC;IACnF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAEjD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC7C,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AACjD,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,6EAA6E;IAC7E,gEAAgE;IAChE,IAAI,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,wCAAwC,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/E,MAAM,WAAW,GAAG,gBAAgB,UAAU,EAAE,IAAI,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC5B,OAAO,WAAW,GAAG,IAAI,CAAC;
|
|
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": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^22.0.0",
|
|
42
42
|
"tsx": "^4.19.0",
|
|
43
|
-
"typescript": "^5.
|
|
43
|
+
"typescript": "^5.7.0",
|
|
44
44
|
"vitest": "^3.0.0"
|
|
45
45
|
}
|
|
46
46
|
}
|