docs-i18n 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# docs-i18n
|
|
2
2
|
|
|
3
|
-
Universal documentation translation engine. Parse markdown/MDX into translatable nodes, translate via LLM, cache in SQLite
|
|
3
|
+
Universal documentation translation engine. Parse markdown/MDX into translatable nodes, translate via LLM, cache in SQLite, manage with admin dashboard.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -8,17 +8,20 @@ Universal documentation translation engine. Parse markdown/MDX into translatable
|
|
|
8
8
|
- **Incremental translation** — only translates changed/new content
|
|
9
9
|
- **Smart chunking** — respects LLM context window and output token limits
|
|
10
10
|
- **YAML-aware frontmatter** — translates title/description fields individually
|
|
11
|
-
- **SQLite cache** — concurrent-safe with WAL mode
|
|
11
|
+
- **SQLite cache** — concurrent-safe with WAL mode
|
|
12
12
|
- **Admin dashboard** — web UI for managing translation progress and jobs
|
|
13
|
+
- **Runtime serve** — D1-compatible translator for SSR sites
|
|
13
14
|
- **Framework-agnostic** — works with any docs site (Next.js, Astro, TanStack Start, etc.)
|
|
14
15
|
|
|
15
16
|
## Quick Start
|
|
16
17
|
|
|
17
18
|
```bash
|
|
18
19
|
npm install docs-i18n
|
|
20
|
+
# or
|
|
21
|
+
bun add docs-i18n
|
|
19
22
|
```
|
|
20
23
|
|
|
21
|
-
Create `docs-i18n.config.ts
|
|
24
|
+
Create `docs-i18n.config.ts` in your project root:
|
|
22
25
|
|
|
23
26
|
```ts
|
|
24
27
|
import { defineConfig } from 'docs-i18n';
|
|
@@ -26,34 +29,133 @@ import { defineConfig } from 'docs-i18n';
|
|
|
26
29
|
export default defineConfig({
|
|
27
30
|
projects: {
|
|
28
31
|
mydocs: {
|
|
29
|
-
sources: {
|
|
32
|
+
sources: {
|
|
33
|
+
latest: 'content/latest',
|
|
34
|
+
v1: 'content/v1',
|
|
35
|
+
},
|
|
30
36
|
},
|
|
31
37
|
},
|
|
32
38
|
languages: ['zh-hans', 'ja', 'es'],
|
|
39
|
+
cacheDir: '.cache',
|
|
40
|
+
translatableFields: ['title', 'description', 'nav_title'],
|
|
41
|
+
llm: {
|
|
42
|
+
provider: 'openrouter', // or 'openai', 'anthropic'
|
|
43
|
+
model: 'qwen/qwen3.5-flash-02-23',
|
|
44
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
45
|
+
contextLength: 1_000_000,
|
|
46
|
+
maxTokens: 65536,
|
|
47
|
+
},
|
|
33
48
|
context: 'MyProject is a TypeScript library for building web apps.',
|
|
34
49
|
});
|
|
35
50
|
```
|
|
36
51
|
|
|
52
|
+
## CLI
|
|
53
|
+
|
|
37
54
|
```bash
|
|
55
|
+
# Check translation progress
|
|
56
|
+
docs-i18n status
|
|
57
|
+
|
|
38
58
|
# Translate
|
|
39
59
|
docs-i18n translate --lang zh-hans
|
|
60
|
+
docs-i18n translate --lang zh-hans --version latest --dry-run
|
|
61
|
+
docs-i18n translate --lang zh-hans --files docs/intro.mdx,docs/guide.mdx
|
|
40
62
|
|
|
41
|
-
#
|
|
42
|
-
docs-i18n
|
|
63
|
+
# Assemble translated files (EN source + cache → output)
|
|
64
|
+
docs-i18n assemble
|
|
65
|
+
docs-i18n assemble --lang zh-hans --version latest
|
|
66
|
+
|
|
67
|
+
# Rescan source files and clean orphans
|
|
68
|
+
docs-i18n rescan
|
|
43
69
|
|
|
44
|
-
# Start admin dashboard
|
|
70
|
+
# Start admin dashboard (http://localhost:3456)
|
|
45
71
|
docs-i18n admin
|
|
72
|
+
docs-i18n admin --port 4000
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### npm scripts
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"scripts": {
|
|
80
|
+
"i18n": "docs-i18n",
|
|
81
|
+
"i18n:status": "docs-i18n status",
|
|
82
|
+
"i18n:admin": "docs-i18n admin",
|
|
83
|
+
"i18n:translate": "docs-i18n translate",
|
|
84
|
+
"i18n:assemble": "docs-i18n assemble",
|
|
85
|
+
"i18n:rescan": "docs-i18n rescan"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
46
88
|
```
|
|
47
89
|
|
|
48
|
-
##
|
|
90
|
+
## Multi-Project Support
|
|
91
|
+
|
|
92
|
+
For projects with multiple libraries (e.g., TanStack), use compound version keys:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
export default defineConfig({
|
|
96
|
+
projects: {
|
|
97
|
+
query: {
|
|
98
|
+
sources: { latest: 'content/query/latest', v4: 'content/query/v4' },
|
|
99
|
+
},
|
|
100
|
+
table: {
|
|
101
|
+
sources: { latest: 'content/table/latest' },
|
|
102
|
+
},
|
|
103
|
+
blog: {
|
|
104
|
+
sources: { latest: 'content/blog' },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
languages: ['zh-hans'],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The admin dashboard automatically groups by project.
|
|
112
|
+
|
|
113
|
+
## Runtime Translation (for SSR)
|
|
114
|
+
|
|
115
|
+
For SSR sites that fetch markdown at runtime (e.g., TanStack Start), use the serve module with Cloudflare D1:
|
|
49
116
|
|
|
50
117
|
```ts
|
|
51
118
|
import { createTranslator } from 'docs-i18n/serve';
|
|
52
119
|
|
|
53
120
|
const translator = createTranslator();
|
|
121
|
+
|
|
122
|
+
// In your request handler:
|
|
123
|
+
const enMarkdown = await fetchFromGitHub(repo, branch, filePath);
|
|
54
124
|
const translated = await translator.translate(enMarkdown, 'zh-hans', env.DB);
|
|
55
125
|
```
|
|
56
126
|
|
|
127
|
+
## Config Reference
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
interface DocsI18nConfig {
|
|
131
|
+
projects: Record<string, {
|
|
132
|
+
sources: Record<string, string>; // version → source directory
|
|
133
|
+
}>;
|
|
134
|
+
languages: string[]; // target languages
|
|
135
|
+
cacheDir?: string; // default: '.cache'
|
|
136
|
+
translatableFields?: string[]; // default: ['title', 'description', 'nav_title']
|
|
137
|
+
include?: string[]; // default: ['**/*.mdx', '**/*.md']
|
|
138
|
+
context?: string; // injected into LLM prompt
|
|
139
|
+
llm?: {
|
|
140
|
+
provider?: 'openrouter' | 'openai' | 'anthropic';
|
|
141
|
+
model?: string;
|
|
142
|
+
apiKey?: string;
|
|
143
|
+
contextLength?: number; // default: 32768
|
|
144
|
+
maxTokens?: number; // default: 16384
|
|
145
|
+
};
|
|
146
|
+
onTranslated?: (info: {
|
|
147
|
+
project: string;
|
|
148
|
+
version: string;
|
|
149
|
+
lang: string;
|
|
150
|
+
}) => Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Requirements
|
|
155
|
+
|
|
156
|
+
- Node.js 20+ or Bun
|
|
157
|
+
- Admin dashboard requires `vite` and `@vitejs/plugin-react` as dev dependencies
|
|
158
|
+
|
|
57
159
|
## License
|
|
58
160
|
|
|
59
161
|
MIT
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-SKKZIV3L.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
|
+
import { createRequire } from "module";
|
|
7
8
|
var args = process.argv.slice(2);
|
|
9
|
+
if (args[0] === "--version" || args[0] === "-v") {
|
|
10
|
+
const require2 = createRequire(import.meta.url);
|
|
11
|
+
const pkg = require2("../package.json");
|
|
12
|
+
console.log(pkg.version);
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
8
15
|
var command = args[0];
|
|
9
16
|
function getOpt(name, def = "") {
|
|
10
17
|
const idx = args.indexOf(`--${name}`);
|
|
@@ -88,7 +95,7 @@ Options:
|
|
|
88
95
|
}
|
|
89
96
|
case "admin": {
|
|
90
97
|
const port = Number(getOpt("port", "3456"));
|
|
91
|
-
const { startAdmin } = await import("./server-
|
|
98
|
+
const { startAdmin } = await import("./server-2WJM3QBQ.js");
|
|
92
99
|
await startAdmin(config, port);
|
|
93
100
|
break;
|
|
94
101
|
}
|
|
@@ -189,7 +189,6 @@ var JobManager = class {
|
|
|
189
189
|
};
|
|
190
190
|
this.jobs.set(id, job);
|
|
191
191
|
const args = [
|
|
192
|
-
CLI_BIN,
|
|
193
192
|
"translate",
|
|
194
193
|
"--lang",
|
|
195
194
|
opts.lang,
|
|
@@ -203,7 +202,7 @@ var JobManager = class {
|
|
|
203
202
|
if (opts.project) args.push("--project", opts.project);
|
|
204
203
|
if (opts.model) args.push("--model", opts.model);
|
|
205
204
|
if (opts.files?.length) args.push("--files", opts.files.join(","));
|
|
206
|
-
const proc = spawn(
|
|
205
|
+
const proc = spawn(CLI_BIN, args, {
|
|
207
206
|
cwd: PROJECT_ROOT,
|
|
208
207
|
stdio: ["ignore", "pipe", "pipe"],
|
|
209
208
|
env: { ...process.env, NO_TTY: "1", FORCE_COLOR: "0" }
|
package/package.json
CHANGED
|
@@ -67,7 +67,6 @@ export class JobManager {
|
|
|
67
67
|
this.jobs.set(id, job);
|
|
68
68
|
|
|
69
69
|
const args = [
|
|
70
|
-
CLI_BIN,
|
|
71
70
|
'translate',
|
|
72
71
|
'--lang', opts.lang,
|
|
73
72
|
'--version', opts.version,
|
|
@@ -79,7 +78,7 @@ export class JobManager {
|
|
|
79
78
|
if (opts.model) args.push('--model', opts.model);
|
|
80
79
|
if (opts.files?.length) args.push('--files', opts.files.join(','));
|
|
81
80
|
|
|
82
|
-
const proc = spawn(
|
|
81
|
+
const proc = spawn(CLI_BIN, args, {
|
|
83
82
|
cwd: PROJECT_ROOT,
|
|
84
83
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
85
84
|
env: { ...process.env, NO_TTY: '1', FORCE_COLOR: '0' },
|