"""Module for gradio chat-based translation agent interface.""" import os import re from pathlib import Path import gradio as gr from agent.workflow import ( report_translation_target_files, translate_docs_interactive, generate_github_pr, ) from pr_generator.searcher import find_reference_pr_simple_stream # State management class ChatState: def __init__(self): self.step = "welcome" # welcome -> find_files -> translate -> create_github_pr self.target_language = "ko" self.k_files = 10 self.files_to_translate = [] self.current_file_content = {"translated": ""} self.pr_result = None # Store PR creation result # GitHub configuration self.github_config = { "token": "", "owner": "", "repo_name": "", "reference_pr_url": "https://github.com/huggingface/transformers/pull/24968", } state = ChatState() def _extract_content_for_display(content: str) -> str: """Extract text from document for display.""" # Remove Copyright header to_translate = re.sub(r"", "", content, count=1, flags=re.DOTALL) to_translate = to_translate.strip() ## remove code blocks from text to_translate = re.sub(r"```.*?```", "", to_translate, flags=re.DOTALL) ## remove markdown tables from text to_translate = re.sub(r"^\|.*\|$\n?", "", to_translate, flags=re.MULTILINE) ## remove empty lines from text to_translate = re.sub(r"\n\n+", "\n\n", to_translate) return to_translate def get_welcome_message(): """Initial welcome message with file finding controls""" return """**š Welcome to š Hugging Face i18n Translation Agent!** I'll help you find files that need translation and translate them in a streamlined workflow. **š Let's start by finding files that need translation.** Use the **`Quick Controls`** on the right or **ask me `what`, `how`, or `help`** to get started. """ def process_file_search_handler(lang: str, k: int, history: list) -> tuple: """Process file search request and update Gradio UI components.""" global state state.target_language = lang state.k_files = k state.step = "find_files" status_report, files_list = report_translation_target_files(lang, k) state.files_to_translate = [file[0] for file in files_list] if files_list else [] response = f"""**ā File search completed!** **Status Report:** {status_report} **š Found first {len(state.files_to_translate)} files to translate:** """ if state.files_to_translate: for i, file in enumerate(state.files_to_translate[:5], 1): # Show first 5 response += f"\n{i}. `{file}`" if len(state.files_to_translate) > 5: response += f"\n... and {len(state.files_to_translate) - 5} more files" response += "\n\n**š Ready to start translation?**\nI can begin translating these files one by one. Would you like to proceed?" else: response += "\nNo files found that need translation." # Add to history history.append(["Please find files that need translation", response]) cleared_input = "" selected_tab = 1 if state.files_to_translate else 0 return history, cleared_input, update_status(), gr.Tabs(selected=selected_tab) def start_translation_process(): """Start the translation process for the first file""" if not state.files_to_translate: return "ā No files available for translation." current_file = state.files_to_translate[0] # Call translation function (simplified for demo) try: status, translated = translate_docs_interactive( state.target_language, [[current_file]] ) state.current_file_content = {"translated": translated} path = ( Path(__file__).resolve().parent.parent / f"translation_result/{current_file}" ) p = Path(path) p.parent.mkdir(parents=True, exist_ok=True) p.write_text(translated, encoding="utf-8") original_file_link = ( "https://github.com/huggingface/transformers/blob/main/" + current_file ) response = ( f"""š Translation for: `{current_file}`**\n""" "**š Original Content Link:**\n" "" f"{original_file_link}\n" "**š Translated Content:**\n" f"\n```\n\n{_extract_content_for_display(translated)}```\n" f"{status}\n" ) print("translated:") print(translated) print("extracted") except Exception as e: response = f"ā Translation failed: {str(e)}" response += "\n**ā”ļø Please try from the beginning.**" return response def handle_general_message(message): """Handle general messages""" message_lower = message.lower() if any(word in message_lower for word in ["help", "what", "how"]): return """**š¤ I'm your Hugging Face i18n Translation Agent!** I can help you: 1. **š Find files** that need translation 2. **š Translate documents** using AI 3. **š Review translations** for quality 4. **š Create GitHub PR** for translation Currently available actions with quick controls: - "find files" - Search for files needing translation - "translate" - Start translation process - "review" - Review current translation - "github" - Create GitHub Pull Request - "restart" - Start over""" elif "restart" in message_lower: global state state = ChatState() return get_welcome_message() else: return """I understand you want to work on translations! To get started, please use the controls above to configure your translation settings and find files that need translation. """ # Main handler def handle_user_message(message, history): """Handle user messages and provide appropriate responses""" global state if not message.strip(): return history, "" elif state.step == "find_files" and any( word in message.lower() for word in ["yes", "proceed", "start", "translate", "translation"] ): # User wants to start translation if state.files_to_translate: state.step = "translate" response = start_translation_process() else: response = ( "ā No files available for translation. Please search for files first." ) # Handle GitHub PR creation - This part is removed as approve_handler is the main entry point else: # General response response = handle_general_message(message) history.append([message, response]) return history, "" def update_status(): if state.step == "welcome": return """