@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.
Files changed (73) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +114 -0
  3. package/dist/cli/commands/glossary.d.ts +3 -0
  4. package/dist/cli/commands/glossary.d.ts.map +1 -0
  5. package/dist/cli/commands/glossary.js +110 -0
  6. package/dist/cli/commands/glossary.js.map +1 -0
  7. package/dist/cli/commands/init.d.ts +3 -0
  8. package/dist/cli/commands/init.d.ts.map +1 -0
  9. package/dist/cli/commands/init.js +82 -0
  10. package/dist/cli/commands/init.js.map +1 -0
  11. package/dist/cli/commands/translate.d.ts +0 -0
  12. package/dist/cli/commands/translate.d.ts.map +1 -1
  13. package/dist/cli/commands/translate.js +53 -26
  14. package/dist/cli/commands/translate.js.map +1 -1
  15. package/dist/cli/index.d.ts +0 -0
  16. package/dist/cli/index.d.ts.map +1 -1
  17. package/dist/cli/index.js +4 -0
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/config.d.ts +1 -0
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +6 -0
  22. package/dist/config.js.map +1 -1
  23. package/dist/errors.d.ts +0 -0
  24. package/dist/errors.d.ts.map +0 -0
  25. package/dist/errors.js +0 -0
  26. package/dist/errors.js.map +0 -0
  27. package/dist/logger.d.ts +0 -0
  28. package/dist/logger.d.ts.map +0 -0
  29. package/dist/logger.js +0 -0
  30. package/dist/logger.js.map +0 -0
  31. package/dist/provider/claude.d.ts +0 -0
  32. package/dist/provider/claude.d.ts.map +0 -0
  33. package/dist/provider/claude.js +0 -0
  34. package/dist/provider/claude.js.map +0 -0
  35. package/dist/provider/gemini.d.ts +0 -0
  36. package/dist/provider/gemini.d.ts.map +0 -0
  37. package/dist/provider/gemini.js +0 -0
  38. package/dist/provider/gemini.js.map +0 -0
  39. package/dist/provider/index.d.ts +0 -0
  40. package/dist/provider/index.d.ts.map +0 -0
  41. package/dist/provider/index.js +0 -0
  42. package/dist/provider/index.js.map +0 -0
  43. package/dist/provider/interface.d.ts +0 -0
  44. package/dist/provider/interface.d.ts.map +0 -0
  45. package/dist/provider/interface.js +0 -0
  46. package/dist/provider/interface.js.map +0 -0
  47. package/dist/provider/ollama.d.ts +0 -0
  48. package/dist/provider/ollama.d.ts.map +0 -0
  49. package/dist/provider/ollama.js +0 -0
  50. package/dist/provider/ollama.js.map +0 -0
  51. package/dist/tasks/batch-translate.d.ts +46 -0
  52. package/dist/tasks/batch-translate.d.ts.map +1 -0
  53. package/dist/tasks/batch-translate.js +174 -0
  54. package/dist/tasks/batch-translate.js.map +1 -0
  55. package/dist/tasks/glossary.d.ts +41 -0
  56. package/dist/tasks/glossary.d.ts.map +1 -0
  57. package/dist/tasks/glossary.js +273 -0
  58. package/dist/tasks/glossary.js.map +1 -0
  59. package/dist/tasks/stream.d.ts +0 -0
  60. package/dist/tasks/stream.d.ts.map +0 -0
  61. package/dist/tasks/stream.js +0 -0
  62. package/dist/tasks/stream.js.map +0 -0
  63. package/dist/tasks/translate.d.ts +27 -0
  64. package/dist/tasks/translate.d.ts.map +1 -1
  65. package/dist/tasks/translate.js +101 -7
  66. package/dist/tasks/translate.js.map +1 -1
  67. package/package.json +14 -8
  68. package/src/templates/fix-links.md +0 -0
  69. package/src/templates/generate-docs.md +0 -0
  70. package/src/templates/generate-tests.md +0 -0
  71. package/src/templates/research.md +0 -0
  72. package/src/templates/sync-docs.md +0 -0
  73. package/src/templates/translate.md +8 -0
File without changes
File without changes
File without changes
@@ -0,0 +1,46 @@
1
+ import type { AIProvider } from "../provider/index.js";
2
+ export interface BatchProgress {
3
+ total: number;
4
+ current: number;
5
+ succeeded: number;
6
+ failed: number;
7
+ skipped: number;
8
+ }
9
+ export interface BatchTranslateOptions {
10
+ pattern: string;
11
+ targetLang: string;
12
+ provider?: AIProvider;
13
+ outputDir?: string;
14
+ inputBase?: string;
15
+ onProgress?: (progress: BatchProgress) => void;
16
+ dryRun: boolean;
17
+ verbose?: boolean;
18
+ }
19
+ export interface BatchResult {
20
+ total: number;
21
+ succeeded: number;
22
+ failed: number;
23
+ errors: Array<{
24
+ file: string;
25
+ error: string;
26
+ }>;
27
+ }
28
+ /**
29
+ * Check if a string contains glob pattern characters
30
+ */
31
+ export declare function isGlobPattern(input: string): boolean;
32
+ /**
33
+ * Generate output path for a translated file
34
+ */
35
+ export declare function generateOutputPath(opts: {
36
+ inputPath: string;
37
+ targetLang: string;
38
+ outputDir?: string;
39
+ inputBase?: string;
40
+ explicitOutput?: string;
41
+ }): string;
42
+ /**
43
+ * Execute batch translation
44
+ */
45
+ export declare function batchTranslate(opts: BatchTranslateOptions): Promise<BatchResult>;
46
+ //# sourceMappingURL=batch-translate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-translate.d.ts","sourceRoot":"","sources":["../../src/tasks/batch-translate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAsCT;AA4CD;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAqHtB"}
@@ -0,0 +1,174 @@
1
+ import fg from "fast-glob";
2
+ import { dirname, join, relative, parse, isAbsolute, sep } from "path";
3
+ import { mkdirSync } from "fs";
4
+ import chalk from "chalk";
5
+ import { translateFile } from "./translate.js";
6
+ /**
7
+ * Check if a string contains glob pattern characters
8
+ */
9
+ export function isGlobPattern(input) {
10
+ return /[*?[\]{}]/.test(input);
11
+ }
12
+ /**
13
+ * Generate output path for a translated file
14
+ */
15
+ export function generateOutputPath(opts) {
16
+ const { inputPath, targetLang, outputDir, inputBase, explicitOutput } = opts;
17
+ // If explicit output is provided, use it
18
+ if (explicitOutput) {
19
+ return explicitOutput;
20
+ }
21
+ // If outputDir is provided, preserve directory structure
22
+ if (outputDir && inputBase) {
23
+ const relativePath = relative(inputBase, inputPath);
24
+ // Security: Prevent path traversal
25
+ // Reject paths that are absolute or try to escape via ".."
26
+ if (isAbsolute(relativePath)) {
27
+ throw new Error(`Path traversal detected: ${inputPath} is outside ${inputBase} (absolute path)`);
28
+ }
29
+ if (relativePath.startsWith(`..${sep}`) || relativePath === "..") {
30
+ throw new Error(`Path traversal detected: ${inputPath} tries to escape ${inputBase}`);
31
+ }
32
+ // Check for ".." in path segments
33
+ const segments = relativePath.split(sep);
34
+ if (segments.includes("..")) {
35
+ throw new Error(`Path traversal detected: ${inputPath} contains ".." segments`);
36
+ }
37
+ return join(outputDir, relativePath);
38
+ }
39
+ // Default: add language code before extension
40
+ const parsed = parse(inputPath);
41
+ const ext = parsed.ext || "";
42
+ const base = parsed.name;
43
+ const dir = parsed.dir;
44
+ return join(dir, `${base}.${targetLang}${ext}`);
45
+ }
46
+ /**
47
+ * Determine the base path for --input-dir calculation
48
+ */
49
+ function determineInputBase(pattern, matchedFiles) {
50
+ // Extract the static prefix from the glob pattern
51
+ // e.g., "docs/en/**/*.md" -> "docs/en"
52
+ const staticPrefix = pattern.split(/[*?[\]{}]/)[0];
53
+ // If there's a static directory prefix, use it
54
+ if (staticPrefix && staticPrefix.includes("/")) {
55
+ // Remove trailing slash and return as-is (it's already a directory path)
56
+ return staticPrefix.replace(/\/$/, "");
57
+ }
58
+ // If no static prefix, find common base from matched files
59
+ if (matchedFiles.length === 0) {
60
+ return undefined;
61
+ }
62
+ // Find the common directory prefix of all matched files
63
+ const dirs = matchedFiles.map(f => dirname(f));
64
+ const commonDir = dirs.reduce((acc, dir) => {
65
+ if (!acc)
66
+ return dir;
67
+ const accParts = acc.split("/");
68
+ const dirParts = dir.split("/");
69
+ const common = [];
70
+ for (let i = 0; i < Math.min(accParts.length, dirParts.length); i++) {
71
+ if (accParts[i] === dirParts[i]) {
72
+ common.push(accParts[i]);
73
+ }
74
+ else {
75
+ break;
76
+ }
77
+ }
78
+ return common.join("/") || ".";
79
+ });
80
+ return commonDir === "." ? undefined : commonDir;
81
+ }
82
+ /**
83
+ * Execute batch translation
84
+ */
85
+ export async function batchTranslate(opts) {
86
+ const { pattern, targetLang, provider, outputDir, onProgress, dryRun, verbose } = opts;
87
+ // Match files using fast-glob
88
+ const matchedFiles = await fg(pattern, {
89
+ onlyFiles: true,
90
+ absolute: false,
91
+ });
92
+ if (matchedFiles.length === 0) {
93
+ throw new Error(`No files matched pattern: ${pattern}`);
94
+ }
95
+ // Determine input base for directory structure preservation
96
+ const inputBase = outputDir ? determineInputBase(pattern, matchedFiles) : undefined;
97
+ // Initialize progress
98
+ const progress = {
99
+ total: matchedFiles.length,
100
+ current: 0,
101
+ succeeded: 0,
102
+ failed: 0,
103
+ skipped: 0,
104
+ };
105
+ const errors = [];
106
+ // Process each file
107
+ for (let i = 0; i < matchedFiles.length; i++) {
108
+ const inputPath = matchedFiles[i];
109
+ progress.current = i + 1;
110
+ const outputPath = generateOutputPath({
111
+ inputPath,
112
+ targetLang,
113
+ outputDir,
114
+ inputBase,
115
+ });
116
+ // Show progress
117
+ const progressPrefix = chalk.cyan(`[${progress.current}/${progress.total}]`);
118
+ if (dryRun) {
119
+ process.stdout.write(`${progressPrefix} Would translate:\n` +
120
+ ` Input: ${inputPath}\n` +
121
+ ` Output: ${outputPath}\n`);
122
+ progress.succeeded++;
123
+ }
124
+ else {
125
+ if (!provider) {
126
+ throw new Error("Provider is required when dryRun is false");
127
+ }
128
+ try {
129
+ process.stdout.write(`${progressPrefix} Translating ${inputPath}...\n`);
130
+ // Ensure output directory exists
131
+ const outputDirPath = dirname(outputPath);
132
+ mkdirSync(outputDirPath, { recursive: true });
133
+ // Translate the file
134
+ const result = await translateFile({
135
+ provider,
136
+ inputPath,
137
+ outputPath,
138
+ targetLang,
139
+ });
140
+ process.stdout.write(`${chalk.green("✓")} Translated to ${result.outputPath}\n` +
141
+ (verbose ? ` Tokens: ${result.usage.totalTokens} (${result.chunks} chunk${result.chunks > 1 ? "s" : ""})\n` : ""));
142
+ progress.succeeded++;
143
+ }
144
+ catch (err) {
145
+ const errorMsg = err instanceof Error ? err.message : String(err);
146
+ process.stderr.write(`${chalk.red("✗")} Failed to translate ${inputPath}: ${errorMsg}\n`);
147
+ errors.push({ file: inputPath, error: errorMsg });
148
+ progress.failed++;
149
+ }
150
+ }
151
+ // Call progress callback
152
+ if (onProgress) {
153
+ onProgress(progress);
154
+ }
155
+ }
156
+ // Print summary
157
+ const summaryColor = progress.failed > 0 ? chalk.yellow : chalk.green;
158
+ process.stdout.write(`\n` +
159
+ summaryColor("Summary:\n") +
160
+ ` Total: ${progress.total}\n` +
161
+ ` Succeeded: ${progress.succeeded}\n` +
162
+ ` Failed: ${progress.failed}\n`);
163
+ if (errors.length > 0) {
164
+ process.stderr.write(`\n${chalk.red("Errors:")}\n` +
165
+ errors.map(e => ` ${e.file}: ${e.error}`).join("\n") + "\n");
166
+ }
167
+ return {
168
+ total: progress.total,
169
+ succeeded: progress.succeeded,
170
+ failed: progress.failed,
171
+ errors,
172
+ };
173
+ }
174
+ //# sourceMappingURL=batch-translate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-translate.js","sourceRoot":"","sources":["../../src/tasks/batch-translate.ts"],"names":[],"mappings":"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"}
@@ -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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"}
File without changes
File without changes
File without changes
File without changes
@@ -1,10 +1,36 @@
1
1
  import type { AIProvider } from "../provider/interface.js";
2
+ import type { GlossaryConfig } from "./glossary.js";
3
+ interface FrontmatterSeparation {
4
+ frontmatter: string | null;
5
+ body: string;
6
+ }
7
+ /**
8
+ * Separate frontmatter from Markdown content
9
+ * Handles: LF, CRLF, no trailing newline after closing ---, trailing spaces, empty frontmatter
10
+ * @param content - Full Markdown content
11
+ * @returns Object with separated frontmatter and body
12
+ */
13
+ export declare function separateFrontmatter(content: string): FrontmatterSeparation;
14
+ interface CodeProtection {
15
+ text: string;
16
+ map: Map<string, string>;
17
+ }
18
+ /**
19
+ * Replace fenced code blocks and inline code with placeholders.
20
+ * Fenced blocks (``` or ````+) take priority over inline code.
21
+ */
22
+ export declare function protectCodeBlocks(content: string): CodeProtection;
23
+ /**
24
+ * Restore placeholders back to original code blocks/inline code.
25
+ */
26
+ export declare function restoreCodeBlocks(content: string, map: Map<string, string>): string;
2
27
  export interface TranslateOptions {
3
28
  provider: AIProvider;
4
29
  inputPath: string;
5
30
  outputPath?: string;
6
31
  targetLang: string;
7
32
  templateContent?: string;
33
+ glossaryConfig?: GlossaryConfig;
8
34
  }
9
35
  export interface TranslateResult {
10
36
  outputPath: string;
@@ -16,4 +42,5 @@ export interface TranslateResult {
16
42
  chunks: number;
17
43
  }
18
44
  export declare function translateFile(options: TranslateOptions): Promise<TranslateResult>;
45
+ export {};
19
46
  //# sourceMappingURL=translate.d.ts.map
@@ -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;AAIxE,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;CAC1B;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;AAsED,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAoD1B"}
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"}