@llm-translate/cli 1.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/.dockerignore +51 -0
  2. package/.env.example +33 -0
  3. package/.github/workflows/docs-pages.yml +57 -0
  4. package/.github/workflows/release.yml +49 -0
  5. package/.translaterc.json +44 -0
  6. package/CLAUDE.md +243 -0
  7. package/Dockerfile +55 -0
  8. package/README.md +371 -0
  9. package/RFC.md +1595 -0
  10. package/dist/cli/index.d.ts +2 -0
  11. package/dist/cli/index.js +4494 -0
  12. package/dist/cli/index.js.map +1 -0
  13. package/dist/index.d.ts +1152 -0
  14. package/dist/index.js +3841 -0
  15. package/dist/index.js.map +1 -0
  16. package/docker-compose.yml +56 -0
  17. package/docs/.vitepress/config.ts +161 -0
  18. package/docs/api/agent.md +262 -0
  19. package/docs/api/engine.md +274 -0
  20. package/docs/api/index.md +171 -0
  21. package/docs/api/providers.md +304 -0
  22. package/docs/changelog.md +64 -0
  23. package/docs/cli/dir.md +243 -0
  24. package/docs/cli/file.md +213 -0
  25. package/docs/cli/glossary.md +273 -0
  26. package/docs/cli/index.md +129 -0
  27. package/docs/cli/init.md +158 -0
  28. package/docs/cli/serve.md +211 -0
  29. package/docs/glossary.json +235 -0
  30. package/docs/guide/chunking.md +272 -0
  31. package/docs/guide/configuration.md +139 -0
  32. package/docs/guide/cost-optimization.md +237 -0
  33. package/docs/guide/docker.md +371 -0
  34. package/docs/guide/getting-started.md +150 -0
  35. package/docs/guide/glossary.md +241 -0
  36. package/docs/guide/index.md +86 -0
  37. package/docs/guide/ollama.md +515 -0
  38. package/docs/guide/prompt-caching.md +221 -0
  39. package/docs/guide/providers.md +232 -0
  40. package/docs/guide/quality-control.md +206 -0
  41. package/docs/guide/vitepress-integration.md +265 -0
  42. package/docs/index.md +63 -0
  43. package/docs/ja/api/agent.md +262 -0
  44. package/docs/ja/api/engine.md +274 -0
  45. package/docs/ja/api/index.md +171 -0
  46. package/docs/ja/api/providers.md +304 -0
  47. package/docs/ja/changelog.md +64 -0
  48. package/docs/ja/cli/dir.md +243 -0
  49. package/docs/ja/cli/file.md +213 -0
  50. package/docs/ja/cli/glossary.md +273 -0
  51. package/docs/ja/cli/index.md +111 -0
  52. package/docs/ja/cli/init.md +158 -0
  53. package/docs/ja/guide/chunking.md +271 -0
  54. package/docs/ja/guide/configuration.md +139 -0
  55. package/docs/ja/guide/cost-optimization.md +30 -0
  56. package/docs/ja/guide/getting-started.md +150 -0
  57. package/docs/ja/guide/glossary.md +214 -0
  58. package/docs/ja/guide/index.md +32 -0
  59. package/docs/ja/guide/ollama.md +410 -0
  60. package/docs/ja/guide/prompt-caching.md +221 -0
  61. package/docs/ja/guide/providers.md +232 -0
  62. package/docs/ja/guide/quality-control.md +137 -0
  63. package/docs/ja/guide/vitepress-integration.md +265 -0
  64. package/docs/ja/index.md +58 -0
  65. package/docs/ko/api/agent.md +262 -0
  66. package/docs/ko/api/engine.md +274 -0
  67. package/docs/ko/api/index.md +171 -0
  68. package/docs/ko/api/providers.md +304 -0
  69. package/docs/ko/changelog.md +64 -0
  70. package/docs/ko/cli/dir.md +243 -0
  71. package/docs/ko/cli/file.md +213 -0
  72. package/docs/ko/cli/glossary.md +273 -0
  73. package/docs/ko/cli/index.md +111 -0
  74. package/docs/ko/cli/init.md +158 -0
  75. package/docs/ko/guide/chunking.md +271 -0
  76. package/docs/ko/guide/configuration.md +139 -0
  77. package/docs/ko/guide/cost-optimization.md +30 -0
  78. package/docs/ko/guide/getting-started.md +150 -0
  79. package/docs/ko/guide/glossary.md +214 -0
  80. package/docs/ko/guide/index.md +32 -0
  81. package/docs/ko/guide/ollama.md +410 -0
  82. package/docs/ko/guide/prompt-caching.md +221 -0
  83. package/docs/ko/guide/providers.md +232 -0
  84. package/docs/ko/guide/quality-control.md +137 -0
  85. package/docs/ko/guide/vitepress-integration.md +265 -0
  86. package/docs/ko/index.md +58 -0
  87. package/docs/zh/api/agent.md +262 -0
  88. package/docs/zh/api/engine.md +274 -0
  89. package/docs/zh/api/index.md +171 -0
  90. package/docs/zh/api/providers.md +304 -0
  91. package/docs/zh/changelog.md +64 -0
  92. package/docs/zh/cli/dir.md +243 -0
  93. package/docs/zh/cli/file.md +213 -0
  94. package/docs/zh/cli/glossary.md +273 -0
  95. package/docs/zh/cli/index.md +111 -0
  96. package/docs/zh/cli/init.md +158 -0
  97. package/docs/zh/guide/chunking.md +271 -0
  98. package/docs/zh/guide/configuration.md +139 -0
  99. package/docs/zh/guide/cost-optimization.md +30 -0
  100. package/docs/zh/guide/getting-started.md +150 -0
  101. package/docs/zh/guide/glossary.md +214 -0
  102. package/docs/zh/guide/index.md +32 -0
  103. package/docs/zh/guide/ollama.md +410 -0
  104. package/docs/zh/guide/prompt-caching.md +221 -0
  105. package/docs/zh/guide/providers.md +232 -0
  106. package/docs/zh/guide/quality-control.md +137 -0
  107. package/docs/zh/guide/vitepress-integration.md +265 -0
  108. package/docs/zh/index.md +58 -0
  109. package/package.json +91 -0
  110. package/release.config.mjs +15 -0
  111. package/schemas/glossary.schema.json +110 -0
  112. package/src/cli/commands/dir.ts +469 -0
  113. package/src/cli/commands/file.ts +291 -0
  114. package/src/cli/commands/glossary.ts +221 -0
  115. package/src/cli/commands/init.ts +68 -0
  116. package/src/cli/commands/serve.ts +60 -0
  117. package/src/cli/index.ts +64 -0
  118. package/src/cli/options.ts +59 -0
  119. package/src/core/agent.ts +1119 -0
  120. package/src/core/chunker.ts +391 -0
  121. package/src/core/engine.ts +634 -0
  122. package/src/errors.ts +188 -0
  123. package/src/index.ts +147 -0
  124. package/src/integrations/vitepress.ts +549 -0
  125. package/src/parsers/markdown.ts +383 -0
  126. package/src/providers/claude.ts +259 -0
  127. package/src/providers/interface.ts +109 -0
  128. package/src/providers/ollama.ts +379 -0
  129. package/src/providers/openai.ts +308 -0
  130. package/src/providers/registry.ts +153 -0
  131. package/src/server/index.ts +152 -0
  132. package/src/server/middleware/auth.ts +93 -0
  133. package/src/server/middleware/logger.ts +90 -0
  134. package/src/server/routes/health.ts +84 -0
  135. package/src/server/routes/translate.ts +210 -0
  136. package/src/server/types.ts +138 -0
  137. package/src/services/cache.ts +899 -0
  138. package/src/services/config.ts +217 -0
  139. package/src/services/glossary.ts +247 -0
  140. package/src/types/analysis.ts +164 -0
  141. package/src/types/index.ts +265 -0
  142. package/src/types/modes.ts +121 -0
  143. package/src/types/mqm.ts +157 -0
  144. package/src/utils/logger.ts +141 -0
  145. package/src/utils/tokens.ts +116 -0
  146. package/tests/fixtures/glossaries/ml-glossary.json +53 -0
  147. package/tests/fixtures/input/lynq-installation.ko.md +350 -0
  148. package/tests/fixtures/input/lynq-installation.md +350 -0
  149. package/tests/fixtures/input/simple.ko.md +27 -0
  150. package/tests/fixtures/input/simple.md +27 -0
  151. package/tests/unit/chunker.test.ts +229 -0
  152. package/tests/unit/glossary.test.ts +146 -0
  153. package/tests/unit/markdown.test.ts +205 -0
  154. package/tests/unit/tokens.test.ts +81 -0
  155. package/tsconfig.json +28 -0
  156. package/tsup.config.ts +34 -0
  157. package/vitest.config.ts +16 -0
@@ -0,0 +1,1152 @@
1
+ import { Root } from 'mdast';
2
+
3
+ /**
4
+ * Translation Mode Configurations
5
+ *
6
+ * Defines preset configurations for different translation quality/speed tradeoffs
7
+ */
8
+ /**
9
+ * Available translation modes
10
+ */
11
+ type TranslationMode = 'fast' | 'balanced' | 'quality';
12
+
13
+ type ProviderName = 'claude' | 'openai' | 'ollama' | 'custom';
14
+ interface TranslateConfig {
15
+ version: string;
16
+ project?: {
17
+ name: string;
18
+ description: string;
19
+ purpose: string;
20
+ };
21
+ languages: {
22
+ source: string;
23
+ targets: string[];
24
+ /** Per-language style instructions (e.g., { "ko": "경어체", "ja": "です・ます調" }) */
25
+ styles?: Record<string, string>;
26
+ };
27
+ provider: {
28
+ default: ProviderName;
29
+ model?: string;
30
+ fallback?: ProviderName[];
31
+ apiKeys?: Record<ProviderName, string>;
32
+ };
33
+ quality: {
34
+ threshold: number;
35
+ maxIterations: number;
36
+ evaluationMethod: 'llm' | 'embedding' | 'hybrid';
37
+ };
38
+ chunking: {
39
+ maxTokens: number;
40
+ overlapTokens: number;
41
+ preserveStructure: boolean;
42
+ };
43
+ glossary?: {
44
+ path: string;
45
+ strict: boolean;
46
+ };
47
+ paths: {
48
+ output: string;
49
+ cache?: string;
50
+ };
51
+ ignore?: string[];
52
+ }
53
+ interface Glossary {
54
+ metadata: {
55
+ name: string;
56
+ sourceLang: string;
57
+ targetLangs: string[];
58
+ version: string;
59
+ domain?: string;
60
+ };
61
+ terms: GlossaryTerm[];
62
+ }
63
+ interface GlossaryTerm {
64
+ source: string;
65
+ targets: Record<string, string>;
66
+ context?: string;
67
+ caseSensitive?: boolean;
68
+ doNotTranslate?: boolean;
69
+ doNotTranslateFor?: string[];
70
+ partOfSpeech?: 'noun' | 'verb' | 'adjective' | 'other';
71
+ notes?: string;
72
+ }
73
+ interface ResolvedGlossary {
74
+ metadata: {
75
+ name: string;
76
+ sourceLang: string;
77
+ targetLang: string;
78
+ version: string;
79
+ domain?: string;
80
+ };
81
+ terms: ResolvedGlossaryTerm[];
82
+ }
83
+ interface ResolvedGlossaryTerm {
84
+ source: string;
85
+ target: string;
86
+ context?: string;
87
+ caseSensitive: boolean;
88
+ doNotTranslate: boolean;
89
+ }
90
+ type DocumentFormat = 'markdown' | 'html' | 'text';
91
+ interface TranslationRequest {
92
+ content: string;
93
+ sourceLang: string;
94
+ targetLang: string;
95
+ format: DocumentFormat;
96
+ glossary?: ResolvedGlossary;
97
+ context?: {
98
+ documentPurpose?: string;
99
+ /** Per-language style instruction (e.g., "경어체", "です・ます調") */
100
+ styleInstruction?: string;
101
+ previousChunks?: string[];
102
+ documentSummary?: string;
103
+ };
104
+ options?: {
105
+ qualityThreshold?: number;
106
+ maxIterations?: number;
107
+ preserveFormatting?: boolean;
108
+ };
109
+ }
110
+ interface TranslationResult {
111
+ content: string;
112
+ metadata: {
113
+ qualityScore: number;
114
+ qualityThreshold: number;
115
+ thresholdMet: boolean;
116
+ iterations: number;
117
+ tokensUsed: {
118
+ input: number;
119
+ output: number;
120
+ /** Tokens read from cache (90% cost reduction) */
121
+ cacheRead?: number;
122
+ /** Tokens written to cache (25% cost increase for first write) */
123
+ cacheWrite?: number;
124
+ };
125
+ duration: number;
126
+ provider: string;
127
+ model: string;
128
+ };
129
+ glossaryCompliance?: {
130
+ applied: string[];
131
+ missed: string[];
132
+ };
133
+ }
134
+ interface ChunkResult {
135
+ original: string;
136
+ translated: string;
137
+ startOffset: number;
138
+ endOffset: number;
139
+ qualityScore: number;
140
+ iterations?: number;
141
+ tokensUsed?: {
142
+ input: number;
143
+ output: number;
144
+ /** Number of cache hits for this chunk */
145
+ cacheRead?: number;
146
+ };
147
+ /** Whether this chunk was retrieved from cache */
148
+ cached?: boolean;
149
+ }
150
+ interface DocumentResult {
151
+ content: string;
152
+ chunks: ChunkResult[];
153
+ metadata: {
154
+ totalTokensUsed: number;
155
+ totalDuration: number;
156
+ averageQuality: number;
157
+ provider: string;
158
+ model: string;
159
+ totalIterations: number;
160
+ tokensUsed: {
161
+ input: number;
162
+ output: number;
163
+ /** Tokens read from cache (90% cost reduction) */
164
+ cacheRead?: number;
165
+ /** Tokens written to cache (25% cost increase for first write) */
166
+ cacheWrite?: number;
167
+ };
168
+ /** Cache statistics */
169
+ cache?: {
170
+ hits: number;
171
+ misses: number;
172
+ };
173
+ };
174
+ glossaryCompliance?: {
175
+ applied: string[];
176
+ missed: string[];
177
+ compliant: boolean;
178
+ };
179
+ }
180
+ interface Chunk {
181
+ id: string;
182
+ content: string;
183
+ type: 'translatable' | 'preserve';
184
+ startOffset: number;
185
+ endOffset: number;
186
+ metadata?: {
187
+ headerHierarchy?: string[];
188
+ previousContext?: string;
189
+ };
190
+ }
191
+ interface ChunkingConfig {
192
+ maxTokens: number;
193
+ overlapTokens: number;
194
+ separators: string[];
195
+ preservePatterns: RegExp[];
196
+ }
197
+ /**
198
+ * Legacy simple quality evaluation (for fast mode or fallback)
199
+ */
200
+ interface SimpleQualityEvaluation {
201
+ score: number;
202
+ breakdown: {
203
+ accuracy: number;
204
+ fluency: number;
205
+ glossary: number;
206
+ format: number;
207
+ };
208
+ issues: string[];
209
+ }
210
+
211
+ /**
212
+ * Combined quality evaluation type (supports both MQM and simple)
213
+ */
214
+ type QualityEvaluation = SimpleQualityEvaluation;
215
+ interface CacheEntry {
216
+ sourceHash: string;
217
+ sourceLang: string;
218
+ targetLang: string;
219
+ glossaryHash: string;
220
+ translation: string;
221
+ qualityScore: number;
222
+ createdAt: string;
223
+ provider: string;
224
+ model: string;
225
+ }
226
+ interface CacheIndex {
227
+ version: string;
228
+ entries: Record<string, CacheEntry>;
229
+ }
230
+
231
+ type ChatRole = 'system' | 'user' | 'assistant';
232
+ /**
233
+ * Content part with optional cache control for prompt caching
234
+ */
235
+ interface CacheableTextPart {
236
+ type: 'text';
237
+ text: string;
238
+ /** Enable prompt caching for this content part (Claude only) */
239
+ cacheControl?: {
240
+ type: 'ephemeral';
241
+ };
242
+ }
243
+ interface ChatMessage {
244
+ role: ChatRole;
245
+ /** Content can be a string or array of cacheable parts */
246
+ content: string | CacheableTextPart[];
247
+ }
248
+ interface ChatRequest {
249
+ messages: ChatMessage[];
250
+ model?: string;
251
+ temperature?: number;
252
+ maxTokens?: number;
253
+ }
254
+ interface ChatResponse {
255
+ content: string;
256
+ usage: {
257
+ inputTokens: number;
258
+ outputTokens: number;
259
+ /** Tokens read from cache (90% cost reduction) */
260
+ cacheReadTokens?: number;
261
+ /** Tokens written to cache (25% cost increase for first write) */
262
+ cacheWriteTokens?: number;
263
+ };
264
+ model: string;
265
+ finishReason: 'stop' | 'length' | 'error';
266
+ }
267
+ interface ModelInfo {
268
+ maxContextTokens: number;
269
+ supportsStreaming: boolean;
270
+ costPer1kInput?: number;
271
+ costPer1kOutput?: number;
272
+ }
273
+ interface ProviderConfig {
274
+ apiKey?: string;
275
+ baseUrl?: string;
276
+ defaultModel?: string;
277
+ timeout?: number;
278
+ }
279
+ interface LLMProvider {
280
+ readonly name: ProviderName;
281
+ /**
282
+ * The default model used by this provider
283
+ */
284
+ readonly defaultModel: string;
285
+ /**
286
+ * Send a chat request and receive a complete response
287
+ */
288
+ chat(request: ChatRequest): Promise<ChatResponse>;
289
+ /**
290
+ * Send a chat request and receive a streaming response
291
+ */
292
+ stream(request: ChatRequest): AsyncIterable<string>;
293
+ /**
294
+ * Count the number of tokens in a text string
295
+ */
296
+ countTokens(text: string): number;
297
+ /**
298
+ * Get information about a specific model
299
+ */
300
+ getModelInfo(model?: string): ModelInfo;
301
+ }
302
+ type ProviderFactory = (config: ProviderConfig) => LLMProvider;
303
+
304
+ declare enum ErrorCode {
305
+ CONFIG_NOT_FOUND = "CONFIG_NOT_FOUND",
306
+ CONFIG_INVALID = "CONFIG_INVALID",
307
+ GLOSSARY_NOT_FOUND = "GLOSSARY_NOT_FOUND",
308
+ GLOSSARY_INVALID = "GLOSSARY_INVALID",
309
+ PROVIDER_NOT_FOUND = "PROVIDER_NOT_FOUND",
310
+ PROVIDER_AUTH_FAILED = "PROVIDER_AUTH_FAILED",
311
+ PROVIDER_RATE_LIMITED = "PROVIDER_RATE_LIMITED",
312
+ PROVIDER_ERROR = "PROVIDER_ERROR",
313
+ QUALITY_THRESHOLD_NOT_MET = "QUALITY_THRESHOLD_NOT_MET",
314
+ GLOSSARY_COMPLIANCE_FAILED = "GLOSSARY_COMPLIANCE_FAILED",
315
+ FILE_NOT_FOUND = "FILE_NOT_FOUND",
316
+ FILE_READ_ERROR = "FILE_READ_ERROR",
317
+ FILE_WRITE_ERROR = "FILE_WRITE_ERROR",
318
+ UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT",
319
+ CHUNK_TOO_LARGE = "CHUNK_TOO_LARGE",
320
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
321
+ }
322
+ declare class TranslationError extends Error {
323
+ readonly code: ErrorCode;
324
+ readonly details?: Record<string, unknown>;
325
+ constructor(code: ErrorCode, details?: Record<string, unknown>, customMessage?: string);
326
+ /**
327
+ * Create a JSON representation of the error
328
+ */
329
+ toJSON(): Record<string, unknown>;
330
+ }
331
+ declare function isTranslationError(error: unknown): error is TranslationError;
332
+ declare function isErrorCode(error: unknown, code: ErrorCode): boolean;
333
+ declare const ExitCode: {
334
+ readonly SUCCESS: 0;
335
+ readonly GENERAL_ERROR: 1;
336
+ readonly INVALID_ARGUMENTS: 2;
337
+ readonly FILE_NOT_FOUND: 3;
338
+ readonly QUALITY_THRESHOLD_NOT_MET: 4;
339
+ readonly PROVIDER_ERROR: 5;
340
+ readonly GLOSSARY_VALIDATION_FAILED: 6;
341
+ };
342
+ type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
343
+ /**
344
+ * Map error codes to exit codes
345
+ */
346
+ declare function getExitCode(error: TranslationError): ExitCode;
347
+
348
+ interface LoadConfigOptions {
349
+ configPath?: string;
350
+ cwd?: string;
351
+ }
352
+ declare function loadConfig(options?: LoadConfigOptions): Promise<TranslateConfig>;
353
+ interface CLIOverrides {
354
+ sourceLang?: string;
355
+ targetLang?: string;
356
+ provider?: ProviderName;
357
+ model?: string;
358
+ quality?: number;
359
+ maxIterations?: number;
360
+ chunkSize?: number;
361
+ glossary?: string;
362
+ output?: string;
363
+ noCache?: boolean;
364
+ }
365
+ declare function mergeConfig(config: TranslateConfig, overrides: CLIOverrides): TranslateConfig;
366
+
367
+ declare function loadGlossary(path: string): Promise<Glossary>;
368
+ declare function resolveGlossary(glossary: Glossary, targetLang: string): ResolvedGlossary;
369
+ interface GlossaryLookup {
370
+ /**
371
+ * Find a term in the glossary
372
+ */
373
+ find(text: string): ResolvedGlossaryTerm | undefined;
374
+ /**
375
+ * Find all matching terms in a text
376
+ */
377
+ findAll(text: string): ResolvedGlossaryTerm[];
378
+ /**
379
+ * Get all terms
380
+ */
381
+ getTerms(): ResolvedGlossaryTerm[];
382
+ /**
383
+ * Format glossary for prompt injection
384
+ */
385
+ formatForPrompt(): string;
386
+ }
387
+ declare function createGlossaryLookup(glossary: ResolvedGlossary): GlossaryLookup;
388
+ interface ComplianceResult {
389
+ applied: string[];
390
+ missed: string[];
391
+ score: number;
392
+ }
393
+ declare function checkGlossaryCompliance(sourceText: string, translatedText: string, glossary: ResolvedGlossary): ComplianceResult;
394
+
395
+ /**
396
+ * Translation Cache Service
397
+ *
398
+ * File-based caching using content hashes to avoid re-translating unchanged content.
399
+ * Cache entries are indexed by a composite key of content hash, target language,
400
+ * glossary hash, provider, and model.
401
+ */
402
+
403
+ /**
404
+ * Context provided to invalidation policies for evaluation
405
+ */
406
+ interface InvalidationContext {
407
+ /** Current glossary hash (if glossary is used) */
408
+ glossaryHash?: string;
409
+ /** Previous glossary hash (stored in cache metadata) */
410
+ previousGlossaryHash?: string;
411
+ /** Provider name */
412
+ provider?: string;
413
+ /** Model name */
414
+ model?: string;
415
+ /** Cache entry creation timestamp */
416
+ entryCreatedAt?: string;
417
+ /** Current timestamp */
418
+ currentTime?: Date;
419
+ /** Custom metadata for policy-specific checks */
420
+ metadata?: Record<string, unknown>;
421
+ }
422
+ /**
423
+ * Result of an invalidation check
424
+ */
425
+ interface InvalidationResult {
426
+ /** Whether invalidation should occur */
427
+ shouldInvalidate: boolean;
428
+ /** Reason for invalidation (for logging) */
429
+ reason?: string;
430
+ /** Scope of invalidation */
431
+ scope: 'all' | 'matching' | 'none';
432
+ /** Filter function for 'matching' scope - returns true if entry should be invalidated */
433
+ filter?: (entry: CacheEntry, key: string) => boolean;
434
+ }
435
+ /**
436
+ * Abstract invalidation policy interface
437
+ */
438
+ interface InvalidationPolicy {
439
+ /** Policy name for logging */
440
+ readonly name: string;
441
+ /** Check if cache should be invalidated */
442
+ check(context: InvalidationContext): InvalidationResult;
443
+ }
444
+ /**
445
+ * Invalidates all cache entries when glossary changes
446
+ */
447
+ declare class GlossaryChangePolicy implements InvalidationPolicy {
448
+ readonly name = "GlossaryChangePolicy";
449
+ private readonly mode;
450
+ /**
451
+ * @param mode - 'all' invalidates entire cache, 'matching' only entries with old glossary hash
452
+ */
453
+ constructor(mode?: 'all' | 'matching');
454
+ check(context: InvalidationContext): InvalidationResult;
455
+ }
456
+ /**
457
+ * Invalidates cache entries older than specified TTL
458
+ */
459
+ declare class TTLPolicy implements InvalidationPolicy {
460
+ readonly name = "TTLPolicy";
461
+ private readonly ttlMs;
462
+ /**
463
+ * @param ttlMs - Time-to-live in milliseconds
464
+ */
465
+ constructor(ttlMs: number);
466
+ /**
467
+ * Create policy with TTL in hours
468
+ */
469
+ static hours(hours: number): TTLPolicy;
470
+ /**
471
+ * Create policy with TTL in days
472
+ */
473
+ static days(days: number): TTLPolicy;
474
+ check(context: InvalidationContext): InvalidationResult;
475
+ }
476
+ /**
477
+ * Invalidates cache entries when provider or model changes
478
+ */
479
+ declare class ProviderChangePolicy implements InvalidationPolicy {
480
+ readonly name = "ProviderChangePolicy";
481
+ private readonly checkModel;
482
+ /**
483
+ * @param checkModel - If true, also invalidate when model changes within same provider
484
+ */
485
+ constructor(checkModel?: boolean);
486
+ check(context: InvalidationContext): InvalidationResult;
487
+ }
488
+ /**
489
+ * Invalidates cache entries below a quality threshold
490
+ */
491
+ declare class QualityThresholdPolicy implements InvalidationPolicy {
492
+ readonly name = "QualityThresholdPolicy";
493
+ private readonly threshold;
494
+ /**
495
+ * @param threshold - Minimum quality score (0-100)
496
+ */
497
+ constructor(threshold: number);
498
+ check(_context: InvalidationContext): InvalidationResult;
499
+ }
500
+ /**
501
+ * Combines multiple policies - invalidates if ANY policy triggers
502
+ */
503
+ declare class CompositePolicy implements InvalidationPolicy {
504
+ readonly name = "CompositePolicy";
505
+ private readonly policies;
506
+ private readonly mode;
507
+ /**
508
+ * @param policies - Array of policies to combine
509
+ * @param mode - 'any' triggers if any policy matches, 'all' requires all policies to match
510
+ */
511
+ constructor(policies: InvalidationPolicy[], mode?: 'any' | 'all');
512
+ check(context: InvalidationContext): InvalidationResult;
513
+ }
514
+ interface CacheOptions {
515
+ /** Cache directory path */
516
+ cacheDir: string;
517
+ /** Enable verbose logging */
518
+ verbose?: boolean;
519
+ /** Invalidation policies to apply */
520
+ invalidationPolicies?: InvalidationPolicy[];
521
+ }
522
+ interface CacheKey {
523
+ /** Source content (will be hashed) */
524
+ content: string;
525
+ /** Source language */
526
+ sourceLang: string;
527
+ /** Target language */
528
+ targetLang: string;
529
+ /** Glossary content or hash (will be hashed if string) */
530
+ glossary?: string;
531
+ /** Provider name */
532
+ provider: string;
533
+ /** Model name */
534
+ model: string;
535
+ }
536
+ interface CacheStats {
537
+ /** Total number of cached entries */
538
+ entries: number;
539
+ /** Total cache size in bytes */
540
+ sizeBytes: number;
541
+ /** Cache version */
542
+ version: string;
543
+ /** Number of entries invalidated by policies */
544
+ invalidated?: number;
545
+ }
546
+ /**
547
+ * Cache metadata stored separately for tracking state across sessions
548
+ */
549
+ interface CacheMetadata {
550
+ /** Last known glossary hash */
551
+ glossaryHash?: string;
552
+ /** Last known provider */
553
+ provider?: string;
554
+ /** Last known model */
555
+ model?: string;
556
+ /** Last invalidation timestamp */
557
+ lastInvalidation?: string;
558
+ /** Custom metadata */
559
+ custom?: Record<string, unknown>;
560
+ }
561
+ interface CacheResult {
562
+ /** Whether the entry was found in cache */
563
+ hit: boolean;
564
+ /** The cached entry if found */
565
+ entry?: CacheEntry;
566
+ }
567
+ /**
568
+ * Generate SHA-256 hash of content
569
+ */
570
+ declare function hashContent(content: string): string;
571
+ /**
572
+ * Generate cache key from components
573
+ */
574
+ declare function generateCacheKey(key: CacheKey): string;
575
+ declare class CacheManager {
576
+ private cacheDir;
577
+ private indexPath;
578
+ private entriesDir;
579
+ private metadataPath;
580
+ private verbose;
581
+ private index;
582
+ private policies;
583
+ private metadata;
584
+ constructor(options: CacheOptions);
585
+ /**
586
+ * Initialize cache directory and load index
587
+ */
588
+ private ensureInitialized;
589
+ /**
590
+ * Load cache metadata from disk
591
+ */
592
+ private loadMetadata;
593
+ /**
594
+ * Save cache metadata to disk
595
+ */
596
+ private saveMetadata;
597
+ /**
598
+ * Update cache metadata
599
+ */
600
+ updateMetadata(updates: Partial<CacheMetadata>): void;
601
+ /**
602
+ * Get current cache metadata
603
+ */
604
+ getMetadata(): CacheMetadata;
605
+ /**
606
+ * Apply all configured invalidation policies
607
+ * @returns Number of entries invalidated
608
+ */
609
+ applyPolicies(context: InvalidationContext): number;
610
+ /**
611
+ * Invalidate entries matching a filter function
612
+ * @returns Number of entries invalidated
613
+ */
614
+ invalidateMatching(filter: (entry: CacheEntry, key: string) => boolean): number;
615
+ /**
616
+ * Add an invalidation policy at runtime
617
+ */
618
+ addPolicy(policy: InvalidationPolicy): void;
619
+ /**
620
+ * Remove an invalidation policy by name
621
+ */
622
+ removePolicy(name: string): boolean;
623
+ /**
624
+ * Get all configured policies
625
+ */
626
+ getPolicies(): InvalidationPolicy[];
627
+ /**
628
+ * Save index to disk
629
+ */
630
+ private saveIndex;
631
+ /**
632
+ * Get cached translation if available
633
+ */
634
+ get(key: CacheKey): CacheResult;
635
+ /**
636
+ * Store translation in cache
637
+ */
638
+ set(key: CacheKey, translation: string, qualityScore: number): void;
639
+ /**
640
+ * Check if entry exists in cache
641
+ */
642
+ has(key: CacheKey): boolean;
643
+ /**
644
+ * Remove entry from cache
645
+ */
646
+ delete(key: CacheKey): boolean;
647
+ /**
648
+ * Clear entire cache (synchronous)
649
+ */
650
+ private clearSync;
651
+ /**
652
+ * Clear entire cache
653
+ */
654
+ clear(): void;
655
+ /**
656
+ * Get cache statistics
657
+ */
658
+ getStats(): CacheStats;
659
+ /**
660
+ * Get all cached entries (for debugging)
661
+ */
662
+ getAllEntries(): Record<string, CacheEntry>;
663
+ }
664
+ /**
665
+ * Create a cache manager instance
666
+ */
667
+ declare function createCacheManager(options: CacheOptions): CacheManager;
668
+ /**
669
+ * Create a no-op cache manager that never caches (for --no-cache mode)
670
+ */
671
+ declare function createNullCacheManager(): CacheManager & {
672
+ isNull: true;
673
+ };
674
+ /**
675
+ * Create default invalidation policies for typical translation workflow
676
+ */
677
+ declare function createDefaultPolicies(): InvalidationPolicy[];
678
+ /**
679
+ * Create strict invalidation policies (more aggressive invalidation)
680
+ */
681
+ declare function createStrictPolicies(qualityThreshold?: number): InvalidationPolicy[];
682
+ /**
683
+ * Create minimal invalidation policies (only glossary changes)
684
+ */
685
+ declare function createMinimalPolicies(): InvalidationPolicy[];
686
+
687
+ declare function registerProvider(name: ProviderName, factory: ProviderFactory): void;
688
+ declare function getProvider(name: ProviderName, config?: ProviderConfig): LLMProvider;
689
+ declare function hasProvider(name: ProviderName): boolean;
690
+ declare function getAvailableProviders(): ProviderName[];
691
+ declare function getProviderConfigFromEnv(name: ProviderName): ProviderConfig;
692
+ interface CreateProviderOptions {
693
+ primary: ProviderName;
694
+ fallback?: ProviderName[];
695
+ config?: Partial<Record<ProviderName, ProviderConfig>>;
696
+ }
697
+ declare function createProviderWithFallback(options: CreateProviderOptions): LLMProvider;
698
+
699
+ declare class ClaudeProvider implements LLMProvider {
700
+ readonly name: ProviderName;
701
+ readonly defaultModel: string;
702
+ private readonly client;
703
+ constructor(config?: ProviderConfig);
704
+ chat(request: ChatRequest): Promise<ChatResponse>;
705
+ /**
706
+ * Convert messages to Vercel AI SDK format with cache control support
707
+ */
708
+ private convertMessages;
709
+ stream(request: ChatRequest): AsyncIterable<string>;
710
+ countTokens(text: string): number;
711
+ getModelInfo(model?: string): ModelInfo;
712
+ private handleError;
713
+ }
714
+ declare function createClaudeProvider(config?: ProviderConfig): LLMProvider;
715
+
716
+ interface ChunkerOptions {
717
+ maxTokens?: number;
718
+ overlapTokens?: number;
719
+ preserveCodeBlocks?: boolean;
720
+ }
721
+ /**
722
+ * Split content into chunks that respect token limits
723
+ */
724
+ declare function chunkContent(content: string, options?: ChunkerOptions): Chunk[];
725
+ /**
726
+ * Reassemble chunks back into a document
727
+ * Note: Chunks should not have overlapping content - overlap is only used for context metadata
728
+ */
729
+ declare function reassembleChunks(chunks: Chunk[]): string;
730
+ /**
731
+ * Get chunk statistics
732
+ */
733
+ declare function getChunkStats(chunks: Chunk[]): {
734
+ totalChunks: number;
735
+ translatableChunks: number;
736
+ preservedChunks: number;
737
+ totalTokens: number;
738
+ averageTokens: number;
739
+ };
740
+
741
+ interface TranslationAgentOptions {
742
+ provider: LLMProvider;
743
+ qualityThreshold?: number;
744
+ maxIterations?: number;
745
+ verbose?: boolean;
746
+ /** If true, throw error when quality threshold is not met after max iterations */
747
+ strictQuality?: boolean;
748
+ /** Enable prompt caching for Claude provider (default: true) */
749
+ enableCaching?: boolean;
750
+ /** Translation mode: fast, balanced, quality (default: balanced) */
751
+ mode?: TranslationMode;
752
+ /** Enable pre-translation analysis (MAPS-style) - overrides mode setting */
753
+ enableAnalysis?: boolean;
754
+ /** Use MQM-based evaluation - overrides mode setting */
755
+ useMQMEvaluation?: boolean;
756
+ }
757
+ declare class TranslationAgent {
758
+ private provider;
759
+ private qualityThreshold;
760
+ private maxIterations;
761
+ private verbose;
762
+ private strictQuality;
763
+ private enableCaching;
764
+ private enableAnalysis;
765
+ private useMQMEvaluation;
766
+ constructor(options: TranslationAgentOptions);
767
+ /**
768
+ * Translate content using Self-Refine loop with optional MAPS analysis and MQM evaluation
769
+ */
770
+ translate(request: TranslationRequest): Promise<TranslationResult>;
771
+ private generateInitialTranslation;
772
+ private generateReflection;
773
+ private improveTranslation;
774
+ private evaluateQuality;
775
+ /**
776
+ * Pre-translation analysis using MAPS-style approach
777
+ * Identifies key terms, ambiguous phrases, and translation challenges
778
+ */
779
+ private analyzeSource;
780
+ /**
781
+ * Evaluate translation quality using MQM framework
782
+ * Returns structured error annotations for targeted refinement
783
+ */
784
+ private evaluateQualityMQM;
785
+ /**
786
+ * Refine translation based on MQM error annotations
787
+ * Applies targeted fixes for identified errors
788
+ */
789
+ private refineWithMQM;
790
+ /**
791
+ * Clean up translation output by removing prompt artifacts
792
+ * Uses guardrails to detect and remove any trailing prompt-like content
793
+ */
794
+ private cleanTranslationOutput;
795
+ /**
796
+ * Preserve leading/trailing whitespace from source text in translated text
797
+ * This ensures document structure (line breaks between sections) is maintained
798
+ */
799
+ private preserveWhitespace;
800
+ private checkGlossaryCompliance;
801
+ }
802
+ declare function createTranslationAgent(options: TranslationAgentOptions): TranslationAgent;
803
+
804
+ interface TranslationEngineOptions {
805
+ config: TranslateConfig;
806
+ provider?: LLMProvider;
807
+ verbose?: boolean;
808
+ /** Disable caching (--no-cache mode) */
809
+ noCache?: boolean;
810
+ }
811
+ interface TranslateFileOptions {
812
+ content: string;
813
+ sourceLang: string;
814
+ targetLang: string;
815
+ format?: DocumentFormat;
816
+ glossaryPath?: string;
817
+ qualityThreshold?: number;
818
+ maxIterations?: number;
819
+ context?: string;
820
+ /** Per-language style instruction (e.g., "경어체", "です・ます調"). Falls back to config.languages.styles[targetLang] if not specified. */
821
+ styleInstruction?: string;
822
+ /** If true, throw error when quality threshold is not met */
823
+ strictQuality?: boolean;
824
+ /** If true, throw error when glossary terms are missed */
825
+ strictGlossary?: boolean;
826
+ }
827
+ declare class TranslationEngine {
828
+ private config;
829
+ private provider;
830
+ private verbose;
831
+ private cache;
832
+ private cacheHits;
833
+ private cacheMisses;
834
+ constructor(options: TranslationEngineOptions);
835
+ /**
836
+ * Translate a single file/content
837
+ */
838
+ translateContent(options: TranslateFileOptions): Promise<DocumentResult>;
839
+ /**
840
+ * Check glossary compliance for the entire document
841
+ */
842
+ private checkDocumentGlossaryCompliance;
843
+ private translateMarkdown;
844
+ private translatePlainText;
845
+ private translateChunk;
846
+ private detectFormat;
847
+ }
848
+ declare function createTranslationEngine(options: TranslationEngineOptions): TranslationEngine;
849
+ declare function translateText(content: string, sourceLang: string, targetLang: string, options?: {
850
+ provider?: LLMProvider;
851
+ glossaryPath?: string;
852
+ qualityThreshold?: number;
853
+ maxIterations?: number;
854
+ verbose?: boolean;
855
+ }): Promise<string>;
856
+
857
+ interface ParsedDocument {
858
+ /** Original markdown content */
859
+ original: string;
860
+ /** AST representation */
861
+ ast: Root;
862
+ /** Extracted text nodes for translation */
863
+ textNodes: TextNode[];
864
+ }
865
+ interface TextNode {
866
+ /** Unique identifier for this node */
867
+ id: string;
868
+ /** Text content to translate */
869
+ content: string;
870
+ /** Node type in AST */
871
+ type: string;
872
+ /** Position in source document */
873
+ position?: {
874
+ start: {
875
+ line: number;
876
+ column: number;
877
+ offset?: number;
878
+ };
879
+ end: {
880
+ line: number;
881
+ column: number;
882
+ offset?: number;
883
+ };
884
+ };
885
+ /** Path to node in AST (for restoration) */
886
+ path: number[];
887
+ /** Whether this node should be translated */
888
+ translatable: boolean;
889
+ }
890
+ interface TranslationMap {
891
+ [nodeId: string]: string;
892
+ }
893
+ /**
894
+ * Parse markdown content and extract translatable text nodes
895
+ */
896
+ declare function parseMarkdown(content: string): Promise<ParsedDocument>;
897
+ /**
898
+ * Apply translations to AST and stringify back to markdown
899
+ */
900
+ declare function applyTranslations(document: ParsedDocument, translations: TranslationMap): Promise<string>;
901
+ /**
902
+ * Get only translatable text from a parsed document
903
+ */
904
+ declare function getTranslatableText(document: ParsedDocument): string[];
905
+ /**
906
+ * Create a translation map from an array of translations
907
+ * (in same order as getTranslatableText output)
908
+ */
909
+ declare function createTranslationMap(document: ParsedDocument, translations: string[]): TranslationMap;
910
+ /**
911
+ * Extract full text content for translation (preserving structure markers)
912
+ *
913
+ * Processing order is important:
914
+ * 1. First, handle fenced code blocks (must be at line start with newline after opener)
915
+ * 2. Then, handle multi-backtick inline code (for examples like ` ```js...``` `)
916
+ * 3. Then, handle single-backtick inline code
917
+ * 4. Finally, handle link URLs
918
+ */
919
+ declare function extractTextForTranslation(content: string): {
920
+ text: string;
921
+ preservedSections: Map<string, string>;
922
+ };
923
+ /**
924
+ * Restore preserved sections after translation
925
+ *
926
+ * Uses flexible regex matching to handle cases where LLM may have:
927
+ * - Added spaces around placeholders
928
+ * - Changed case
929
+ * - Added extra underscores
930
+ */
931
+ declare function restorePreservedSections(translatedText: string, preservedSections: Map<string, string>): string;
932
+ /**
933
+ * Simple markdown translation that preserves structure
934
+ * This is the main function to use for translating markdown content
935
+ */
936
+ declare function translateMarkdownContent(content: string, translateFn: (text: string) => Promise<string>): Promise<string>;
937
+
938
+ /**
939
+ * Approximate token count for a given text.
940
+ * This is a rough estimate - actual token counts may vary by model.
941
+ *
942
+ * Rules of thumb:
943
+ * - English: ~4 characters per token
944
+ * - CJK (Korean, Japanese, Chinese): ~1.5 characters per token
945
+ * - Code: ~3.5 characters per token
946
+ */
947
+ declare function estimateTokens(text: string): number;
948
+ /**
949
+ * Check if text exceeds a token limit
950
+ */
951
+ declare function exceedsTokenLimit(text: string, limit: number): boolean;
952
+ /**
953
+ * Truncate text to approximately fit within a token limit
954
+ */
955
+ declare function truncateToTokenLimit(text: string, limit: number): string;
956
+
957
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
958
+ interface LoggerConfig {
959
+ level: LogLevel;
960
+ quiet: boolean;
961
+ json: boolean;
962
+ }
963
+ declare function configureLogger(options: Partial<LoggerConfig>): void;
964
+ declare const logger: {
965
+ debug(message: string, data?: Record<string, unknown>): void;
966
+ info(message: string, data?: Record<string, unknown>): void;
967
+ warn(message: string, data?: Record<string, unknown>): void;
968
+ error(message: string, data?: Record<string, unknown>): void;
969
+ success(message: string): void;
970
+ progress(current: number, total: number, message: string): void;
971
+ };
972
+ declare function createTimer(): {
973
+ elapsed: () => number;
974
+ format: () => string;
975
+ };
976
+
977
+ /**
978
+ * VitePress Integration Helpers
979
+ *
980
+ * Helper functions to auto-generate VitePress i18n configuration
981
+ * based on translated document structure.
982
+ *
983
+ * @example
984
+ * ```typescript
985
+ * // docs/.vitepress/config.ts
986
+ * import { defineConfig } from 'vitepress';
987
+ * import { generateLocaleConfig } from 'llm-translate/vitepress';
988
+ *
989
+ * const locales = await generateLocaleConfig('./docs', {
990
+ * defaultLocale: 'en',
991
+ * locales: ['ko', 'ja'],
992
+ * });
993
+ *
994
+ * export default defineConfig({ locales });
995
+ * ```
996
+ */
997
+ /**
998
+ * Navigation item with a link
999
+ * Compatible with VitePress DefaultTheme.NavItemWithLink
1000
+ */
1001
+ interface NavItemWithLink {
1002
+ text: string;
1003
+ link: string;
1004
+ activeMatch?: string;
1005
+ rel?: string;
1006
+ target?: string;
1007
+ noIcon?: boolean;
1008
+ }
1009
+ /**
1010
+ * Navigation item with children
1011
+ * Compatible with VitePress DefaultTheme.NavItemWithChildren
1012
+ */
1013
+ interface NavItemWithChildren {
1014
+ text?: string;
1015
+ items: NavItemWithLink[];
1016
+ activeMatch?: string;
1017
+ }
1018
+ /**
1019
+ * Navigation item type
1020
+ * Compatible with VitePress DefaultTheme.NavItem
1021
+ */
1022
+ type NavItem = NavItemWithLink | NavItemWithChildren;
1023
+ /**
1024
+ * Sidebar item
1025
+ * Compatible with VitePress DefaultTheme.SidebarItem
1026
+ */
1027
+ interface SidebarItem {
1028
+ text?: string;
1029
+ link?: string;
1030
+ items?: SidebarItem[];
1031
+ collapsed?: boolean;
1032
+ base?: string;
1033
+ docFooterText?: string;
1034
+ rel?: string;
1035
+ target?: string;
1036
+ }
1037
+ /**
1038
+ * Theme configuration
1039
+ * Compatible with VitePress DefaultTheme.Config
1040
+ */
1041
+ interface ThemeConfig {
1042
+ nav?: NavItem[];
1043
+ sidebar?: SidebarItem[] | Record<string, SidebarItem[]>;
1044
+ editLink?: {
1045
+ pattern: string;
1046
+ text?: string;
1047
+ };
1048
+ docFooter?: {
1049
+ prev?: string | false;
1050
+ next?: string | false;
1051
+ };
1052
+ outline?: {
1053
+ level?: number | [number, number] | 'deep';
1054
+ label?: string;
1055
+ };
1056
+ lastUpdated?: {
1057
+ text?: string;
1058
+ formatOptions?: Intl.DateTimeFormatOptions;
1059
+ };
1060
+ returnToTopLabel?: string;
1061
+ sidebarMenuLabel?: string;
1062
+ darkModeSwitchLabel?: string;
1063
+ langMenuLabel?: string;
1064
+ }
1065
+ /**
1066
+ * Locale configuration
1067
+ * Compatible with VitePress LocaleConfig
1068
+ */
1069
+ interface LocaleConfig {
1070
+ label: string;
1071
+ lang?: string;
1072
+ link?: string;
1073
+ description?: string;
1074
+ themeConfig?: ThemeConfig;
1075
+ }
1076
+ /**
1077
+ * Options for generating locale configuration
1078
+ */
1079
+ interface GenerateOptions {
1080
+ /** Default locale code (e.g., 'en') */
1081
+ defaultLocale?: string;
1082
+ /** List of locale codes to generate (e.g., ['ko', 'ja']) */
1083
+ locales?: string[];
1084
+ /** Locale display labels */
1085
+ labels?: Record<string, string>;
1086
+ /** Locale lang codes for HTML */
1087
+ langCodes?: Record<string, string>;
1088
+ /** Locale descriptions */
1089
+ descriptions?: Record<string, string>;
1090
+ /** Directories to include in sidebar (default: auto-detect) */
1091
+ sidebarDirs?: string[];
1092
+ /** Use title from file's first heading */
1093
+ useTitleFromHeading?: boolean;
1094
+ /** Custom locale translations */
1095
+ translations?: Record<string, LocaleTranslations>;
1096
+ }
1097
+ interface LocaleTranslations {
1098
+ editLinkText?: string;
1099
+ docFooter?: {
1100
+ prev: string;
1101
+ next: string;
1102
+ };
1103
+ outline?: {
1104
+ label: string;
1105
+ };
1106
+ lastUpdated?: {
1107
+ text: string;
1108
+ };
1109
+ returnToTopLabel?: string;
1110
+ sidebarMenuLabel?: string;
1111
+ darkModeSwitchLabel?: string;
1112
+ }
1113
+ /**
1114
+ * Auto-detect available locales by scanning for locale directories
1115
+ */
1116
+ declare function detectLocales(docsDir: string, defaultLocale?: string): string[];
1117
+ /**
1118
+ * Auto-detect sidebar directories by looking at root structure
1119
+ */
1120
+ declare function detectSidebarDirs(docsDir: string): string[];
1121
+ /**
1122
+ * Generate locale configuration for a specific locale
1123
+ */
1124
+ declare function generateLocale(docsDir: string, locale: string, options?: GenerateOptions): LocaleConfig;
1125
+ /**
1126
+ * Generate complete locale configuration for VitePress
1127
+ *
1128
+ * @example
1129
+ * ```typescript
1130
+ * import { defineConfig } from 'vitepress';
1131
+ * import { generateLocaleConfig } from 'llm-translate';
1132
+ *
1133
+ * const locales = generateLocaleConfig('./docs', {
1134
+ * defaultLocale: 'en',
1135
+ * locales: ['ko', 'ja'],
1136
+ * });
1137
+ *
1138
+ * export default defineConfig({
1139
+ * locales,
1140
+ * // ... other config
1141
+ * });
1142
+ * ```
1143
+ */
1144
+ declare function generateLocaleConfig(docsDir: string, options?: GenerateOptions): Record<string, LocaleConfig>;
1145
+ /**
1146
+ * Generate sidebar configuration only
1147
+ *
1148
+ * Useful when you want to manually configure nav but auto-generate sidebar.
1149
+ */
1150
+ declare function generateSidebarConfig(docsDir: string, options?: Omit<GenerateOptions, 'descriptions' | 'translations'>): Record<string, Record<string, SidebarItem[]>>;
1151
+
1152
+ export { type CacheEntry, type CacheIndex, type CacheKey, CacheManager, type CacheMetadata, type CacheOptions, type CacheResult, type CacheStats, type ChatMessage, type ChatRequest, type ChatResponse, type Chunk, type ChunkResult, type ChunkingConfig, ClaudeProvider, CompositePolicy, type DocumentFormat, type DocumentResult, ErrorCode, ExitCode, type GenerateOptions, type Glossary, GlossaryChangePolicy, type GlossaryTerm, type InvalidationContext, type InvalidationPolicy, type InvalidationResult, type LLMProvider, type LocaleConfig, type LocaleTranslations, type ModelInfo, type NavItem, type NavItemWithChildren, type NavItemWithLink, ProviderChangePolicy, type ProviderConfig, type ProviderName, type QualityEvaluation, QualityThresholdPolicy, type ResolvedGlossary, type ResolvedGlossaryTerm, type SidebarItem, TTLPolicy, type ThemeConfig, type TranslateConfig, TranslationAgent, TranslationEngine, TranslationError, type TranslationRequest, type TranslationResult, applyTranslations, checkGlossaryCompliance, chunkContent, configureLogger, createCacheManager, createClaudeProvider, createDefaultPolicies, createGlossaryLookup, createMinimalPolicies, createNullCacheManager, createProviderWithFallback, createStrictPolicies, createTimer, createTranslationAgent, createTranslationEngine, createTranslationMap, detectLocales, detectSidebarDirs, estimateTokens, exceedsTokenLimit, extractTextForTranslation, generateCacheKey, generateLocale, generateLocaleConfig, generateSidebarConfig, getAvailableProviders, getChunkStats, getExitCode, getProvider, getProviderConfigFromEnv, getTranslatableText, hasProvider, hashContent, isErrorCode, isTranslationError, loadConfig, loadGlossary, logger, mergeConfig, parseMarkdown, reassembleChunks, registerProvider, resolveGlossary, restorePreservedSections, translateMarkdownContent, translateText, truncateToTokenLimit };