@geolonia/yuuhitsu 0.2.4 → 0.3.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.
- package/README.ja.md +383 -0
- package/README.md +141 -63
- package/dist/cli/commands/translate.d.ts.map +1 -1
- package/dist/cli/commands/translate.js +6 -3
- package/dist/cli/commands/translate.js.map +1 -1
- package/dist/tasks/batch-translate.d.ts +2 -1
- package/dist/tasks/batch-translate.d.ts.map +1 -1
- package/dist/tasks/batch-translate.js +3 -2
- package/dist/tasks/batch-translate.js.map +1 -1
- package/dist/tasks/translate.d.ts +4 -2
- package/dist/tasks/translate.d.ts.map +1 -1
- package/dist/tasks/translate.js +159 -54
- package/dist/tasks/translate.js.map +1 -1
- package/package.json +5 -2
package/README.ja.md
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# yuuhitsu (右筆)
|
|
2
|
+
|
|
3
|
+
AI を活用したドキュメント操作 CLI
|
|
4
|
+
|
|
5
|
+
## 概要
|
|
6
|
+
|
|
7
|
+
**yuuhitsu**(右筆、封建時代の日本で「秘書」や「書記」を意味する)は、AI を使用してドキュメント操作を自動化するコマンドラインツールです。この名前は、封建領主に仕え、公式文書の執筆・管理を代行した書記に由来しています — このツールはエンジニアに対して同様の役割を果たし、翻訳、ドキュメント生成、ドキュメント同期を担います。
|
|
8
|
+
|
|
9
|
+
### 主な機能
|
|
10
|
+
|
|
11
|
+
* **Markdown 翻訳**:構造、コードブロック、フォーマットを保持しながらドキュメントを翻訳
|
|
12
|
+
* **用語集管理**:プロジェクトレベルの用語集により、すべての翻訳で一貫した用語を維持
|
|
13
|
+
* **マルチプロバイダー対応**:設定ファイルの 1 行を変更するだけで、Claude(Anthropic)、Gemini(Google)、Ollama(ローカル)を切り替え可能
|
|
14
|
+
* **ローカル品質管理**:構文チェック、意味チェック、LLM ジャッジチェックによる公開前の自動 QC
|
|
15
|
+
* **ドライランモード**:API 呼び出しを行わずに操作のプレビューが可能
|
|
16
|
+
|
|
17
|
+
## 機能
|
|
18
|
+
|
|
19
|
+
### 翻訳
|
|
20
|
+
|
|
21
|
+
yuuhitsu は AST(remark)パイプラインを使用して、段落レベルで Markdown ドキュメントを翻訳します:
|
|
22
|
+
|
|
23
|
+
1. **解析** — remark が Markdown を mdast AST に解析します
|
|
24
|
+
2. **抽出** — `extractBlockNodes()` が段落全体と見出しノードを Markdown 単位として収集し、各ブロック内のインライン要素(コードスパン、太字、斜体、リンク)を保持します
|
|
25
|
+
3. **バッチ処理** — ノードは推定トークン数に基づいて API バッチにグループ化されます(`--max-tokens-per-batch`、デフォルト:4000 文字 ÷ 4)
|
|
26
|
+
4. **翻訳** — Claude の構造化出力(tool\_use)は 1:1 の ID マッピングが保証された JSON レスポンスを返します;Gemini と Ollama はテキストモードの JSON を使用します
|
|
27
|
+
5. **適用** — 翻訳されたテキストは remark を通じて再解析され、AST に書き戻されます;その後、ドキュメント全体がシリアライズされます
|
|
28
|
+
|
|
29
|
+
**なぜ段落レベルのチャンクなのか?**
|
|
30
|
+
|
|
31
|
+
以前のリリース(0.1.x)ではテキストをインライン要素の境界で分割していました — たとえば、`"When \`AUTH\_ENABLED=true\`, a token is required."`を`"When "`と`", a token is required."`に分割するなどです。LLM は各フラグメントのコンテキストを持たず、英語と日本語の混在、フレーズの重複、意味の逆転などの問題が生じました。段落レベルのチャンク処理(0.3.0)により、このクラスのエラーが解消されます。
|
|
32
|
+
|
|
33
|
+
**保持されるもの(LLM に送信されないもの):**
|
|
34
|
+
|
|
35
|
+
* フェンスコードブロック(` ``` `...` ``` `):AST によってそのまま保持
|
|
36
|
+
* インラインコード(`` `...` ``):各段落ブロック内で保持
|
|
37
|
+
* ドキュメント構造(見出し、リスト、テーブル、HR、リンク):AST のラウンドトリップによって確定的に処理
|
|
38
|
+
|
|
39
|
+
### 用語集の管理
|
|
40
|
+
|
|
41
|
+
プロジェクトレベルの用語集を管理して、すべての翻訳にわたって一貫した用語を徹底します。
|
|
42
|
+
|
|
43
|
+
* **`glossary init`**:サンプル用語を含む `glossary.yaml` のスケルトンを生成します
|
|
44
|
+
* **`glossary check`**:ドキュメント内の禁止用語や不整合な用語を検出します — Markdown(`.md`)と JSON i18n ファイル(`.json`)をサポート;違反は行番号またはキーパスとともに報告されます
|
|
45
|
+
* **`glossary fix`**:ドキュメント内の `severity: auto-fix` 用語を自動置換します
|
|
46
|
+
* **`glossary sync`**:設定されたすべての言語における翻訳カバレッジをレポートし、欠落エントリのスタブを作成します
|
|
47
|
+
* **`glossary review`**:すべての用語集の用語とその翻訳の Markdown レポートを生成します
|
|
48
|
+
|
|
49
|
+
`yuuhitsu.config.yaml` に `glossary` のパスが設定されている場合、`translate` コマンドは自動的に用語集を AI プロンプトに注入し、正規の用語が使用され、禁止されたバリアントが回避されることを保証します。
|
|
50
|
+
|
|
51
|
+
**重大度レベル**(`glossary.yaml` で用語ごとに設定):
|
|
52
|
+
|
|
53
|
+
| Level | Behaviour |
|
|
54
|
+
| ---------- | ------------------------------------------ |
|
|
55
|
+
| `block` | Hard error — CI fails |
|
|
56
|
+
| `warn` | Warning — CI passes, human review required |
|
|
57
|
+
| `auto-fix` | Automatically replaced by `glossary fix` |
|
|
58
|
+
|
|
59
|
+
### ローカル品質管理
|
|
60
|
+
|
|
61
|
+
yuuhitsu には公開前 QC スクリプト(`scripts/local-qc.ts`)が同梱されており、`npm publish` のたびに実際の翻訳済みフィクスチャリポジトリに対して実行されます。これにより、ユニットテストでは検出できない構文のリグレッションとセマンティックな品質低下の両方を捕捉します。
|
|
62
|
+
|
|
63
|
+
**構文チェック:**
|
|
64
|
+
|
|
65
|
+
| Check | Description |
|
|
66
|
+
| --------------- | ------------------------------------------------------------------------------------ |
|
|
67
|
+
| bare-fence | Fenced code blocks without a language tag |
|
|
68
|
+
| five-axis | EN/JA mix, duplicate phrase, heading integrity, anchor validity across fixture files |
|
|
69
|
+
| markdownlint | Common Markdown lint rules |
|
|
70
|
+
| vitepress-build | VitePress build succeeds on the fixture repo |
|
|
71
|
+
|
|
72
|
+
**セマンティックチェック:**
|
|
73
|
+
|
|
74
|
+
| Check | Description |
|
|
75
|
+
| ----------------- | ----------------------------------------------------- |
|
|
76
|
+
| en-ja-mix | Paragraphs that mix English and Japanese unexpectedly |
|
|
77
|
+
| duplicate-phrase | Same phrase repeated twice within one paragraph |
|
|
78
|
+
| heading-integrity | Headings match between EN and JA versions |
|
|
79
|
+
| anchor-validity | Internal anchor links resolve correctly |
|
|
80
|
+
|
|
81
|
+
**LLM ジャッジ:**
|
|
82
|
+
|
|
83
|
+
* モデル:`claude-sonnet-4-6`
|
|
84
|
+
* 閾値:フィクスチャごとの平均スコア ≥ 4.0、フィクスチャごとの最低スコア ≥ 3.5(スケール 1〜5)
|
|
85
|
+
* `LOCAL_QC_FIXTURE_REPO` 内のデフォルトフィクスチャファイル全 7 件をカバー
|
|
86
|
+
|
|
87
|
+
**設定:**
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Point to your translated fixture repository
|
|
91
|
+
export LOCAL_QC_FIXTURE_REPO=/home/user/workspace/my-docs # default: /home/hal/workspace/geonicdb-docs
|
|
92
|
+
|
|
93
|
+
# Run QC manually
|
|
94
|
+
npm run local-qc
|
|
95
|
+
|
|
96
|
+
# QC runs automatically before publish
|
|
97
|
+
npm publish # triggers prepublishOnly → local-qc.ts
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
QC スクリプトはすべてのプルリクエストに対して `.github/workflows/local-qc.yml` 経由で GitHub Actions CI でも実行されます。
|
|
101
|
+
|
|
102
|
+
## クイックスタート
|
|
103
|
+
|
|
104
|
+
### インストール
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm install -g @geolonia/yuuhitsu
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 基本的な使い方
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Translate a document to Japanese
|
|
114
|
+
yuuhitsu translate --input README.md --lang ja
|
|
115
|
+
|
|
116
|
+
# Translate to English
|
|
117
|
+
yuuhitsu translate --input docs.md --lang en --output docs.en.md
|
|
118
|
+
|
|
119
|
+
# Preview without API calls
|
|
120
|
+
yuuhitsu translate --input README.md --lang ja --dry-run
|
|
121
|
+
|
|
122
|
+
# Use a specific config file
|
|
123
|
+
yuuhitsu translate --input README.md --lang ja --config ./custom.config.yaml
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 設定
|
|
127
|
+
|
|
128
|
+
プロジェクトのルートに `yuuhitsu.config.yaml` ファイルを作成します:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
# AI Provider Selection
|
|
132
|
+
provider: claude # Options: claude, gemini, ollama
|
|
133
|
+
model: claude-sonnet-4-6
|
|
134
|
+
|
|
135
|
+
# Optional Settings
|
|
136
|
+
outputDir: ./translated
|
|
137
|
+
templates: ./templates
|
|
138
|
+
glossary: ./glossary.yaml # Path to glossary file (enables auto-injection during translation)
|
|
139
|
+
log:
|
|
140
|
+
enabled: true
|
|
141
|
+
path: ./yuuhitsu.log
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 環境変数
|
|
145
|
+
|
|
146
|
+
API 認証用の `.env` ファイルを作成するか、環境変数を設定します:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# For Claude (Anthropic) — recommended
|
|
150
|
+
ANTHROPIC_API_KEY=your_api_key_here
|
|
151
|
+
|
|
152
|
+
# For Gemini (Google)
|
|
153
|
+
GOOGLE_API_KEY=your_api_key_here
|
|
154
|
+
|
|
155
|
+
# Ollama requires no API key (runs locally)
|
|
156
|
+
|
|
157
|
+
# For Local QC
|
|
158
|
+
LOCAL_QC_FIXTURE_REPO=/path/to/your/translated-docs-repo
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### サポートされているプロバイダー
|
|
162
|
+
|
|
163
|
+
| Provider | SDK | Environment Variable | Use Case |
|
|
164
|
+
| -------- | --------------------- | -------------------- | ------------------------------------------- |
|
|
165
|
+
| Claude | `@anthropic-ai/sdk` | `ANTHROPIC_API_KEY` | High-quality translation, structured output |
|
|
166
|
+
| Gemini | `@google/genai` | `GOOGLE_API_KEY` | Fast processing, cost-effective |
|
|
167
|
+
| Ollama | `openai` (compatible) | *(none)* | Local execution, privacy, offline use |
|
|
168
|
+
|
|
169
|
+
## コマンド
|
|
170
|
+
|
|
171
|
+
### `translate`
|
|
172
|
+
|
|
173
|
+
Markdown ドキュメントを言語間で翻訳します。
|
|
174
|
+
|
|
175
|
+
**グローバルオプション**(サブコマンドの前):
|
|
176
|
+
|
|
177
|
+
* `--config <path>`:設定ファイルのパス(デフォルト:`./yuuhitsu.config.yaml`)
|
|
178
|
+
* `--dry-run`:API 呼び出しを行わずに実行内容を表示します
|
|
179
|
+
* `--verbose`:詳細な出力を有効にします
|
|
180
|
+
|
|
181
|
+
**オプション:**
|
|
182
|
+
|
|
183
|
+
* `--input <path>`(必須):入力 Markdown ファイルのパスまたは glob パターン(例:`docs/en/**/*.md`)
|
|
184
|
+
* `--output <path>`:出力ファイルのパス(デフォルト:`<input>.<lang>.md`)
|
|
185
|
+
* `--output-dir <dir>`:バッチ翻訳の出力ディレクトリ(ディレクトリ構造を保持します)
|
|
186
|
+
* `--lang <code>`(必須):ターゲット言語コード(例:`en`、`ja`、`zh`、`es`)
|
|
187
|
+
* `--max-tokens-per-batch <N>`:API バッチ呼び出しごとの推定最大トークン数(デフォルト:`4000`)。見出しが少ない大きなドキュメントの場合は増やし、API のコンテキスト制限に達した場合は減らしてください。
|
|
188
|
+
* `--max-chunk-lines <N>`:翻訳チャンクごとの最大行数(レガシーフォールバック;デフォルト:`150`)。AST パスがバイパスされた場合にのみ使用されます。
|
|
189
|
+
|
|
190
|
+
**単一ファイルの例:**
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
yuuhitsu translate \
|
|
194
|
+
--input ./docs/guide.md \
|
|
195
|
+
--output ./docs/guide.ja.md \
|
|
196
|
+
--lang ja \
|
|
197
|
+
--max-tokens-per-batch 4000
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**バッチ翻訳の例:**
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
yuuhitsu translate \
|
|
204
|
+
--input "docs/en/**/*.md" \
|
|
205
|
+
--output-dir docs/ja \
|
|
206
|
+
--lang ja
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### `glossary`
|
|
210
|
+
|
|
211
|
+
用語の一貫性を保つためにプロジェクトの用語集を管理します。
|
|
212
|
+
|
|
213
|
+
#### `glossary init`
|
|
214
|
+
|
|
215
|
+
現在のディレクトリに `glossary.yaml` のスケルトンを生成します。
|
|
216
|
+
|
|
217
|
+
**オプション:**
|
|
218
|
+
|
|
219
|
+
* `--output <path>`:用語集ファイルの出力パス(デフォルト:`glossary.yaml`)
|
|
220
|
+
* `--force`:既存の用語集ファイルを上書きする
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
yuuhitsu glossary init
|
|
224
|
+
yuuhitsu glossary init --output ./docs/glossary.yaml
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### `glossary check`
|
|
228
|
+
|
|
229
|
+
ドキュメント内の禁止用語や不統一な用語を検出します。
|
|
230
|
+
|
|
231
|
+
Markdown(`.md`)と JSON i18n ファイル(`.json`)の両方をサポートします。`.json` ファイルを指定した場合、違反はキーパス(例:`dashboard.title`)として報告されます。
|
|
232
|
+
|
|
233
|
+
**スキップされる箇所(チェック対象外):**
|
|
234
|
+
|
|
235
|
+
* フェンスコードブロック(` ``` `...` ``` `)
|
|
236
|
+
* インラインコード(`` `...` ``)
|
|
237
|
+
* URL(`http://` / `https://`)
|
|
238
|
+
* フロントマター(`---`...`---`)
|
|
239
|
+
* Markdown リンクの URL パス部分
|
|
240
|
+
|
|
241
|
+
**オプション:**
|
|
242
|
+
|
|
243
|
+
* `--input <file>`(必須):チェック対象のドキュメントファイル(Markdown または JSON i18n ファイル)
|
|
244
|
+
* `--glossary <path>`(必須):用語集ファイルのパス
|
|
245
|
+
* `--lang <code>`(必須):チェックする言語コード(例:`ja`、`en`)
|
|
246
|
+
* `--severity-filter <levels>`:報告する重要度レベルをカンマ区切りで指定(例:`block,warn`)。デフォルト:全レベル。
|
|
247
|
+
* `--format <format>`:出力形式:`text`、`json`、`sarif`(デフォルト:`text`)
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Check a Markdown document
|
|
251
|
+
yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja
|
|
252
|
+
|
|
253
|
+
# Check only block-level violations
|
|
254
|
+
yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja --severity-filter block
|
|
255
|
+
|
|
256
|
+
# Output SARIF for GitHub Code Scanning
|
|
257
|
+
yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja --format sarif
|
|
258
|
+
|
|
259
|
+
# Check a JSON i18n file
|
|
260
|
+
yuuhitsu glossary check --input locales/ja/common.json --glossary glossary.yaml --lang ja
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### `glossary fix`
|
|
264
|
+
|
|
265
|
+
ドキュメント内の `severity: auto-fix` 用語を自動置換します。
|
|
266
|
+
|
|
267
|
+
**オプション:**
|
|
268
|
+
|
|
269
|
+
* `--input <file>`(必須):修正対象のドキュメントファイル
|
|
270
|
+
* `--glossary <path>`(必須):用語集ファイルのパス
|
|
271
|
+
* `--lang <code>`(必須):言語コード
|
|
272
|
+
* `--dry-run`:ファイルを変更せずに置換内容をプレビュー表示する
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
yuuhitsu glossary fix --input README.md --glossary glossary.yaml --lang ja
|
|
276
|
+
yuuhitsu glossary fix --input README.md --glossary glossary.yaml --lang ja --dry-run
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### `glossary sync`
|
|
280
|
+
|
|
281
|
+
翻訳カバレッジを報告し、不足しているエントリのスタブを作成します。
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
yuuhitsu glossary sync --glossary glossary.yaml
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
#### `glossary review`
|
|
288
|
+
|
|
289
|
+
すべての用語集の用語とその翻訳を Markdown レポートとして生成します。
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
yuuhitsu glossary review --glossary glossary.yaml
|
|
293
|
+
yuuhitsu glossary review --glossary glossary.yaml --output glossary-report.md
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 用語集ファイルのフォーマット
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
version: 1
|
|
300
|
+
languages: [ja, en]
|
|
301
|
+
terms:
|
|
302
|
+
- canonical: "API"
|
|
303
|
+
type: noun
|
|
304
|
+
translations:
|
|
305
|
+
ja: "API"
|
|
306
|
+
en: "API"
|
|
307
|
+
do_not_use:
|
|
308
|
+
ja: ["API", "えーぴーあい"]
|
|
309
|
+
- canonical: "webhook"
|
|
310
|
+
type: noun
|
|
311
|
+
severity: warn # block | warn | auto-fix (default: block)
|
|
312
|
+
translations:
|
|
313
|
+
ja: "Webhook"
|
|
314
|
+
en: "webhook"
|
|
315
|
+
do_not_use:
|
|
316
|
+
ja: ["ウェブフック"]
|
|
317
|
+
en: ["web hook"]
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
| Field | Description |
|
|
321
|
+
| ---------------------- | ------------------------------------------------- |
|
|
322
|
+
| `version` | Schema version (currently `1`) |
|
|
323
|
+
| `languages` | List of language codes managed by this glossary |
|
|
324
|
+
| `terms[].canonical` | The authoritative (source-language) term |
|
|
325
|
+
| `terms[].type` | Term type (e.g., `noun`, `verb`) |
|
|
326
|
+
| `terms[].severity` | `block` (default), `warn`, or `auto-fix` |
|
|
327
|
+
| `terms[].translations` | Map of language code → translated term |
|
|
328
|
+
| `terms[].do_not_use` | Map of language code → list of forbidden variants |
|
|
329
|
+
|
|
330
|
+
## 開発
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Clone the repository
|
|
334
|
+
git clone https://github.com/geolonia/yuuhitsu.git
|
|
335
|
+
cd yuuhitsu
|
|
336
|
+
|
|
337
|
+
# Install dependencies
|
|
338
|
+
npm install
|
|
339
|
+
|
|
340
|
+
# Run tests
|
|
341
|
+
npm test
|
|
342
|
+
|
|
343
|
+
# Build the project
|
|
344
|
+
npm run build
|
|
345
|
+
|
|
346
|
+
# Run locally (development)
|
|
347
|
+
npm run dev -- translate --input test.md --lang ja
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### テストの実行
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
# Run all unit tests
|
|
354
|
+
npm test
|
|
355
|
+
|
|
356
|
+
# Watch mode
|
|
357
|
+
npm run test:watch
|
|
358
|
+
|
|
359
|
+
# Integration tests (requires ANTHROPIC_API_KEY)
|
|
360
|
+
npm run test:integration
|
|
361
|
+
|
|
362
|
+
# Type checking
|
|
363
|
+
npm run lint
|
|
364
|
+
|
|
365
|
+
# Local QC (requires LOCAL_QC_FIXTURE_REPO)
|
|
366
|
+
npm run local-qc
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## 変更履歴
|
|
370
|
+
|
|
371
|
+
完全なバージョン履歴については [CHANGELOG.md](./CHANGELOG.md) を参照してください。
|
|
372
|
+
|
|
373
|
+
**0.3.0 のハイライト:**
|
|
374
|
+
|
|
375
|
+
* 段落レベルのチャンク再設計(`extractBlockNodes`) — インライン要素の分割による EN/JA の混在、重複フレーズ、意味の逆転を排除
|
|
376
|
+
* トークン数ベースのバッチ処理(`--max-tokens-per-batch`、デフォルト: 4000) — 行数ベースの `--max-nodes-per-batch` を置き換え
|
|
377
|
+
* ローカル QC(`scripts/local-qc.ts`) — prepublishOnly フック + LLM ジャッジ(`claude-sonnet-4-6`、平均 ≥ 4.0)を使用した GitHub Actions CI
|
|
378
|
+
|
|
379
|
+
## ライセンス
|
|
380
|
+
|
|
381
|
+
MIT — [LICENSE](./LICENSE) を参照
|
|
382
|
+
|
|
383
|
+
Copyright (c) 2026 Geolonia Inc.
|