diff --git a/public/locales/en.json b/public/locales/en.json index 0dc833fd..8efb7e5f 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -1,657 +1,657 @@ { - "login": { - "title": "Welcome to Maxun", - "email": "Email", - "password": "Password", - "button": "Login", - "loading": "Loading", - "register_prompt": "Don't have an account?", - "register_link": "Register", - "welcome_notification": "Welcome to Maxun!", - "validation": { - "required_fields": "Email and password are required", - "password_length": "Password must be at least 6 characters" - }, - "error": { - "user_not_found": "User does not exist", - "invalid_credentials": "Invalid email or password", - "server_error": "Login failed. Please try again later", - "generic": "An error occurred. Please try again" - } + "login": { + "title": "Welcome to Maxun", + "email": "Email", + "password": "Password", + "button": "Login", + "loading": "Loading", + "register_prompt": "Don't have an account?", + "register_link": "Register", + "welcome_notification": "Welcome to Maxun!", + "validation": { + "required_fields": "Email and password are required", + "password_length": "Password must be at least 6 characters" }, - "register": { - "title": "Create An Account", - "email": "Email", - "password": "Password", - "button": "Register", - "loading": "Loading", - "register_prompt": "Already have an account?", - "login_link": "Login", - "welcome_notification": "Welcome to Maxun!", - "validation": { - "email_required": "Email is required", - "password_requirements": "Password must be at least 6 characters" - }, - "error": { - "user_exists": "User with this email already exists", - "creation_failed": "Could not create account", - "server_error": "Server error occurred", - "generic": "Registration failed. Please try again" - } + "error": { + "user_not_found": "User does not exist", + "invalid_credentials": "Invalid email or password", + "server_error": "Login failed. Please try again later", + "generic": "An error occurred. Please try again" + } + }, + "register": { + "title": "Create An Account", + "email": "Email", + "password": "Password", + "button": "Register", + "loading": "Loading", + "register_prompt": "Already have an account?", + "login_link": "Login", + "welcome_notification": "Welcome to Maxun!", + "validation": { + "email_required": "Email is required", + "password_requirements": "Password must be at least 6 characters" }, - "recordingtable":{ - "run": "Run", - "name": "Name", - "schedule": "Schedule", - "integrate": "Integrate", - "settings": "Settings", - "options": "Options", - "heading":"My Robots", - "new":"Create Robot", - "search_criteria": "Try adjusting your search criteria", - "placeholder": { - "title": "You're All Set to Start", - "body": "Robots you create will appear here. Click \"Create Robot\" to get started!", - "search": "No robots match your search" + "error": { + "user_exists": "User with this email already exists", + "creation_failed": "Could not create account", + "server_error": "Server error occurred", + "generic": "Registration failed. Please try again" + } + }, + "recordingtable": { + "run": "Run", + "name": "Name", + "schedule": "Schedule", + "integrate": "Integrate", + "settings": "Settings", + "options": "Options", + "heading": "My Robots", + "new": "Create Robot", + "search_criteria": "Try adjusting your search criteria", + "placeholder": { + "title": "You're All Set to Start", + "body": "Robots you create will appear here. Click \"Create Robot\" to get started!", + "search": "No robots match your search" + }, + "modal": { + "title": "Enter the URL", + "login_title": "Does this website require logging in?", + "label": "URL", + "button": "Start Recording" + }, + "warning_modal": { + "title": "Active Browser Detected", + "message": "There is already a browser recording session running. Would you like to discard it and create a new recording?", + "discard_and_create": "Discard & Create New", + "cancel": "Cancel" + }, + "retrain": "Retrain", + "edit": "Edit", + "delete": "Delete", + "duplicate": "Duplicate", + "search": "Search Robots...", + "notifications": { + "delete_warning": "The robot has associated runs. First delete runs to delete the robot", + "delete_success": "Robot deleted successfully", + "auth_success": "Robot successfully authenticated", + "browser_limit_warning": "Remote browsers are currently busy. Please wait for a few minutes and try again" + } + }, + "mainmenu": { + "recordings": "Robots", + "runs": "Runs", + "proxy": "Proxy", + "apikey": "API Key", + "feedback": "Join Maxun Cloud", + "apidocs": "Website To API" + }, + "runstable": { + "runs": "All Runs", + "runStatus": "Status", + "runName": "Name", + "name": "Name", + "startedAt": "Started At", + "finishedAt": "Finished At", + "delete": "Delete", + "settings": "Settings", + "search": "Search Runs...", + "sort_tooltip": "Click to sort", + "placeholder": { + "title": "No Runs Found", + "body": "This is where all your robot runs will appear. Once a robot is active, its runs will be logged here.", + "search": "No runs match your search" + }, + "notifications": { + "no_runs": "No runs found. Please try again.", + "delete_success": "Run deleted successfully" + } + }, + "proxy": { + "title": "Proxy Configuration", + "tab_standard": "Standard Proxy", + "tab_rotation": "Automatic Proxy Rotation", + "server_url": "Proxy Server URL", + "server_url_helper": "Proxy to be used for all robots. HTTP and SOCKS proxies are supported. Example http://myproxy.com:3128 or socks5://myproxy.com:3128. Short form myproxy.com:3128 is considered an HTTP proxy.", + "requires_auth": "Requires Authentication?", + "username": "Username", + "password": "Password", + "add_proxy": "Add Proxy", + "test_proxy": "Test Proxy", + "remove_proxy": "Remove Proxy", + "table": { + "proxy_url": "Proxy URL", + "requires_auth": "Requires Authentication" + }, + "coming_soon": "Coming Soon - In Open Source (Basic Rotation) & Cloud (Advanced Rotation). If you don't want to manage the infrastructure, join our cloud waitlist to get early access.", + "join_waitlist": "Join Maxun Cloud Waitlist", + "alert": { + "title": "If your proxy requires a username and password, always provide them separate from the proxy URL.", + "right_way": "The right way", + "wrong_way": "The wrong way", + "proxy_url": "Proxy URL:", + "username": "Username:", + "password": "Password:" + }, + "notifications": { + "config_success": "Proxy saved successfully", + "config_error": "Failed to save proxy. Try again.", + "test_success": "Proxy is working", + "test_error": "Proxy test failed. Try again.", + "fetch_success": "Proxy loaded successfully", + "remove_success": "Proxy removed successfully", + "remove_error": "Failed to remove proxy. Try again." + } + }, + "apikey": { + "title": "Manage Your API Key", + "default_name": "Maxun API Key", + "table": { + "name": "API Key Name", + "key": "API Key", + "actions": "Actions" + }, + "actions": { + "copy": "Copy", + "show": "Show", + "hide": "Hide", + "delete": "Delete" + }, + "no_key_message": "You haven't generated an API key yet.", + "generate_button": "Generate API Key", + "notifications": { + "fetch_error": "Failed to fetch API Key - {{error}}", + "generate_success": "Generated API Key successfully", + "generate_error": "Failed to generate API Key - {{error}}", + "delete_success": "API Key deleted successfully", + "delete_error": "Failed to delete API Key - {{error}}", + "copy_success": "Copied API Key successfully" + } + }, + "action_description": { + "text": { + "title": "Capture Text", + "description": "Hover over the texts you want to extract and click to select them" + }, + "screenshot": { + "title": "Capture Screenshot", + "description": "Capture a partial or full page screenshot of the current page." + }, + "list": { + "title": "Capture List", + "description": "Hover over the list you want to extract. Once selected, you can hover over all texts inside the list you selected. Click to select them." + }, + "default": { + "title": "What data do you want to extract?", + "description": "A robot can perform one or multiple actions. Choose from the options listed below." + }, + "list_stages": { + "initial": "Select the list you want to extract along with the texts inside it", + "pagination": "Select how the robot can capture the rest of the list", + "limit": "Choose the number of items to extract", + "complete": "Capture is complete" + }, + "actions": { + "text": "Capture Text", + "list": "Capture List", + "screenshot": "Capture Screenshot" + } + }, + "right_panel": { + "buttons": { + "capture_list": "Capture List", + "capture_text": "Capture Text", + "capture_screenshot": "Capture Screenshot", + "confirm": "Confirm", + "discard": "Discard", + "confirm_capture": "Confirm Capture", + "confirm_pagination": "Confirm", + "confirm_limit": "Confirm", + "confirm_reset": "Confirm", + "finish_capture": "Finish Capture", + "back": "Back", + "reset": "Restart Recording", + "finish": "Finish", + "cancel": "Cancel", + "delete": "Delete" + }, + "screenshot": { + "capture_fullpage": "Capture Fullpage", + "capture_visible": "Capture Visible Part", + "display_fullpage": "Take Fullpage Screenshot", + "display_visible": "Take Visible Part Screenshot" + }, + "pagination": { + "title": "How can we find the next list item on the page?", + "click_next": "Click on next to navigate to the next page", + "click_load_more": "Click on load more to load more items", + "scroll_down": "Scroll down to load more items", + "scroll_up": "Scroll up to load more items", + "none": "No more items to load" + }, + "limit": { + "title": "What is the maximum number of rows you want to extract?", + "custom": "Custom", + "enter_number": "Enter number" + }, + "fields": { + "label": "Label", + "data": "Data", + "field_label": "Field Label", + "field_data": "Field Data" + }, + "messages": { + "list_selected": "List Selected Successfully", + "list_empty": "List selected. Please select fields inside the list." + }, + "errors": { + "select_pagination": "Please select a pagination type.", + "select_pagination_element": "Please select the pagination element first.", + "select_limit": "Please select a limit or enter a custom limit.", + "invalid_limit": "Please enter a valid limit.", + "confirm_text_fields": "Please confirm all text fields", + "unable_create_settings": "Unable to create list settings. Make sure you have defined a field for the list.", + "capture_text_discarded": "Capture Text Discarded", + "capture_list_discarded": "Capture List Discarded", + "label_required": "Label cannot be empty", + "duplicate_label": "This label already exists. Please use a unique label.", + "no_text_captured": "Please highlight and select text elements before confirming.", + "capture_list_first": "Please hover over a list and select text fields inside it first", + "confirm_all_list_fields": "Please confirm all captured list fields before proceeding" + }, + "tooltips": { + "capture_list_first": "Hover over a list and select text fields inside it first", + "confirm_all_list_fields": "Please confirm all captured list fields before proceeding" + } + }, + "save_recording": { + "title": "Save Robot", + "robot_name": "Name", + "buttons": { + "save": "Save", + "confirm": "Confirm" + }, + "notifications": { + "save_success": "Robot saved successfully", + "retrain_success": "Robot retrained successfully", + "save_error": "Error saving robot" + }, + "errors": { + "user_not_logged": "User not logged in. Cannot save recording.", + "exists_warning": "Robot with this name already exists, please confirm the Robot's overwrite.", + "name_exists": "A robot with this name already exists. Please choose a different name.", + "no_actions_performed": "Cannot save robot. Please perform at least one capture action before saving." + }, + "tooltips": { + "saving": "Optimizing and saving the workflow" + } + }, + "browser_recording": { + "modal": { + "confirm_discard": "Are you sure you want to discard the recording?", + "confirm_reset": "Are you sure you want to restart the recording?", + "reset_warning": "This will clear all previous captures in the current session. The recording session will restart for the same website." + }, + "notifications": { + "terminated": "Current Recording was terminated", + "environment_reset": "Browser environment has been reset", + "reset_successful": "Successfully reset all captures and returned to initial state", + "timeout_discarded": "Recording session timed out after 10 minutes and was automatically discarded." + } + }, + "interpretation_log": { + "titles": { + "output_preview": "Output Data Preview", + "screenshot": "Screenshot" + }, + "messages": { + "additional_rows": "Additional rows of data will be extracted once you finish recording.", + "successful_training": "You've successfully trained the robot to perform actions! Click on the button below to get a preview of the data your robot will extract.", + "no_selection": "It looks like you have not selected anything for extraction yet. Once you do, the robot will show a preview of your selections here." + }, + "data_sections": { + "binary_received": "---------- Binary output data received ----------", + "serializable_received": "---------- Serializable output data received ----------", + "mimetype": "mimetype: ", + "image_below": "Image is rendered below:", + "separator": "--------------------------------------------------" + }, + "notifications": { + "reset_success": "Output Preview reset successfully" + } + }, + "interpretation_buttons": { + "buttons": { + "preview": "Get Preview of Output Data", + "reset": "Reset", + "yes": "Yes", + "no": "No" + }, + "messages": { + "extracting": "Extracting data...please wait", + "restart_required": "Please restart the interpretation after updating the recording", + "run_finished": "Run finished", + "run_failed": "Run failed to start" + }, + "modal": { + "use_previous": "Do you want to use your previous selection as a condition for performing this action?", + "previous_action": "Your previous action was: ", + "element_text": "on an element with text " + }, + "notifications": { + "reset_success": "Output Preview reset successfully" + } + }, + "recording_page": { + "loader": { + "browser_startup": "Spinning up a browser...Hold tight" + } + }, + "integration_settings": { + "title": "Integration Settings", + "descriptions": { + "authenticated_as": "Authenticated as: {{email}}" + }, + "buttons": { + "submit": "Submit", + "remove_integration": "Remove Integration" + }, + "google": { + "title": "Integrate with Google Sheet", + "descriptions": { + "sync_info": "If you enable this option, every time this robot runs a task successfully, its captured data will be appended to your Google Sheet.", + "authenticated_as": "Authenticated as: {{email}}" }, - "modal":{ - "title":"Enter the URL", - "login_title": "Does this website require logging in?", - "label":"URL", - "button":"Start Recording" + "alerts": { + "success": { + "title": "Google Sheet Integrated Successfully.", + "content": "Every time this robot creates a successful run, its captured data is appended to your {{sheetName}} Google Sheet. You can check the data updates", + "here": "here", + "note": "Note:", + "sync_limitation": "The data extracted before integrating with Google Sheets will not be synced in the Google Sheet. Only the data extracted after the integration will be synced." + } }, - "warning_modal":{ - "title":"Active Browser Detected", - "message": "There is already a browser recording session running. Would you like to discard it and create a new recording?", - "discard_and_create":"Discard & Create New", - "cancel":"Cancel" + "buttons": { + "authenticate": "Authenticate with Google", + "fetch_sheets": "Fetch Google Spreadsheets", + "remove_integration": "Remove Integration", + "submit": "Submit" + }, + "fields": { + "select_sheet": "Select Google Sheet", + "selected_sheet": "Selected Sheet: {{name}} (ID: {{id}})" + }, + "errors": { + "auth_error": "Error authenticating with Google", + "fetch_error": "Error fetching spreadsheet files: {{message}}", + "update_error": "Error updating Google Sheet ID: {{message}}", + "remove_error": "Error removing Google Sheets integration: {{message}}" }, - "retrain": "Retrain", - "edit":"Edit", - "delete":"Delete", - "duplicate":"Duplicate", - "search":"Search Robots...", "notifications": { - "delete_warning": "The robot has associated runs. First delete runs to delete the robot", - "delete_success": "Robot deleted successfully", - "auth_success": "Robot successfully authenticated", - "browser_limit_warning": "Remote browsers are currently busy. Please wait for a few minutes and try again" + "sheet_selected": "Google Sheet selected successfully", + "integration_removed": "Google Sheets integration removed successfully" } }, - "mainmenu":{ + "airtable": { + "title": "Integrate with Airtable", + "descriptions": { + "sync_info": "If you enable this option, every time this robot runs a task successfully, its captured data will be appended to your Airtable Base.", + "authenticated_as": "Authenticated with Airtable successfully. You can now select the base and table to integrate with." + }, + "alerts": { + "success": { + "title": "Airtable Base Integrated Successfully", + "content": "Every time this robot creates a successful run, its captured data is appended to your {{baseName}} Base and {{tableName}} Table. You can check updates", + "here": "here", + "note": "Note:", + "sync_limitation": "Only data captured after integration will be synced to Airtable." + } + }, + "buttons": { + "authenticate": "Connect with Airtable", + "fetch_bases": "Fetch Airtable Bases", + "fetch_tables": "Fetch Airtable Tables", + "remove_integration": "Remove Integration", + "submit": "Select Base and Table" + }, + "fields": { + "select_base": "Select Airtable Base", + "select_table": "Select Airtable Table", + "selected_base": "Selected Base: {{name}}", + "selected_table": "Selected Table: {{name}}" + }, + "errors": { + "auth_error": "Error authenticating with Airtable", + "fetch_error": "Error fetching Airtable bases: {{message}}", + "fetch_tables_error": "Error fetching Airtable tables: {{message}}", + "update_error": "Error updating Airtable base: {{message}}", + "remove_error": "Error removing Airtable integration: {{message}}" + }, + "notifications": { + "base_selected": "Airtable base selected successfully", + "table_selected": "Airtable table selected successfully", + "integration_removed": "Airtable integration removed successfully" + } + } + }, + "robot_duplication": { + "title": "Duplicate Robot", + "descriptions": { + "purpose": "Robot duplication is useful to extract data from pages with the same structure.", + "example": "Example: If you've created a robot for <0>{{url1}}, you can duplicate it to scrape similar pages like <1>{{url2}} without training a robot from scratch.", + "warning": "⚠️ Ensure the new page has the same structure as the original page." + }, + "fields": { + "target_url": "Target URL", + "new_name": "Robot Name" + }, + "buttons": { + "duplicate": "Duplicate Robot", + "cancel": "Cancel" + }, + "notifications": { + "robot_not_found": "Could not find robot details. Please try again.", + "url_required": "Target URL is required.", + "name_required": "Robot name is required.", + "duplicate_success": "Robot duplicated successfully.", + "duplicate_error": "Failed to update the Target URL. Please try again.", + "unknown_error": "An error occurred while updating the Target URL." + } + }, + "robot_settings": { + "title": "Settings", + "target_url": "Target URL", + "robot_id": "Robot ID", + "robot_limit": "Robot Limit", + "created_by_user": "Created By User", + "created_at": "Robot Created At", + "compare_runs": "Enable Monitoring", + "errors": { + "robot_not_found": "Could not find robot details. Please try again." + }, + "buttons": { + "close": "Close" + } + }, + "robot_edit": { + "title": "Edit Robot", + "change_name": "Name", + "robot_limit": "Robot Limit", + "save": "Save Changes", + "cancel": "Cancel", + "notifications": { + "update_success": "Robot updated successfully.", + "update_failed": "Failed to update the robot. Please try again.", + "update_error": "An error occurred while updating the robot." + } + }, + "schedule_settings": { + "title": "Schedule Settings", + "run_every": "Run every", + "start_from": "Start From", + "on_day": "On day", + "at_around": "At around", + "timezone": "Timezone", + "buttons": { + "delete_schedule": "Delete Schedule", + "save_schedule": "Save Schedule", + "cancel": "Cancel" + }, + "labels": { + "in_between": "In Between", + "run_once_every": "Run once every", + "start_from_label": "Start From", + "on_day_of_month": "On Day of the Month", + "on_day": { + "st": "st", + "nd": "nd", + "rd": "rd", + "th": "th" + } + } + }, + "main_page": { + "notifications": { + "interpretation_success": "Interpretation of robot {{name}} succeeded", + "interpretation_failed": "Failed to interpret robot {{name}}", + "run_started": "Running robot: {{name}}", + "run_start_failed": "Failed to run robot: {{name}}", + "schedule_success": "Robot {{name}} scheduled successfully", + "schedule_failed": "Failed to schedule robot {{name}}", + "abort_success": "Interpretation of robot {{name}} aborted successfully", + "abort_failed": "Failed to abort the interpretation of robot {{name}}", + "abort_initiated": "Aborting the interpretation of robot {{name}}" + }, + "menu": { "recordings": "Robots", "runs": "Runs", "proxy": "Proxy", - "apikey": "API Key", - "feedback":"Join Maxun Cloud", - "apidocs":"Website To API" - }, - "runstable":{ - "runs":"All Runs", - "runStatus":"Status", - "runName":"Name", - "name":"Name", - "startedAt":"Started At", - "finishedAt":"Finished At", - "delete":"Delete", - "settings":"Settings", - "search":"Search Runs...", - "sort_tooltip": "Click to sort", - "placeholder": { - "title": "No Runs Found", - "body": "This is where all your robot runs will appear. Once a robot is active, its runs will be logged here.", - "search":"No runs match your search" - }, + "apikey": "API Key" + } + }, + "browser_window": { + "attribute_modal": { + "title": "Select Attribute", "notifications": { - "no_runs": "No runs found. Please try again.", - "delete_success": "Run deleted successfully" + "list_select_success": "List has been successfully selected. Please select the text data to extract.", + "pagination_select_success": "Pagination element has been successfully selected." } }, - "proxy": { - "title": "Proxy Configuration", - "tab_standard": "Standard Proxy", - "tab_rotation": "Automatic Proxy Rotation", - "server_url": "Proxy Server URL", - "server_url_helper": "Proxy to be used for all robots. HTTP and SOCKS proxies are supported. Example http://myproxy.com:3128 or socks5://myproxy.com:3128. Short form myproxy.com:3128 is considered an HTTP proxy.", - "requires_auth": "Requires Authentication?", - "username": "Username", - "password": "Password", - "add_proxy": "Add Proxy", - "test_proxy": "Test Proxy", - "remove_proxy": "Remove Proxy", - "table": { - "proxy_url": "Proxy URL", - "requires_auth": "Requires Authentication" + "attribute_options": { + "anchor": { + "text": "Text: {{text}}", + "url": "URL: {{url}}" }, - "coming_soon": "Coming Soon - In Open Source (Basic Rotation) & Cloud (Advanced Rotation). If you don't want to manage the infrastructure, join our cloud waitlist to get early access.", - "join_waitlist": "Join Maxun Cloud Waitlist", - "alert": { - "title": "If your proxy requires a username and password, always provide them separate from the proxy URL.", - "right_way": "The right way", - "wrong_way": "The wrong way", - "proxy_url": "Proxy URL:", - "username": "Username:", - "password": "Password:" - }, - "notifications": { - "config_success": "Proxy configuration submitted successfully", - "config_error": "Failed to submit proxy configuration. Try again.", - "test_success": "Proxy configuration is working", - "test_error": "Failed to test proxy configuration. Try again.", - "fetch_success": "Proxy configuration fetched successfully", - "remove_success": "Proxy configuration removed successfully", - "remove_error": "Failed to remove proxy configuration. Try again." - } - }, - "apikey": { - "title": "Manage Your API Key", - "default_name": "Maxun API Key", - "table": { - "name": "API Key Name", - "key": "API Key", - "actions": "Actions" - }, - "actions": { - "copy": "Copy", - "show": "Show", - "hide": "Hide", - "delete": "Delete" - }, - "no_key_message": "You haven't generated an API key yet.", - "generate_button": "Generate API Key", - "notifications": { - "fetch_error": "Failed to fetch API Key - {{error}}", - "generate_success": "Generated API Key successfully", - "generate_error": "Failed to generate API Key - {{error}}", - "delete_success": "API Key deleted successfully", - "delete_error": "Failed to delete API Key - {{error}}", - "copy_success": "Copied API Key successfully" - } - }, - "action_description": { - "text": { - "title": "Capture Text", - "description": "Hover over the texts you want to extract and click to select them" - }, - "screenshot": { - "title": "Capture Screenshot", - "description": "Capture a partial or full page screenshot of the current page." - }, - "list": { - "title": "Capture List", - "description": "Hover over the list you want to extract. Once selected, you can hover over all texts inside the list you selected. Click to select them." + "image": { + "alt_text": "Alt Text: {{altText}}", + "image_url": "Image URL: {{imageUrl}}" }, "default": { - "title": "What data do you want to extract?", - "description": "A robot can perform one or multiple actions. Choose from the options listed below." - }, - "list_stages": { - "initial": "Select the list you want to extract along with the texts inside it", - "pagination": "Select how the robot can capture the rest of the list", - "limit": "Choose the number of items to extract", - "complete": "Capture is complete" - }, - "actions": { - "text": "Capture Text", - "list": "Capture List", - "screenshot": "Capture Screenshot" + "text": "Text: {{text}}" } - }, - "right_panel": { - "buttons": { - "capture_list": "Capture List", - "capture_text": "Capture Text", - "capture_screenshot": "Capture Screenshot", - "confirm": "Confirm", - "discard": "Discard", - "confirm_capture": "Confirm Capture", - "confirm_pagination": "Confirm", - "confirm_limit": "Confirm", - "confirm_reset": "Confirm", - "finish_capture": "Finish Capture", - "back": "Back", - "reset": "Restart Recording", - "finish": "Finish", - "cancel": "Cancel", - "delete": "Delete" - }, - "screenshot": { - "capture_fullpage": "Capture Fullpage", - "capture_visible": "Capture Visible Part", - "display_fullpage": "Take Fullpage Screenshot", - "display_visible": "Take Visible Part Screenshot" - }, - "pagination": { - "title": "How can we find the next list item on the page?", - "click_next": "Click on next to navigate to the next page", - "click_load_more": "Click on load more to load more items", - "scroll_down": "Scroll down to load more items", - "scroll_up": "Scroll up to load more items", - "none": "No more items to load" - }, - "limit": { - "title": "What is the maximum number of rows you want to extract?", - "custom": "Custom", - "enter_number": "Enter number" - }, - "fields": { - "label": "Label", - "data": "Data", - "field_label": "Field Label", - "field_data": "Field Data" - }, - "messages": { - "list_selected": "List Selected Successfully", - "list_empty": "List selected. Please select fields inside the list." - }, - "errors": { - "select_pagination": "Please select a pagination type.", - "select_pagination_element": "Please select the pagination element first.", - "select_limit": "Please select a limit or enter a custom limit.", - "invalid_limit": "Please enter a valid limit.", - "confirm_text_fields": "Please confirm all text fields", - "unable_create_settings": "Unable to create list settings. Make sure you have defined a field for the list.", - "capture_text_discarded": "Capture Text Discarded", - "capture_list_discarded": "Capture List Discarded", - "label_required": "Label cannot be empty", - "duplicate_label": "This label already exists. Please use a unique label.", - "no_text_captured": "Please highlight and select text elements before confirming.", - "capture_list_first": "Please hover over a list and select text fields inside it first", - "confirm_all_list_fields": "Please confirm all captured list fields before proceeding" - }, - "tooltips": { - "capture_list_first": "Hover over a list and select text fields inside it first", - "confirm_all_list_fields": "Please confirm all captured list fields before proceeding" - } - }, - "save_recording": { - "title": "Save Robot", - "robot_name": "Name", - "buttons": { - "save": "Save", - "confirm": "Confirm" - }, - "notifications": { - "save_success": "Robot saved successfully", - "retrain_success": "Robot retrained successfully", - "save_error": "Error saving robot" - }, - "errors": { - "user_not_logged": "User not logged in. Cannot save recording.", - "exists_warning": "Robot with this name already exists, please confirm the Robot's overwrite.", - "name_exists": "A robot with this name already exists. Please choose a different name.", - "no_actions_performed": "Cannot save robot. Please perform at least one capture action before saving." - }, - "tooltips": { - "saving": "Optimizing and saving the workflow" - } - }, - "browser_recording": { - "modal": { - "confirm_discard": "Are you sure you want to discard the recording?", - "confirm_reset": "Are you sure you want to restart the recording?", - "reset_warning": "This will clear all previous captures in the current session. The recording session will restart for the same website." - }, - "notifications": { - "terminated": "Current Recording was terminated", - "environment_reset": "Browser environment has been reset", - "reset_successful": "Successfully reset all captures and returned to initial state", - "timeout_discarded": "Recording session timed out after 10 minutes and was automatically discarded." - } - }, - "interpretation_log": { - "titles": { - "output_preview": "Output Data Preview", - "screenshot": "Screenshot" - }, - "messages": { - "additional_rows": "Additional rows of data will be extracted once you finish recording.", - "successful_training": "You've successfully trained the robot to perform actions! Click on the button below to get a preview of the data your robot will extract.", - "no_selection": "It looks like you have not selected anything for extraction yet. Once you do, the robot will show a preview of your selections here." - }, - "data_sections": { - "binary_received": "---------- Binary output data received ----------", - "serializable_received": "---------- Serializable output data received ----------", - "mimetype": "mimetype: ", - "image_below": "Image is rendered below:", - "separator": "--------------------------------------------------" - }, - "notifications": { - "reset_success": "Output Preview reset successfully" - } - }, - "interpretation_buttons": { - "buttons": { - "preview": "Get Preview of Output Data", - "reset": "Reset", - "yes": "Yes", - "no": "No" - }, - "messages": { - "extracting": "Extracting data...please wait", - "restart_required": "Please restart the interpretation after updating the recording", - "run_finished": "Run finished", - "run_failed": "Run failed to start" - }, - "modal": { - "use_previous": "Do you want to use your previous selection as a condition for performing this action?", - "previous_action": "Your previous action was: ", - "element_text": "on an element with text " - }, - "notifications": { - "reset_success": "Output Preview reset successfully" - } - }, - "recording_page": { - "loader": { - "browser_startup": "Spinning up a browser...Hold tight" - } - }, - "integration_settings": { - "title": "Integration Settings", - "descriptions": { - "authenticated_as": "Authenticated as: {{email}}" - }, - "buttons": { - "submit": "Submit", - "remove_integration": "Remove Integration" - }, - "google": { - "title": "Integrate with Google Sheet", - "descriptions": { - "sync_info": "If you enable this option, every time this robot runs a task successfully, its captured data will be appended to your Google Sheet.", - "authenticated_as": "Authenticated as: {{email}}" - }, - "alerts": { - "success": { - "title": "Google Sheet Integrated Successfully.", - "content": "Every time this robot creates a successful run, its captured data is appended to your {{sheetName}} Google Sheet. You can check the data updates", - "here": "here", - "note": "Note:", - "sync_limitation": "The data extracted before integrating with Google Sheets will not be synced in the Google Sheet. Only the data extracted after the integration will be synced." - } - }, - "buttons": { - "authenticate": "Authenticate with Google", - "fetch_sheets": "Fetch Google Spreadsheets", - "remove_integration": "Remove Integration", - "submit": "Submit" - }, - "fields": { - "select_sheet": "Select Google Sheet", - "selected_sheet": "Selected Sheet: {{name}} (ID: {{id}})" - }, - "errors": { - "auth_error": "Error authenticating with Google", - "fetch_error": "Error fetching spreadsheet files: {{message}}", - "update_error": "Error updating Google Sheet ID: {{message}}", - "remove_error": "Error removing Google Sheets integration: {{message}}" - }, - "notifications": { - "sheet_selected": "Google Sheet selected successfully", - "integration_removed": "Google Sheets integration removed successfully" - } - }, - "airtable": { - "title": "Integrate with Airtable", - "descriptions": { - "sync_info": "If you enable this option, every time this robot runs a task successfully, its captured data will be appended to your Airtable Base.", - "authenticated_as": "Authenticated with Airtable successfully. You can now select the base and table to integrate with." - }, - "alerts": { - "success": { - "title": "Airtable Base Integrated Successfully", - "content": "Every time this robot creates a successful run, its captured data is appended to your {{baseName}} Base and {{tableName}} Table. You can check updates", - "here": "here", - "note": "Note:", - "sync_limitation": "Only data captured after integration will be synced to Airtable." - } - }, - "buttons": { - "authenticate": "Connect with Airtable", - "fetch_bases": "Fetch Airtable Bases", - "fetch_tables": "Fetch Airtable Tables", - "remove_integration": "Remove Integration", - "submit": "Select Base and Table" - }, - "fields": { - "select_base": "Select Airtable Base", - "select_table": "Select Airtable Table", - "selected_base": "Selected Base: {{name}}", - "selected_table": "Selected Table: {{name}}" - }, - "errors": { - "auth_error": "Error authenticating with Airtable", - "fetch_error": "Error fetching Airtable bases: {{message}}", - "fetch_tables_error": "Error fetching Airtable tables: {{message}}", - "update_error": "Error updating Airtable base: {{message}}", - "remove_error": "Error removing Airtable integration: {{message}}" - }, - "notifications": { - "base_selected": "Airtable base selected successfully", - "table_selected": "Airtable table selected successfully", - "integration_removed": "Airtable integration removed successfully" - } - } - }, - "robot_duplication": { - "title": "Duplicate Robot", - "descriptions": { - "purpose": "Robot duplication is useful to extract data from pages with the same structure.", - "example": "Example: If you've created a robot for <0>{{url1}}, you can duplicate it to scrape similar pages like <1>{{url2}} without training a robot from scratch.", - "warning": "⚠️ Ensure the new page has the same structure as the original page." - }, - "fields": { - "target_url": "Target URL", - "new_name": "Robot Name" - }, - "buttons": { - "duplicate": "Duplicate Robot", - "cancel": "Cancel" - }, - "notifications": { - "robot_not_found": "Could not find robot details. Please try again.", - "url_required": "Target URL is required.", - "name_required": "Robot name is required.", - "duplicate_success": "Robot duplicated successfully.", - "duplicate_error": "Failed to update the Target URL. Please try again.", - "unknown_error": "An error occurred while updating the Target URL." - } - }, - "robot_settings": { - "title": "Settings", - "target_url": "Target URL", - "robot_id": "Robot ID", - "robot_limit": "Robot Limit", - "created_by_user": "Created By User", - "created_at": "Robot Created At", - "compare_runs": "Enable Monitoring", - "errors": { - "robot_not_found": "Could not find robot details. Please try again." - }, - "buttons": { - "close": "Close" - } - }, - "robot_edit": { - "title": "Edit Robot", - "change_name": "Name", - "robot_limit": "Robot Limit", - "save": "Save Changes", - "cancel": "Cancel", - "notifications": { - "update_success": "Robot updated successfully.", - "update_failed": "Failed to update the robot. Please try again.", - "update_error": "An error occurred while updating the robot." - } - }, - "schedule_settings": { - "title": "Schedule Settings", - "run_every": "Run every", - "start_from": "Start From", - "on_day": "On day", - "at_around": "At around", - "timezone": "Timezone", - "buttons": { - "delete_schedule": "Delete Schedule", - "save_schedule": "Save Schedule", - "cancel": "Cancel" - }, - "labels": { - "in_between": "In Between", - "run_once_every": "Run once every", - "start_from_label": "Start From", - "on_day_of_month": "On Day of the Month", - "on_day": { - "st": "st", - "nd": "nd", - "rd": "rd", - "th": "th" - } - } - }, - "main_page": { - "notifications": { - "interpretation_success": "Interpretation of robot {{name}} succeeded", - "interpretation_failed": "Failed to interpret robot {{name}}", - "run_started": "Running robot: {{name}}", - "run_start_failed": "Failed to run robot: {{name}}", - "schedule_success": "Robot {{name}} scheduled successfully", - "schedule_failed": "Failed to schedule robot {{name}}", - "abort_success": "Interpretation of robot {{name}} aborted successfully", - "abort_failed": "Failed to abort the interpretation of robot {{name}}", - "abort_initiated": "Aborting the interpretation of robot {{name}}" - }, - "menu": { - "recordings": "Robots", - "runs": "Runs", - "proxy": "Proxy", - "apikey": "API Key" - } - }, - "browser_window": { - "attribute_modal": { - "title": "Select Attribute", - "notifications": { - "list_select_success": "List has been successfully selected. Please select the text data to extract.", - "pagination_select_success": "Pagination element has been successfully selected." - } - }, - "attribute_options": { - "anchor": { - "text": "Text: {{text}}", - "url": "URL: {{url}}" - }, - "image": { - "alt_text": "Alt Text: {{altText}}", - "image_url": "Image URL: {{imageUrl}}" - }, - "default": { - "text": "Text: {{text}}" - } - } - }, - "runs_table": { - "run_type_chips": { - "manual_run": "Manual", - "scheduled_run": "Scheduled", - "api": "API", - "sdk": "SDK", - "mcp": "MCP", - "cli": "CLI", - "unknown_run_type": "Unknown Run Type" - }, - "run_status_chips": { - "success": "Success", - "running": "Running", - "scheduled": "Scheduled", - "queued": "Queued", - "failed": "Failed", - "aborted": "Aborted" - }, - "run_settings_modal": { - "title": "Run Settings", - "labels": { - "run_id": "Run ID", - "run_by_user": "Run by User", - "run_by_schedule": "Run by Schedule ID", - "run_by_api": "Run by API", - "run_type": "Run Type" - } - } - }, - "run_content": { - "tabs": { - "output_data": "Output Data", - "log": "Log" - }, - "buttons": { - "stop": "Stop" - }, - "loading": "Extracting data...", - "empty_output": "No output data available", - "captured_data": { - "title": "Captured Data", - "download_csv": "Download CSV", - "view_full": "View Full Data", - "items": "items", - "schema_title": "Captured Texts", - "list_title": "Captured Lists" - }, - "captured_screenshot": { - "title": "Captured Screenshots", - "download": "Download", - "render_failed": "Failed to render screenshot" - } - }, - "navbar": { - "project_name": "Maxun", - "notifications": { - "success": { - "logout": "Logged out successfully" - }, - "errors": { - "logout": { - "unauthorized": "You are not authorized to perform this action", - "server": "Server error occurred during logout", - "network": "Network error while logging out", - "unknown": "An unexpected error occurred during logout" - } - } - }, - "upgrade": { - "button": "Upgrade", - "modal": { - "up_to_date": "🎉 You're up to date!", - "new_version_available": "A new version is available: {{version}}. Upgrade to the latest version for bug fixes, enhancements and new features!", - "view_updates": "View all the new updates", - "view_updates_link": "here", - "tabs": { - "manual_setup": "Manual Setup Upgrade", - "docker_setup": "Docker Compose Setup Upgrade" - } - } - }, - "menu_items": { - "logout": "Logout", - "discord": "Discord", - "youtube": "YouTube", - "twitter": "Twitter (X)", - "language": "Language" - }, - "recording": { - "discard": "Discard" - } - }, - "language_menu": { - "en": "English", - "es": "Spanish", - "ja": "Japanese", - "zh": "Chinese", - "de": "German", - "tr": "Turkish", - "ko": "Korean", - "he": "Hebrew", - "az": "Azerbaijani" } -} + }, + "runs_table": { + "run_type_chips": { + "manual_run": "Manual", + "scheduled_run": "Scheduled", + "api": "API", + "sdk": "SDK", + "mcp": "MCP", + "cli": "CLI", + "unknown_run_type": "Unknown Run Type" + }, + "run_status_chips": { + "success": "Success", + "running": "Running", + "scheduled": "Scheduled", + "queued": "Queued", + "failed": "Failed", + "aborted": "Aborted" + }, + "run_settings_modal": { + "title": "Run Settings", + "labels": { + "run_id": "Run ID", + "run_by_user": "Run by User", + "run_by_schedule": "Run by Schedule ID", + "run_by_api": "Run by API", + "run_type": "Run Type" + } + } + }, + "run_content": { + "tabs": { + "output_data": "Output Data", + "log": "Log" + }, + "buttons": { + "stop": "Stop" + }, + "loading": "Extracting data...", + "empty_output": "No output data available", + "captured_data": { + "title": "Captured Data", + "download_csv": "Download CSV", + "view_full": "View Full Data", + "items": "items", + "schema_title": "Captured Texts", + "list_title": "Captured Lists" + }, + "captured_screenshot": { + "title": "Captured Screenshots", + "download": "Download", + "render_failed": "Failed to render screenshot" + } + }, + "navbar": { + "project_name": "Maxun", + "notifications": { + "success": { + "logout": "Logged out successfully" + }, + "errors": { + "logout": { + "unauthorized": "You are not authorized to perform this action", + "server": "Server error occurred during logout", + "network": "Network error while logging out", + "unknown": "An unexpected error occurred during logout" + } + } + }, + "upgrade": { + "button": "Upgrade", + "modal": { + "up_to_date": "🎉 You're up to date!", + "new_version_available": "A new version is available: {{version}}. Upgrade to the latest version for bug fixes, enhancements and new features!", + "view_updates": "View all the new updates", + "view_updates_link": "here", + "tabs": { + "manual_setup": "Manual Setup Upgrade", + "docker_setup": "Docker Compose Setup Upgrade" + } + } + }, + "menu_items": { + "logout": "Logout", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "Language" + }, + "recording": { + "discard": "Discard" + } + }, + "language_menu": { + "en": "English", + "es": "Spanish", + "ja": "Japanese", + "zh": "Chinese", + "de": "German", + "tr": "Turkish", + "ko": "Korean", + "he": "Hebrew", + "az": "Azerbaijani" + } +} \ No newline at end of file diff --git a/src/components/proxy/ProxyForm.tsx b/src/components/proxy/ProxyForm.tsx index 3c6a427a..5f960042 100644 --- a/src/components/proxy/ProxyForm.tsx +++ b/src/components/proxy/ProxyForm.tsx @@ -12,7 +12,8 @@ import { TableRow, TableBody, TableCell, - Paper + Paper, + CircularProgress } from '@mui/material'; import { sendProxyConfig, getProxyConfig, testProxyConfig, deleteProxyConfig } from '../../api/proxy'; import { useGlobalInfoStore } from '../../context/globalInfo'; @@ -37,6 +38,7 @@ const ProxyForm: React.FC = () => { const [isProxyConfigured, setIsProxyConfigured] = useState(false); const [proxy, setProxy] = useState({ proxy_url: '', auth: false }); const [recommendedProxiesAvailable, setRecommendedProxiesAvailable] = useState(false); + const [isTesting, setIsTesting] = useState(false); const { notify } = useGlobalInfoStore(); @@ -89,6 +91,7 @@ const ProxyForm: React.FC = () => { setIsProxyConfigured(true); setProxy({ proxy_url: proxyConfigForm.server_url, auth: requiresAuth }); notify('success', t('proxy.notifications.config_success')); + // Refresh the masked config silently; the success toast above already covers this action fetchProxyConfig(); } else { notify('error', t('proxy.notifications.config_error')); @@ -100,22 +103,32 @@ const ProxyForm: React.FC = () => { }; const testProxy = async () => { - await testProxyConfig().then((response) => { + if (isTesting) return; + setIsTesting(true); + try { + const response = await testProxyConfig(); if (response.success) { notify('success', t('proxy.notifications.test_success')); } else { notify('error', t('proxy.notifications.test_error')); } - }); + } catch (error: any) { + notify('error', t('proxy.notifications.test_error')); + } finally { + setIsTesting(false); + } }; - const fetchProxyConfig = async () => { + // Only notifies when explicitly asked to, so loading the page stays silent + const fetchProxyConfig = async (showNotification: boolean = false) => { try { const response = await getProxyConfig(); if (response.proxy_url) { setIsProxyConfigured(true); setProxy(response); - notify('success', t('proxy.notifications.fetch_success')); + if (showNotification) { + notify('success', t('proxy.notifications.fetch_success')); + } } } catch (error: any) { notify('error', error); @@ -204,10 +217,22 @@ const ProxyForm: React.FC = () => { - -