Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 114b7e3

Browse files
committed
add workflow
1 parent 4e8c85b commit 114b7e3

File tree

4 files changed

+640
-95
lines changed

4 files changed

+640
-95
lines changed

CLAUDE.md

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,69 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
5353

5454
`library/asyncio.po` を翻訳してください」という指示があった場合、以下の手順で作業を進めます。
5555

56-
1. `read_file` ツールで `library/asyncio.po` の内容を読み込みます。
57-
2. 未翻訳の箇所 (`msgstr ""`) を見つけます。
58-
3. reStructuredTextの構文に注意しながら、対応する `msgid` を翻訳し、`msgstr` に記述します。
59-
4. 既存の翻訳もレビューし、必要に応じて修正案を考えます。
60-
5. `replace` または `write_file` ツールを使い、変更を適用します。
56+
**重要**: 翻訳作業は必ず `translate_workflow.py` スクリプトを使用して実行してください。
6157

62-
#### 4.1 ファイルの分割
58+
1. **翻訳ワークフロー開始**:
59+
```bash
60+
python3 translate_workflow.py library/asyncio.po
61+
```
6362

64-
.poファイルのサイズが20kbを超える場合は、すべてをまとめて処理せず、splitpoコマンドでpoファイルを30エントリずつに分割して、それぞれを翻訳します。
63+
2. **作業の自動判定**:
64+
- スクリプトが既存の作業状況を自動チェック
65+
- 未着手の場合: 自動的にファイル分割(20KB超の場合)
66+
- 作業中の場合: 次に翻訳すべきファイルを表示
67+
- 完了済みの場合: 自動的にファイル結合と最終チェック
6568

69+
3. **翻訳作業の実行**:
70+
- 表示された分割ファイルを順次翻訳
71+
- 各ファイル完了後、`.splitted_done/` ディレクトリに移動
72+
- 翻訳完了後、再度スクリプトを実行して次のファイルへ
6673

74+
4. **完了確認**:
75+
- 全ファイル翻訳完了後、自動的に結合処理
76+
- 最終的な翻訳漏れチェックを実行
77+
- 元のファイルが更新されて翻訳が完了
78+
- 一時ファイル(`.splitted/`, `.splitted_done/`)は自動削除
79+
80+
#### 4.0 翻訳ワークフローシステム
81+
82+
翻訳作業は中断・再開が可能な専用システムで管理されます。
83+
84+
**ディレクトリ構造**:
85+
```
86+
.splitted/ # 分割ファイル格納
87+
└── [ファイル名]/ # ファイル固有ディレクトリ
88+
.splitted_done/ # 翻訳完了ファイル格納
89+
└── [ファイル名]/ # ファイル固有ディレクトリ
90+
```
91+
92+
**基本コマンド**:
93+
```bash
94+
# 翻訳開始/再開
95+
python3 translate_workflow.py [ファイル名].po
96+
97+
# 状況確認
98+
python3 translate_workflow.py --status [ファイル名].po
99+
100+
# 完了ファイル結合
101+
python3 translate_workflow.py --join [ファイル名].po
102+
```
103+
104+
**作業フロー**:
105+
1. 20KB以下のファイル: 直接翻訳
106+
2. 20KB超のファイル: 30エントリずつ自動分割
107+
3. 各分割ファイルの翻訳完了後、`.splitted_done/` に移動
108+
4. 全分割ファイル完了後、自動結合と最終チェック
109+
110+
このシステムにより、作業の中断・再開が確実に行え、翻訳漏れを防止できます。
111+
112+
#### 4.1 ファイルの分割(自動化済み)
113+
114+
**注意**: 以下の手動分割手順は `translate_workflow.py` により自動化されています。直接実行する必要はありません。
115+
116+
.poファイルのサイズが20kbを超える場合は、translate_workflow.pyが自動的にsplitpoコマンドでpoファイルを30エントリずつに分割して、それぞれを翻訳します。
117+
118+
**手動実行時の参考コマンド**:
67119
```
68120
splitpo -h
69121
usage: splitpo [-h] [-o OUTPUT_DIR] [-e ENTRIES] input_file
@@ -79,24 +131,18 @@ options:
79131
Output directory for split files
80132
-e, --entries ENTRIES
81133
Number of entries per split file (default: 100)
82-
83134
```
84135

85-
実行例:
86-
87-
`splitpo -o /tmp/split_pathlib -e 30 library/pathlib.po`
136+
**自動実行例**:
137+
`translate_workflow.py` が実行: `splitpo -o .splitted/pathlib -e 30 library/pathlib.po`
88138

89-
このコマンドは、poファイルを30エントリごとに分割します。
90-
91-
Split files are named with the pattern `{original_name}_part_{number}.po`:
139+
**分割ファイル命名規則**:
92140
- `input.po``input_part_000.po`, `input_part_001.po`, etc.
93141
- Number of digits adjusts to file count (minimum 3 digits)
94142
- Numbering starts from 0
95143

96-
ファイル名をそのままソートすれば、元ファイルと同じ順番で並ぶようになっていますので、この順序で翻訳を進めてください。
97-
98-
それぞれのファイルの翻訳が終了したら、joinpoコマンドで分割したファイルを結合します。
99-
144+
**結合処理**:
145+
翻訳完了後、`translate_workflow.py` が自動的にjoinpoコマンドで分割したファイルを結合します。
100146

101147
```
102148
joinpo -h
@@ -112,9 +158,11 @@ options:
112158
-o, --output OUTPUT Output .po file
113159
```
114160

115-
実行例:
116-
117-
`joinpo -o translated_pathlib.po /tmp/split_pathlib/*.po -o`
161+
**自動実行例**:
162+
`translate_workflow.py` が実行:
163+
1. `joinpo -o translated_pathlib.po .splitted_done/pathlib/*.po`
164+
2. 元のファイルを翻訳済みファイルで更新
165+
3. 一時ファイルとディレクトリを削除
118166

119167

120168

@@ -149,13 +197,13 @@ options:
149197
2. 既存翻訳の品質が改善されている
150198
3. コード例等の翻訳不要な部分は適切に `msgstr ""` のまま残されている
151199

152-
### 4.3 翻訳作業完了前の必須チェック手順(最終確認
200+
### 4.3 翻訳作業完了前の必須チェック手順(自動化済み
153201

154-
**重要**: 翻訳作業の最後には、**必ず**以下の手順を実行して未翻訳部分が残っていないか確認してください。この手順は翻訳作業の品質を保証するために必須です
202+
**重要**: 以下の最終チェック手順は `translate_workflow.py` により自動化されています。翻訳完了時に自動実行されますが、必要に応じて手動でも実行できます
155203

156-
#### 最終チェックスクリプトの実行
204+
#### 最終チェックスクリプトの実行(自動化済み)
157205

158-
翻訳対象ファイルに対して以下のPythonスクリプトを実行し、未翻訳のテキストエントリが残っていないか確認します:
206+
`translate_workflow.py` が翻訳完了時に自動実行するチェックスクリプトです。手動実行時は以下のPythonスクリプトを実行し、未翻訳のテキストエントリが残っていないか確認します:
159207

160208
```python
161209
python3 -c "
@@ -241,11 +289,13 @@ else:
241289

242290
**注意**: この最終チェックを省略してはいけません。翻訳作業の品質保証において必須の手順です。
243291

244-
### 4.4 翻訳漏れ防止のための必須手順
292+
### 4.4 翻訳漏れ防止のための必須手順(自動化済み)
293+
294+
**重要**: 以下の翻訳漏れ防止手順は `translate_workflow.py` により自動化されています。手動実行時の参考として記載しています。
245295

246-
翻訳漏れを完全に防ぐため、以下の手順を**必ず**実行してください:
296+
#### 翻訳作業開始前の事前確認(自動化済み)
247297

248-
#### 翻訳作業開始前の事前確認
298+
`translate_workflow.py` が自動実行する確認項目:
249299

250300
1. **重複エントリの検出**:
251301
```bash
@@ -267,16 +317,18 @@ print(f'翻訳前未翻訳エントリ数: {len(re.findall(r\"msgstr \\\"\\\"\",
267317
#### 翻訳作業中の段階的確認
268318

269319
3. **定期的な進捗確認**:
270-
- 50エントリごとに翻訳状況をチェック
320+
- `translate_workflow.py` が進捗状況を自動表示
271321
- 重複エントリを発見した場合は**すべて**翻訳する
272322

273323
4. **分割ファイル処理時の特別措置**:
274-
- 各分割ファイルの翻訳完了後、即座に未翻訳エントリ数をチェック
275-
- 結合前に各分割ファイルの翻訳完了を確認
324+
- 各分割ファイルの翻訳完了後、`.splitted_done/` ディレクトリに自動移動
325+
- 結合前に各分割ファイルの翻訳完了を自動確認
276326

277-
#### 翻訳作業完了前の厳格な最終チェック
327+
#### 翻訳作業完了前の厳格な最終チェック(自動化済み)
278328

279329
5. **最終チェックスクリプト(改良版)**:
330+
`translate_workflow.py` が自動実行するチェックスクリプト:
331+
280332
```python
281333
python3 -c "
282334
import re
@@ -307,8 +359,8 @@ else:
307359
#### 品質保証のための二重チェック
308360

309361
6. **翻訳完了後の検証**:
310-
- 翻訳前後の未翻訳エントリ数の差分を確認
311-
- 重複エントリがすべて翻訳されていることを確認
362+
- `translate_workflow.py` が翻訳前後の未翻訳エントリ数の差分を自動確認
363+
- 重複エントリがすべて翻訳されていることを自動確認
312364
- 既存翻訳の品質向上も完了していることを確認
313365

314366
#### 緊急時の対応
@@ -318,7 +370,7 @@ else:
318370
- 同じ`msgid`の他のエントリも確認
319371
- 翻訳完了まで作業を継続
320372

321-
**重要**: この手順を省略することは品質保証上許可されません。すべての翻訳対象エントリが完了するまで作業を継続してください
373+
**重要**: `translate_workflow.py` を使用することで、これらの手順が自動化され、翻訳品質が保証されます
322374

323375
## Repository Structure
324376

check_translation_progress.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env python3
2+
"""
3+
翻訳進捗チェックツール
4+
分割された翻訳ファイルの進捗を確認し、作業再開をサポートします。
5+
"""
6+
7+
import os
8+
import sys
9+
import re
10+
from pathlib import Path
11+
from typing import Dict, List, Tuple, Optional
12+
13+
14+
def get_split_info(po_file: str) -> Tuple[str, str, str]:
15+
"""
16+
ファイルパスから分割作業用のディレクトリパスを取得
17+
Returns: (base_name, splitted_dir, done_dir)
18+
"""
19+
po_path = Path(po_file)
20+
base_name = po_path.stem
21+
22+
# ファイル固有のディレクトリを作成
23+
splitted_dir = Path(".splitted") / base_name
24+
done_dir = Path(".splitted_done") / base_name
25+
26+
return base_name, splitted_dir, done_dir
27+
28+
29+
def check_split_files(splitted_dir: Path) -> List[Path]:
30+
"""分割ファイルの一覧を取得"""
31+
if not splitted_dir.exists():
32+
return []
33+
34+
split_files = list(splitted_dir.glob("*_part_*.po"))
35+
return sorted(split_files)
36+
37+
38+
def check_done_files(done_dir: Path) -> List[Path]:
39+
"""完了ファイルの一覧を取得"""
40+
if not done_dir.exists():
41+
return []
42+
43+
done_files = list(done_dir.glob("*_part_*.po"))
44+
return sorted(done_files)
45+
46+
47+
def get_untranslated_count(po_file: Path) -> int:
48+
"""POファイルの未翻訳エントリ数を取得"""
49+
try:
50+
with open(po_file, 'r', encoding='utf-8') as f:
51+
content = f.read()
52+
53+
# 未翻訳エントリを検出
54+
all_entries = re.findall(r'(#: [^\n]+\nmsgid[^m]+?msgstr "")', content, re.DOTALL)
55+
untranslated_text = []
56+
57+
for entry in all_entries:
58+
# コードサンプルを除外
59+
if not any(marker in entry for marker in ['def ', 'class ', 'assert ', 'print(', 'return ', '>>>', 'import ', 'raise ']):
60+
untranslated_text.append(entry)
61+
62+
return len(untranslated_text)
63+
except Exception:
64+
return -1
65+
66+
67+
def analyze_progress(po_file: str) -> Dict:
68+
"""翻訳進捗を分析"""
69+
base_name, splitted_dir, done_dir = get_split_info(po_file)
70+
71+
# 元ファイルの存在確認
72+
original_exists = os.path.exists(po_file)
73+
74+
# 分割ファイルの確認
75+
split_files = check_split_files(splitted_dir)
76+
done_files = check_done_files(done_dir)
77+
78+
# 各ファイルの未翻訳エントリ数を取得
79+
split_status = {}
80+
for split_file in split_files:
81+
untranslated = get_untranslated_count(split_file)
82+
split_status[split_file.name] = {
83+
'path': split_file,
84+
'untranslated': untranslated,
85+
'completed': untranslated == 0
86+
}
87+
88+
done_status = {}
89+
for done_file in done_files:
90+
untranslated = get_untranslated_count(done_file)
91+
done_status[done_file.name] = {
92+
'path': done_file,
93+
'untranslated': untranslated,
94+
'completed': untranslated == 0
95+
}
96+
97+
return {
98+
'base_name': base_name,
99+
'original_file': po_file,
100+
'original_exists': original_exists,
101+
'splitted_dir': splitted_dir,
102+
'done_dir': done_dir,
103+
'split_files': split_files,
104+
'done_files': done_files,
105+
'split_status': split_status,
106+
'done_status': done_status,
107+
'has_work_in_progress': len(split_files) > 0 or len(done_files) > 0
108+
}
109+
110+
111+
def print_progress_report(progress: Dict):
112+
"""進捗レポートを表示"""
113+
print(f"=== 翻訳進捗レポート: {progress['base_name']} ===")
114+
print(f"元ファイル: {progress['original_file']} ({'存在' if progress['original_exists'] else '不存在'})")
115+
print(f"分割作業ディレクトリ: {progress['splitted_dir']}")
116+
print(f"完了ディレクトリ: {progress['done_dir']}")
117+
118+
if not progress['has_work_in_progress']:
119+
print("✅ 作業中のファイルはありません")
120+
return
121+
122+
print("\n--- 作業中ファイル ---")
123+
for filename, status in progress['split_status'].items():
124+
status_mark = "✅" if status['completed'] else "🔄"
125+
print(f"{status_mark} {filename}: 未翻訳{status['untranslated']}件")
126+
127+
print("\n--- 完了ファイル ---")
128+
for filename, status in progress['done_status'].items():
129+
status_mark = "✅" if status['completed'] else "⚠️"
130+
print(f"{status_mark} {filename}: 未翻訳{status['untranslated']}件")
131+
132+
# 次の作業提案
133+
incomplete_splits = [f for f, s in progress['split_status'].items() if not s['completed']]
134+
if incomplete_splits:
135+
print(f"\n📋 次の作業: {incomplete_splits[0]} の翻訳を継続")
136+
else:
137+
print("\n📋 次の作業: 完了ファイルの結合")
138+
139+
140+
def get_next_action(progress: Dict) -> str:
141+
"""次に実行すべきアクションを取得"""
142+
if not progress['has_work_in_progress']:
143+
return "start_fresh"
144+
145+
# 作業中ファイルに未完了があるか確認
146+
incomplete_splits = [f for f, s in progress['split_status'].items() if not s['completed']]
147+
if incomplete_splits:
148+
return "continue_translation"
149+
150+
# すべて完了している場合は結合
151+
if progress['done_files']:
152+
return "join_files"
153+
154+
return "unknown"
155+
156+
157+
def main():
158+
if len(sys.argv) != 2:
159+
print("使用法: python check_translation_progress.py <po_file>")
160+
sys.exit(1)
161+
162+
po_file = sys.argv[1]
163+
if not os.path.exists(po_file):
164+
print(f"エラー: ファイル '{po_file}' が見つかりません")
165+
sys.exit(1)
166+
167+
progress = analyze_progress(po_file)
168+
print_progress_report(progress)
169+
170+
action = get_next_action(progress)
171+
print(f"\n🎯 推奨アクション: {action}")
172+
173+
174+
if __name__ == "__main__":
175+
main()

0 commit comments

Comments
 (0)