diff --git a/README.md b/README.md index 963ed6f..245cafc 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,83 @@ Here's an example of how the AI assistant would call the `interactive_feedback` ``` +## Language Support + +The Interactive Feedback MCP supports multiple languages through a flexible JSON-based configuration system. Languages are automatically detected from the `languages/` directory. + +### Available Languages + +| Language Code | Language Name | File | +|---------------|---------------|------| +| `en` | English | `languages/en.json` | +| `zh` | 中文 (Chinese) | `languages/zh.json` | +| `fr` | Français (French) | `languages/fr.json` | + +### Language Configuration Structure + +Each language file follows this JSON structure: + +```json +{ + "name": "Language Display Name", + "window_title": "Window title text", + "show_command_section": "Show Command Section", + "hide_command_section": "Hide Command Section", + "command": "Command", + "working_directory": "Working directory", + "run": "&Run", + "stop": "Sto&p", + "execute_automatically": "Execute automatically on next run", + "save_configuration": "&Save Configuration", + "console": "Console", + "clear": "&Clear", + "feedback": "Feedback", + "feedback_placeholder": "Enter your feedback here (Ctrl+Enter to submit)", + "send_feedback": "&Send Feedback (Ctrl+Enter)", + "contact_info": "Contact information HTML", + "configuration_saved": "Configuration saved for this project.\n", + "error_running_command": "Error running command: {error}\n", + "command_prompt": "$ {command}\n", + "language": "Language", + "language_changed": "Language changed message.\n", + "please_enter_command": "Please enter a command to run\n", + "argparse_description": "Run the feedback UI", + "argparse_project_directory_help": "The project directory to run the command in", + "argparse_prompt_help": "The prompt to show to the user", + "argparse_output_file_help": "Path to save the feedback result as JSON", + "default_prompt": "I implemented the changes you requested.", + "logs_collected": "Logs collected", + "feedback_received": "Feedback received", + "argparse_language_help": "Interface language, automatically detects available languages" +} +``` + +### Adding New Languages + +To add support for a new language: + +1. Create a new JSON file in the `languages/` directory (e.g., `languages/es.json` for Spanish) +2. Include the `name` field with the language's display name +3. Translate all the text keys according to the structure above +4. The language will be automatically detected and available in the language selector + +### Usage + +You can specify the language when running the application: + +```bash +# Use English (default) +python feedback_ui.py --language en + +# Use Chinese +python feedback_ui.py --language zh + +# Use French +python feedback_ui.py --language fr +``` + +The language preference is automatically saved and restored between sessions. + ## Acknowledgements & Contact If you find this Interactive Feedback MCP useful, the best way to show appreciation is by following Fábio Ferreira on [X @fabiomlferreira](https://x.com/fabiomlferreira). diff --git a/feedback_ui.py b/feedback_ui.py index c71e951..f51a3c6 100644 --- a/feedback_ui.py +++ b/feedback_ui.py @@ -13,11 +13,13 @@ from PySide6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QCheckBox, QTextEdit, QGroupBox + QLabel, QLineEdit, QPushButton, QCheckBox, QTextEdit, QGroupBox, QComboBox ) from PySide6.QtCore import Qt, Signal, QObject, QTimer, QSettings from PySide6.QtGui import QTextCursor, QIcon, QKeyEvent, QFont, QFontDatabase, QPalette, QColor +from language_manager import get_language_manager, get_text + class FeedbackResult(TypedDict): command_logs: str interactive_feedback: str @@ -221,14 +223,18 @@ def __init__(self, project_directory: str, prompt: str): self.log_signals = LogSignals() self.log_signals.append_log.connect(self._append_log) - self.setWindowTitle("Interactive Feedback MCP") + self.language_manager = get_language_manager() + + self.settings = QSettings("InteractiveFeedbackMCP", "InteractiveFeedbackMCP") + saved_language = self.settings.value("language", "en", type=str) + self.language_manager.set_language(saved_language) + + self.setWindowTitle(get_text("window_title")) script_dir = os.path.dirname(os.path.abspath(__file__)) icon_path = os.path.join(script_dir, "images", "feedback.png") self.setWindowIcon(QIcon(icon_path)) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) - - self.settings = QSettings("InteractiveFeedbackMCP", "InteractiveFeedbackMCP") - + # Load general UI settings for the main window (geometry, state) self.settings.beginGroup("MainWindow_General") geometry = self.settings.value("geometry") @@ -244,7 +250,7 @@ def __init__(self, project_directory: str, prompt: str): if state: self.restoreState(state) self.settings.endGroup() # End "MainWindow_General" group - + # Load project-specific settings (command, auto-execute, command section visibility) self.project_group_name = get_project_settings_group(self.project_directory) self.settings.beginGroup(self.project_group_name) @@ -252,7 +258,7 @@ def __init__(self, project_directory: str, prompt: str): loaded_execute_auto = self.settings.value("execute_automatically", False, type=bool) command_section_visible = self.settings.value("commandSectionVisible", False, type=bool) self.settings.endGroup() # End project-specific group - + self.config: FeedbackConfig = { "run_command": loaded_run_command, "execute_automatically": loaded_execute_auto @@ -263,9 +269,9 @@ def __init__(self, project_directory: str, prompt: str): # Set command section visibility AFTER _create_ui has created relevant widgets self.command_group.setVisible(command_section_visible) if command_section_visible: - self.toggle_command_button.setText("Hide Command Section") + self.toggle_command_button.setText(get_text("hide_command_section")) else: - self.toggle_command_button.setText("Show Command Section") + self.toggle_command_button.setText(get_text("show_command_section")) set_dark_title_bar(self, True) @@ -286,19 +292,45 @@ def _create_ui(self): self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) + # Language selection + language_layout = QHBoxLayout() + self.language_label = QLabel(get_text("language") + ":") + self.language_label.setObjectName("language_label") + self.language_combo = QComboBox() + self.language_combo.setObjectName("language_combo") + available_languages = self.language_manager.get_available_languages() + for code, name in available_languages.items(): + self.language_combo.addItem(name, code) + + # Set current language in combo box + current_lang = self.language_manager.get_current_language() + for i in range(self.language_combo.count()): + if self.language_combo.itemData(i) == current_lang: + self.language_combo.setCurrentIndex(i) + break + + self.language_combo.currentTextChanged.connect(self._on_language_changed) + language_layout.addWidget(self.language_label) + language_layout.addWidget(self.language_combo) + language_layout.addStretch() + layout.addLayout(language_layout) + # Toggle Command Section Button - self.toggle_command_button = QPushButton("Show Command Section") + self.toggle_command_button = QPushButton(get_text("show_command_section")) + self.toggle_command_button.setObjectName("toggle_command_button") self.toggle_command_button.clicked.connect(self._toggle_command_section) layout.addWidget(self.toggle_command_button) # Command section - self.command_group = QGroupBox("Command") + self.command_group = QGroupBox(get_text("command")) + self.command_group.setObjectName("command_group") command_layout = QVBoxLayout(self.command_group) # Working directory label formatted_path = self._format_windows_path(self.project_directory) - working_dir_label = QLabel(f"Working directory: {formatted_path}") - command_layout.addWidget(working_dir_label) + self.working_dir_label = QLabel(f"{get_text('working_directory')}: {formatted_path}") + self.working_dir_label.setObjectName("working_dir_label") + command_layout.addWidget(self.working_dir_label) # Command input row command_input_layout = QHBoxLayout() @@ -306,7 +338,8 @@ def _create_ui(self): self.command_entry.setText(self.config["run_command"]) self.command_entry.returnPressed.connect(self._run_command) self.command_entry.textChanged.connect(self._update_config) - self.run_button = QPushButton("&Run") + self.run_button = QPushButton(get_text("run")) + self.run_button.setObjectName("run_button") self.run_button.clicked.connect(self._run_command) command_input_layout.addWidget(self.command_entry) @@ -315,22 +348,25 @@ def _create_ui(self): # Auto-execute and save config row auto_layout = QHBoxLayout() - self.auto_check = QCheckBox("Execute automatically on next run") + self.auto_check = QCheckBox(get_text("execute_automatically")) + self.auto_check.setObjectName("auto_check") self.auto_check.setChecked(self.config.get("execute_automatically", False)) self.auto_check.stateChanged.connect(self._update_config) - save_button = QPushButton("&Save Configuration") - save_button.clicked.connect(self._save_config) + self.save_button = QPushButton(get_text("save_configuration")) + self.save_button.setObjectName("save_button") + self.save_button.clicked.connect(self._save_config) auto_layout.addWidget(self.auto_check) auto_layout.addStretch() - auto_layout.addWidget(save_button) + auto_layout.addWidget(self.save_button) command_layout.addLayout(auto_layout) # Console section (now part of command_group) - console_group = QGroupBox("Console") - console_layout_internal = QVBoxLayout(console_group) - console_group.setMinimumHeight(200) + self.console_group = QGroupBox(get_text("console")) + self.console_group.setObjectName("console_group") + console_layout_internal = QVBoxLayout(self.console_group) + self.console_group.setMinimumHeight(200) # Log text area self.log_text = QTextEdit() @@ -342,66 +378,77 @@ def _create_ui(self): # Clear button button_layout = QHBoxLayout() - self.clear_button = QPushButton("&Clear") + self.clear_button = QPushButton(get_text("clear")) + self.clear_button.setObjectName("clear_button") self.clear_button.clicked.connect(self.clear_logs) button_layout.addStretch() button_layout.addWidget(self.clear_button) console_layout_internal.addLayout(button_layout) - - command_layout.addWidget(console_group) - self.command_group.setVisible(False) + command_layout.addWidget(self.console_group) + + self.command_group.setVisible(False) layout.addWidget(self.command_group) # Feedback section with adjusted height - self.feedback_group = QGroupBox("Feedback") + self.feedback_group = QGroupBox(get_text("feedback")) + self.feedback_group.setObjectName("feedback_group") feedback_layout = QVBoxLayout(self.feedback_group) # Short description label (from self.prompt) - self.description_label = QLabel(self.prompt) + display_prompt = self.prompt + all_default_prompts = self.language_manager.get_all_default_prompts() + if self.prompt in all_default_prompts: + display_prompt = get_text("default_prompt") + + self.description_label = QLabel(display_prompt) + self.description_label.setObjectName("description_label") self.description_label.setWordWrap(True) feedback_layout.addWidget(self.description_label) self.feedback_text = FeedbackTextEdit() + self.feedback_text.setObjectName("feedback_text") font_metrics = self.feedback_text.fontMetrics() row_height = font_metrics.height() # Calculate height for 5 lines + some padding for margins padding = self.feedback_text.contentsMargins().top() + self.feedback_text.contentsMargins().bottom() + 5 # 5 is extra vertical padding self.feedback_text.setMinimumHeight(5 * row_height + padding) - self.feedback_text.setPlaceholderText("Enter your feedback here (Ctrl+Enter to submit)") - submit_button = QPushButton("&Send Feedback (Ctrl+Enter)") - submit_button.clicked.connect(self._submit_feedback) + self.feedback_text.setPlaceholderText(get_text("feedback_placeholder")) + self.submit_button = QPushButton(get_text("send_feedback")) + self.submit_button.setObjectName("submit_button") + self.submit_button.clicked.connect(self._submit_feedback) feedback_layout.addWidget(self.feedback_text) - feedback_layout.addWidget(submit_button) + feedback_layout.addWidget(self.submit_button) # Set minimum height for feedback_group to accommodate its contents # This will be based on the description label and the 5-line feedback_text - self.feedback_group.setMinimumHeight(self.description_label.sizeHint().height() + self.feedback_text.minimumHeight() + submit_button.sizeHint().height() + feedback_layout.spacing() * 2 + feedback_layout.contentsMargins().top() + feedback_layout.contentsMargins().bottom() + 10) # 10 for extra padding + self.feedback_group.setMinimumHeight(self.description_label.sizeHint().height() + self.feedback_text.minimumHeight() + self.submit_button.sizeHint().height() + feedback_layout.spacing() * 2 + feedback_layout.contentsMargins().top() + feedback_layout.contentsMargins().bottom() + 10) # 10 for extra padding # Add widgets in a specific order layout.addWidget(self.feedback_group) # Credits/Contact Label - contact_label = QLabel('Need to improve? Contact Fábio Ferreira on X.com or visit dotcursorrules.com') - contact_label.setOpenExternalLinks(True) - contact_label.setAlignment(Qt.AlignCenter) + self.contact_label = QLabel(get_text("contact_info")) + self.contact_label.setObjectName("contact_label") + self.contact_label.setOpenExternalLinks(True) + self.contact_label.setAlignment(Qt.AlignCenter) # Optionally, make font a bit smaller and less prominent # contact_label_font = contact_label.font() # contact_label_font.setPointSize(contact_label_font.pointSize() - 1) # contact_label.setFont(contact_label_font) - contact_label.setStyleSheet("font-size: 9pt; color: #cccccc;") # Light gray for dark theme - layout.addWidget(contact_label) + self.contact_label.setStyleSheet("font-size: 9pt; color: #cccccc;") # Light gray for dark theme + layout.addWidget(self.contact_label) def _toggle_command_section(self): is_visible = self.command_group.isVisible() self.command_group.setVisible(not is_visible) if not is_visible: - self.toggle_command_button.setText("Hide Command Section") + self.toggle_command_button.setText(get_text("hide_command_section")) else: - self.toggle_command_button.setText("Show Command Section") - + self.toggle_command_button.setText(get_text("show_command_section")) + # Immediately save the visibility state for this project self.settings.beginGroup(self.project_group_name) self.settings.setValue("commandSectionVisible", self.command_group.isVisible()) @@ -411,7 +458,7 @@ def _toggle_command_section(self): new_height = self.centralWidget().sizeHint().height() if self.command_group.isVisible() and self.command_group.layout().sizeHint().height() > 0 : # if command group became visible and has content, ensure enough height - min_content_height = self.command_group.layout().sizeHint().height() + self.feedback_group.minimumHeight() + self.toggle_command_button.height() + layout().spacing() * 2 + min_content_height = self.command_group.layout().sizeHint().height() + self.feedback_group.minimumHeight() + self.toggle_command_button.height() + self.centralWidget().layout().spacing() * 2 new_height = max(new_height, min_content_height) current_width = self.width() @@ -432,8 +479,8 @@ def _check_process_status(self): if self.process and self.process.poll() is not None: # Process has terminated exit_code = self.process.poll() - self._append_log(f"\nProcess exited with code {exit_code}\n") - self.run_button.setText("&Run") + self._append_log(f"\n{get_text('process_exited', exit_code=exit_code)}\n") + self.run_button.setText(get_text("run")) self.process = None self.activateWindow() self.feedback_text.setFocus() @@ -442,7 +489,7 @@ def _run_command(self): if self.process: kill_tree(self.process) self.process = None - self.run_button.setText("&Run") + self.run_button.setText(get_text("run")) return # Clear the log buffer but keep UI logs visible @@ -450,11 +497,11 @@ def _run_command(self): command = self.command_entry.text() if not command: - self._append_log("Please enter a command to run\n") + self._append_log(get_text("please_enter_command")) return - self._append_log(f"$ {command}\n") - self.run_button.setText("Sto&p") + self._append_log(get_text("command_prompt", command=command)) + self.run_button.setText(get_text("stop")) try: self.process = subprocess.Popen( @@ -493,8 +540,8 @@ def read_output(pipe): self.status_timer.start(100) # Check every 100ms except Exception as e: - self._append_log(f"Error running command: {str(e)}\n") - self.run_button.setText("&Run") + self._append_log(get_text("error_running_command", error=str(e))) + self.run_button.setText(get_text("run")) def _submit_feedback(self): self.feedback_result = FeedbackResult( @@ -513,7 +560,89 @@ def _save_config(self): self.settings.setValue("run_command", self.config["run_command"]) self.settings.setValue("execute_automatically", self.config["execute_automatically"]) self.settings.endGroup() - self._append_log("Configuration saved for this project.\n") + self._append_log(get_text("configuration_saved")) + + def _on_language_changed(self): + """Change language and update UI texts""" + selected_index = self.language_combo.currentIndex() + if selected_index >= 0: + language_code = self.language_combo.itemData(selected_index) + if language_code and self.language_manager.set_language(language_code): + # Save language preference to settings + self.settings.setValue("language", language_code) + + # Update UI texts + self._update_ui_texts() + + # Record language change + self._append_log(get_text("language_changed")) + + def _update_ui_texts(self): + """Update UI texts to the current language""" + # Update window title + self.setWindowTitle(get_text("window_title")) + + # Initialize language manager + widget_text_mapping = { + 'language_label': ('setText', lambda: get_text("language") + ":"), + 'command_group': ('setTitle', 'command'), + 'feedback_group': ('setTitle', 'feedback'), + 'console_group': ('setTitle', 'console'), + 'auto_check': ('setText', 'execute_automatically'), + 'clear_button': ('setText', 'clear'), + 'save_button': ('setText', 'save_configuration'), + 'submit_button': ('setText', 'send_feedback'), + 'contact_label': ('setText', 'contact_info'), + 'working_dir_label': ('setText', lambda: f"{get_text('working_directory')}: {self._format_windows_path(self.project_directory)}"), + 'feedback_text': ('setPlaceholderText', 'feedback_placeholder'), + } + + # Update UI texts based on the mapping + for widget_name, (method_name, text_key) in widget_text_mapping.items(): + if hasattr(self, widget_name): + widget = getattr(self, widget_name) + if widget and hasattr(widget, method_name): + if callable(text_key): + text = text_key() + else: + text = get_text(text_key) + + getattr(widget, method_name)(text) + + if hasattr(self, 'toggle_command_button'): + if self.command_group.isVisible(): + self.toggle_command_button.setText(get_text("hide_command_section")) + else: + self.toggle_command_button.setText(get_text("show_command_section")) + + if hasattr(self, 'run_button'): + if self.process: + self.run_button.setText(get_text("stop")) + else: + self.run_button.setText(get_text("run")) + + if hasattr(self, 'language_combo'): + current_lang = self.language_manager.get_current_language() + available_languages = self.language_manager.get_available_languages() + + self.language_combo.currentTextChanged.disconnect() + self.language_combo.clear() + for code, name in available_languages.items(): + self.language_combo.addItem(name, code) + + for i in range(self.language_combo.count()): + if self.language_combo.itemData(i) == current_lang: + self.language_combo.setCurrentIndex(i) + break + + self.language_combo.currentTextChanged.connect(self._on_language_changed) + + if hasattr(self, 'description_label') and self.description_label: + current_text = self.description_label.text() + all_default_prompts = self.language_manager.get_all_default_prompts() + + if (self.prompt in all_default_prompts or current_text in all_default_prompts): + self.description_label.setText(get_text("default_prompt")) def closeEvent(self, event): # Save general UI settings for the main window (geometry, state) @@ -568,14 +697,30 @@ def feedback_ui(project_directory: str, prompt: str, output_file: Optional[str] return result if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Run the feedback UI") - parser.add_argument("--project-directory", default=os.getcwd(), help="The project directory to run the command in") - parser.add_argument("--prompt", default="I implemented the changes you requested.", help="The prompt to show to the user") - parser.add_argument("--output-file", help="Path to save the feedback result as JSON") + lang_manager = get_language_manager() # This is necessary to initialize the language manager + + available_languages = list(lang_manager.get_available_languages().keys()) + default_language = available_languages[0] if available_languages else "en" + + # First check for --language argument + import sys + if "--language" in sys.argv: + lang_index = sys.argv.index("--language") + if lang_index + 1 < len(sys.argv): + requested_lang = sys.argv[lang_index + 1] + if requested_lang in available_languages: + lang_manager.set_language(requested_lang) + + parser = argparse.ArgumentParser(description=get_text("argparse_description")) + parser.add_argument("--project-directory", default=os.getcwd(), help=get_text("argparse_project_directory_help")) + parser.add_argument("--prompt", default=get_text("default_prompt"), help=get_text("argparse_prompt_help")) + parser.add_argument("--output-file", help=get_text("argparse_output_file_help")) + parser.add_argument("--language", choices=available_languages, default=default_language, help=get_text("argparse_language_help")) args = parser.parse_args() + lang_manager.set_language(args.language) result = feedback_ui(args.project_directory, args.prompt, args.output_file) if result: - print(f"\nLogs collected: \n{result['logs']}") - print(f"\nFeedback received:\n{result['interactive_feedback']}") + print(f"\n{get_text('logs_collected')}: \n{result['logs']}") + print(f"\n{get_text('feedback_received')}:\n{result['interactive_feedback']}") sys.exit(0) diff --git a/language_manager.py b/language_manager.py new file mode 100644 index 0000000..c9c0c2c --- /dev/null +++ b/language_manager.py @@ -0,0 +1,129 @@ +# Language Manager for Interactive Feedback MCP +# Handles loading and managing language configurations + +import os +import json +import glob +from typing import Dict, Optional + + +class LanguageManager: + """Class for managing multiple language configurations""" + + def __init__(self, default_language: str = "en"): + self.current_language = default_language + self.languages: Dict[str, Dict[str, str]] = {} + self.available_languages: list[str] = [] + self._load_languages() + + def _load_languages(self): + """Scan and load all available language configuration files""" + script_dir = os.path.dirname(os.path.abspath(__file__)) + languages_dir = os.path.join(script_dir, "languages") + + if not os.path.exists(languages_dir): + print(f"Warning: Languages directory {languages_dir} not found") + return + + # Get language files + json_files = glob.glob(os.path.join(languages_dir, "*.json")) + + for lang_file in json_files: + # Get the language code from the file name + lang_code = os.path.splitext(os.path.basename(lang_file))[0] + + try: + with open(lang_file, 'r', encoding='utf-8') as f: + lang_data = json.load(f) + + # Verify that the language file contains the necessary fields + if 'name' not in lang_data: + print(f"Warning: Language file {lang_file} missing 'name' field") + continue + + self.languages[lang_code] = lang_data + self.available_languages.append(lang_code) + + except FileNotFoundError: + print(f"Warning: Language file {lang_file} not found") + except json.JSONDecodeError as e: + print(f"Warning: Error parsing language file {lang_file}: {e}") + + # Ensure there is a default language + if self.current_language not in self.available_languages and self.available_languages: + self.current_language = self.available_languages[0] + elif not self.available_languages: + print("Warning: No valid language files found") + + def set_language(self, language_code: str) -> bool: + """Set the current language""" + if language_code in self.languages: + self.current_language = language_code + return True + return False + + def get_text(self, key: str, **kwargs) -> str: + """Get the text for a given key, supporting formatting arguments""" + if self.current_language not in self.languages: + # If the current language is not available, fallback to English + self.current_language = "en" + + text = self.languages.get(self.current_language, {}).get(key, key) + + # If the key is not found in the current language, try to get it from English + if text == key and self.current_language != "en": + text = self.languages.get("en", {}).get(key, key) + + # Apply formatting arguments + if kwargs: + try: + text = text.format(**kwargs) + except (KeyError, ValueError): + # If formatting fails, return the original text + pass + + return text + + def get_current_language(self) -> str: + """Get the current language code""" + return self.current_language + + def get_available_languages(self) -> Dict[str, str]: + """Retrieve the list of available languages and return the mapping between language codes and display names""" + result = {} + for lang_code in self.available_languages: + if lang_code in self.languages and 'name' in self.languages[lang_code]: + result[lang_code] = self.languages[lang_code]['name'] + else: + result[lang_code] = lang_code + return result + + def get_all_default_prompts(self) -> list[str]: + """Get all default prompt variants for all languages""" + default_prompts = [] + for lang_code in self.available_languages: + if lang_code in self.languages and 'default_prompt' in self.languages[lang_code]: + prompt = self.languages[lang_code]['default_prompt'] + if prompt not in default_prompts: + default_prompts.append(prompt) + return default_prompts + + +_language_manager = None + +def get_language_manager() -> LanguageManager: + """Get a global language manager instance""" + global _language_manager + if _language_manager is None: + _language_manager = LanguageManager() + return _language_manager + + +def set_global_language(language_code: str) -> bool: + """Set global language""" + return get_language_manager().set_language(language_code) + + +def get_text(key: str, **kwargs) -> str: + """Convenient function for obtaining text""" + return get_language_manager().get_text(key, **kwargs) diff --git a/languages/en.json b/languages/en.json new file mode 100644 index 0000000..88a34dd --- /dev/null +++ b/languages/en.json @@ -0,0 +1,33 @@ +{ + "name": "English", + "window_title": "Interactive Feedback MCP", + "show_command_section": "Show Command Section", + "hide_command_section": "Hide Command Section", + "command": "Command", + "working_directory": "Working directory", + "run": "&Run", + "stop": "Sto&p", + "execute_automatically": "Execute automatically on next run", + "save_configuration": "&Save Configuration", + "console": "Console", + "clear": "&Clear", + "feedback": "Feedback", + "feedback_placeholder": "Enter your feedback here (Ctrl+Enter to submit)", + "send_feedback": "&Send Feedback (Ctrl+Enter)", + "contact_info": "Need to improve? Contact Fábio Ferreira on X.com or visit dotcursorrules.com", + "configuration_saved": "Configuration saved for this project.\n", + "error_running_command": "Error running command: {error}\n", + "command_prompt": "$ {command}\n", + "language": "Language", + "language_changed": "Language changed to English.\n", + "please_enter_command": "Please enter a command to run\n", + "argparse_description": "Run the feedback UI", + "argparse_project_directory_help": "The project directory to run the command in", + "argparse_prompt_help": "The prompt to show to the user", + "argparse_output_file_help": "Path to save the feedback result as JSON", + "default_prompt": "I implemented the changes you requested.", + "logs_collected": "Logs collected", + "feedback_received": "Feedback received", + "argparse_language_help": "Interface language, automatically detects available languages", + "process_exited": "Process exited with code {exit_code}" +} diff --git a/languages/fr.json b/languages/fr.json new file mode 100644 index 0000000..e1642e1 --- /dev/null +++ b/languages/fr.json @@ -0,0 +1,33 @@ +{ + "name": "Français", + "window_title": "Interface de Retour Interactif MCP", + "show_command_section": "Afficher la Section Commande", + "hide_command_section": "Masquer la Section Commande", + "command": "Commande", + "working_directory": "Répertoire de travail", + "run": "&Exécuter", + "stop": "&Arrêter", + "execute_automatically": "Exécuter automatiquement au prochain lancement", + "save_configuration": "&Sauvegarder la Configuration", + "console": "Console", + "clear": "&Effacer", + "feedback": "Retour", + "feedback_placeholder": "Entrez votre retour ici (Ctrl+Entrée pour soumettre)", + "send_feedback": "&Envoyer le Retour (Ctrl+Entrée)", + "contact_info": "Besoin d'amélioration ? Contactez Fábio Ferreira sur X.com ou visitez dotcursorrules.com", + "configuration_saved": "Configuration sauvegardée pour ce projet.\n", + "error_running_command": "Erreur lors de l'exécution de la commande : {error}\n", + "command_prompt": "$ {command}\n", + "language": "Langue", + "language_changed": "Langue changée en français.\n", + "please_enter_command": "Veuillez entrer une commande à exécuter\n", + "argparse_description": "Lancer l'interface de retour", + "argparse_project_directory_help": "Le répertoire du projet dans lequel exécuter la commande", + "argparse_prompt_help": "Le message à afficher à l'utilisateur", + "argparse_output_file_help": "Chemin pour sauvegarder le résultat du retour en JSON", + "default_prompt": "J'ai implémenté les changements que vous avez demandés.", + "logs_collected": "Journaux collectés", + "feedback_received": "Retour reçu", + "argparse_language_help": "Langue de l'interface, détecte automatiquement les langues disponibles", + "process_exited": "Le processus s'est terminé avec le code {exit_code}" +} diff --git a/languages/zh.json b/languages/zh.json new file mode 100644 index 0000000..8eb1c01 --- /dev/null +++ b/languages/zh.json @@ -0,0 +1,33 @@ +{ + "name": "中文", + "window_title": "交互式反馈 MCP", + "show_command_section": "显示命令区域", + "hide_command_section": "隐藏命令区域", + "command": "命令", + "working_directory": "工作目录", + "run": "运行", + "stop": "停止", + "execute_automatically": "下次运行时自动执行", + "save_configuration": "保存配置", + "console": "控制台", + "clear": "清除", + "feedback": "反馈", + "feedback_placeholder": "在此输入您的反馈", + "send_feedback": "发送反馈", + "contact_info": "需要改进?联系 Fábio Ferreira 在 X.com 或访问 dotcursorrules.com", + "configuration_saved": "此项目的配置已保存。\n", + "error_running_command": "运行命令时出错: {error}\n", + "command_prompt": "$ {command}\n", + "language": "语言", + "language_changed": "语言已更改为中文。\n", + "please_enter_command": "请输入要运行的命令\n", + "argparse_description": "运行反馈界面", + "argparse_project_directory_help": "运行命令的项目目录", + "argparse_prompt_help": "显示给用户的提示信息", + "argparse_output_file_help": "保存反馈结果为JSON的路径", + "default_prompt": "我已实现您请求的更改。", + "logs_collected": "收集的日志", + "feedback_received": "收到的反馈", + "argparse_language_help": "界面语言,自动检测可用语言", + "process_exited": "进程已退出,退出代码 {exit_code}" +}