File size: 8,025 Bytes
14af3c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import os
import gradio as gr
import git
import tempfile
import shutil
from datetime import datetime
from typing import List, Dict, Tuple, Optional
import re

class TranslationTracker:
    def __init__(self):
        self.repo_url = "https://github.com/huggingface/transformers.git"
        self.repo_path = None
        self.en_docs_path = None
        self.ko_docs_path = None
        self.repo = None

    def clone_repo(self, progress=gr.Progress()):
        """Transformers 레포지토리를 클론합니다."""
        try:
            # 임시 디렉토리 생성
            temp_dir = tempfile.mkdtemp()
            progress(0.1, desc="레포지토리 클론 준비 중...")
            
            # depth=1로 shallow clone 수행 (더 빠름)
            progress(0.2, desc="레포지토리 클론 중...")
            self.repo = git.Repo.clone_from(self.repo_url, temp_dir, depth=1)
            self.repo_path = temp_dir
            
            # 문서 경로 설정
            self.en_docs_path = os.path.join(self.repo_path, "docs", "source", "en")
            self.ko_docs_path = os.path.join(self.repo_path, "docs", "source", "ko")
            
            progress(1.0, desc="레포지토리 클론 완료")
            return f"레포지토리 클론 완료: {self.repo_path}"
        except Exception as e:
            return f"레포지토리 클론 실패: {str(e)}"

    def cleanup(self):
        """임시 디렉토리 정리"""
        if self.repo_path and os.path.exists(self.repo_path):
            shutil.rmtree(self.repo_path)
            self.repo_path = None
            self.repo = None
    
    def get_last_commit_date(self, file_path: str) -> Optional[datetime]:
        """파일의 마지막 커밋 날짜를 가져옵니다."""
        try:
            # 파일이 존재하지 않으면 None 반환
            if not os.path.exists(file_path):
                return None
            
            # 파일의 상대 경로 구하기
            rel_path = os.path.relpath(file_path, self.repo_path)
            
            # 마지막 커밋 정보 찾기
            for commit in self.repo.iter_commits(paths=rel_path, max_count=1):
                return commit.committed_datetime
            
            return None
        except Exception:
            return None
    
    def get_translation_status(self, progress=gr.Progress()) -> List[Dict]:
        """모든 영어 문서와 해당하는 한글 번역 상태를 확인합니다."""
        if not self.repo_path:
            return [{"error": "레포지토리가 클론되지 않았습니다. 먼저 클론을 수행하세요."}]
        
        results = []
        en_md_files = []
        
        # 영어 마크다운 파일 수집
        progress(0.1, desc="영어 문서 스캔 중...")
        for root, _, files in os.walk(self.en_docs_path):
            for file in files:
                if file.endswith(".md"):
                    en_md_files.append(os.path.join(root, file))
        
        total_files = len(en_md_files)
        
        # 각 파일에 대한 번역 상태 확인
        for i, en_file in enumerate(en_md_files):
            progress((i + 1) / total_files, desc=f"번역 상태 확인 중 ({i+1}/{total_files})...")
            
            # 상대 경로 계산 (docs/source/en 이후 부분)
            rel_path = os.path.relpath(en_file, self.en_docs_path)
            ko_file = os.path.join(self.ko_docs_path, rel_path)
            
            # 파일 이름 추출
            file_name = os.path.basename(en_file)
            
            # 영어 문서 마지막 커밋 날짜
            en_commit_date = self.get_last_commit_date(en_file)
            
            # 번역 문서 마지막 커밋 날짜
            ko_commit_date = self.get_last_commit_date(ko_file)
            
            # 번역 상태 결정
            if ko_commit_date is None:
                status = "미번역"
                outdate = False
            else:
                if en_commit_date > ko_commit_date:
                    status = "번역됨 (업데이트 필요)"
                    outdate = True
                else:
                    status = "번역됨 (최신)"
                    outdate = False
            
            # 결과 추가
            results.append({
                "file_name": file_name,
                "en_path": rel_path,
                "ko_path": rel_path if os.path.exists(ko_file) else "없음",
                "en_last_commit": en_commit_date.strftime("%Y-%m-%d %H:%M:%S") if en_commit_date else "알 수 없음",
                "ko_last_commit": ko_commit_date.strftime("%Y-%m-%d %H:%M:%S") if ko_commit_date else "없음",
                "status": status,
                "outdate": outdate
            })
        
        # 파일명으로 정렬
        results.sort(key=lambda x: x["file_name"])
        return results

def create_ui():
    """Gradio UI 생성"""
    tracker = TranslationTracker()
    
    with gr.Blocks(title="Transformers 문서 번역 추적기") as app:
        gr.Markdown("# Transformers 문서 번역 추적기")
        gr.Markdown("HuggingFace Transformers 레포지토리의 문서 번역 상태를 확인합니다.")
        
        with gr.Row():
            clone_btn = gr.Button("레포지토리 클론", variant="primary")
            status_btn = gr.Button("번역 상태 확인", variant="secondary")
            cleanup_btn = gr.Button("정리", variant="stop")
        
        status_output = gr.Textbox(label="상태")
        
        with gr.Tabs():
            with gr.TabItem("모든 문서"):
                all_table = gr.DataFrame(
                    headers=["파일명", "영어 경로", "한글 경로", "영어 마지막 커밋", "한글 마지막 커밋", "상태"], 
                    datatype=["str", "str", "str", "str", "str", "str"],
                    label="번역 상태"
                )
            
            with gr.TabItem("번역 필요"):
                untranslated_table = gr.DataFrame(
                    headers=["파일명", "영어 경로", "상태"], 
                    datatype=["str", "str", "str"],
                    label="번역이 필요한 문서"
                )
            
            with gr.TabItem("업데이트 필요"):
                outdated_table = gr.DataFrame(
                    headers=["파일명", "영어 경로", "영어 마지막 커밋", "한글 마지막 커밋"], 
                    datatype=["str", "str", "str", "str"],
                    label="업데이트가 필요한 문서"
                )
        
        # 이벤트 핸들러
        clone_btn.click(tracker.clone_repo, outputs=status_output)
        
        def process_translation_status():
            results = tracker.get_translation_status()
            if results and "error" in results[0]:
                return status_output.update(results[0]["error"]), None, None, None
            
            # 전체 데이터
            all_data = [[r["file_name"], r["en_path"], r["ko_path"], r["en_last_commit"], r["ko_last_commit"], r["status"]] for r in results]
            
            # 미번역 데이터
            untranslated = [[r["file_name"], r["en_path"], r["status"]] for r in results if r["status"] == "미번역"]
            
            # 업데이트 필요 데이터
            outdated = [[r["file_name"], r["en_path"], r["en_last_commit"], r["ko_last_commit"]] for r in results if r["outdate"]]
            
            return "번역 상태 조회 완료", all_data, untranslated, outdated
        
        status_btn.click(
            process_translation_status,
            outputs=[status_output, all_table, untranslated_table, outdated_table]
        )
        
        cleanup_btn.click(
            lambda: (tracker.cleanup(), "정리 완료"),
            outputs=status_output
        )
    
    return app

def main():
    app = create_ui()
    app.launch()

if __name__ == "__main__":
    main()