{ "LoginPage": { "titleAccept": "Sign in to accept", "titleWelcome": "Welcome back", "descAccept": "Sign in and we'll take you to the invitation.", "descWelcome": "Sign in to your account", "emailLabel": "Email", "emailPlaceholder": "you@example.com", "passwordLabel": "Password", "forgotPassword": "Forgot password?", "passwordPlaceholder": "Enter your password", "signingIn": "Signing in...", "signIn": "Sign in", "noAccount": "Don't have an account?", "createAccount": "Create account" }, "Sidebar": { "title": "CRM Template for WhatsApp", "dashboard": "Dashboard", "inbox": "Inbox", "notifications": "Notifications", "contacts": "Contacts", "pipelines": "Pipelines", "broadcasts": "Broadcasts", "automations": "Automations", "flows": "Flows", "aiAgents": "AI Agents", "settings": "Settings", "beta": "Beta", "unreadConversations": "{count} unread {count, plural, =1 {conversation} other {conversations}}", "unreadNotifications": "{count} unread {count, plural, =1 {notification} other {notifications}}", "roleOwner": "Owner", "roleAdmin": "Admin", "roleAgent": "Agent", "roleViewer": "Viewer", "closeMenu": "Close menu", "defaultUser": "User", "defaultAvatar": "Avatar", "menuProfile": "Profile", "menuSettings": "Settings", "menuSignOut": "Sign out" }, "Header": { "dashboard": "Dashboard", "inbox": "Inbox", "notifications": "Notifications", "contacts": "Contacts", "pipelines": "Pipelines", "broadcasts": "Broadcasts", "automations": "Automations", "settings": "Settings", "openMenu": "Open menu", "openAccountMenu": "Open account menu", "defaultUser": "User", "defaultAvatar": "Avatar", "menuProfile": "Profile", "menuSettings": "Settings", "menuSignOut": "Sign out" }, "ModeToggle": { "switchMode": "Switch to {mode} mode" }, "Dashboard": { "page": { "title": "Dashboard", "description": "Live analytics across conversations, contacts, deals, broadcasts, and automations.", "activeConversations": "Active Conversations", "newContactsToday": "New Contacts Today", "openDealsValue": "Open Deals Value", "messagesSentToday": "Messages Sent Today", "newTodayVsYesterday": "new today vs yesterday", "vsYesterday": "vs yesterday", "openDeals": "{count} open {count, plural, =1 {deal} other {deals}}", "noChange": "No change {suffix}" }, "quickActions": { "newContact": "New Contact", "newDeal": "New Deal", "newBroadcast": "New Broadcast", "newAutomation": "New Automation" }, "activityFeed": { "title": "Recent Activity", "viewAll": "View all →", "noActivity": "No activity yet", "noActivityHint": "Activity from messages, deals, broadcasts, and automations will appear here.", "showingOf": "Showing {visible} of {totalLoaded}{plus}", "show": "Show", "timeS": "{sec}s ago", "timeM": "{min}m ago", "timeH": "{hr}h ago", "timeD": "{day}d ago" }, "conversationsChart": { "title": "Conversations Over Time", "description": "Daily message volume by direction", "days": "{count} days", "noActivity": "No message activity in this range", "noActivityHint": "Send or receive messages to start populating this chart.", "incoming": "Incoming", "outgoing": "Outgoing", "tooltipIncoming": "{count} incoming", "tooltipOutgoing": "{count} outgoing", "ariaLabel": "Conversations per day" }, "pipelineDonut": { "title": "Pipeline Value", "description": "Open deals by stage", "noOpenDeals": "No open deals yet", "noOpenDealsHint": "Create deals in Pipelines to see stage breakdowns here.", "dealCount": "{count} {count, plural, =1 {deal} other {deals}}", "total": "Total", "ariaLabel": "Pipeline value by stage" }, "responseTimeChart": { "title": "Average First Response Time", "description": "Minutes to reply to a customer's first unreplied message, by weekday", "target": "target {minutes}m", "thisWeek": "This week:", "lastWeek": "Last week:", "noReplies": "No replies recorded yet", "noRepliesHint": "This chart fills in as you reply to customer messages." }, "emptyState": { "title": "Not enough data yet" } }, "Inbox": { "page": { "whatsappNotConnected": "WhatsApp® is not connected. Go to Settings to connect your account." }, "conversationList": { "searchPlaceholder": "Search conversations...", "filterAll": "All", "filterUnread": "Unread", "filterOpen": "Open", "filterPending": "Pending", "filterClosed": "Closed", "tags": "Tags", "company": "Company", "allCompanies": "All companies", "clearAll": "Clear all", "noConversations": "No conversations found", "noMessagesYet": "No messages yet", "unknown": "Unknown" }, "messageThread": { "backToConversations": "Back to conversations", "hideContactPanel": "Hide contact panel", "showContactPanel": "Show contact panel", "hideContact": "Hide contact", "showContact": "Show contact", "refresh": "Refresh", "refreshConversation": "Refresh conversation", "status": "Status", "statusOpen": "Open", "statusPending": "Pending", "statusClosed": "Closed", "assign": "Assign", "assigned": "Assigned", "unassign": "Unassign", "noTeammates": "No teammates available", "me": " (me)", "noMessagesYet": "No messages yet", "sendTemplateHint": "Send a template to start the conversation", "selectConversation": "Select a conversation", "selectConversationHint": "Choose a conversation from the left to start messaging", "today": "Today", "yesterday": "Yesterday" }, "sessionTimer": { "expired": "Expired", "xhRemaining": "{hours}h remaining", "xmRemaining": "{minutes}m remaining", "noCustomerMessages": "No customer messages" }, "composer": { "draftHint": "Tap the ✨ to draft a reply with AI — you can edit it before sending", "sessionExpiredHint": "24-hour session expired. Use a template to re-engage.", "templates": "Templates", "readOnlyPlaceholder": "Read-only — viewers can browse but not reply", "sessionExpiredPlaceholder": "Session expired - use a template", "typeMessagePlaceholder": "Type a message... (Shift+Enter for new line)", "readOnlyTitle": "Read-only — your role can't send messages", "recording": "Recording… {current} / {max}", "cancel": "Cancel", "stopAndAttach": "Stop and attach", "attachMedia": "Attach media", "photo": "Photo", "video": "Video", "document": "Document", "voiceNote": "Voice note", "sendTemplate": "Send template", "draftWithAI": "Draft a reply with AI", "addCaption": "Add a caption…", "removeAttachment": "Remove attachment", "moreActions": "More", "interactiveMessage": "Interactive message", "quickReplies": "Quick replies", "quickRepliesEmpty": "No quick replies yet. Add some in Settings → Quick replies.", "saveAsQuickReply": "Save as quick reply", "send": "Send", "quickReplyNamePrompt": "Name this quick reply:", "quickReplySaved": "Saved as a quick reply.", "quickReplySaveError": "Couldn't save the quick reply." }, "bubble": { "photo": "Photo", "video": "Video", "audio": "Audio", "unavailable": "{label} unavailable", "document": "Document", "locationShared": "Location shared", "template": "Template", "buttonReply": "Button reply", "interactiveReply": "[Interactive reply]", "unsupported": "[Unsupported message type]", "aiBadge": "AI", "aiBadgeTitle": "Sent automatically by the AI assistant" }, "actions": { "reply": "Reply", "copyText": "Copy text", "delete": "Delete", "react": "React", "reactWith": "React with {emoji}", "nothingToCopy": "Nothing to copy", "copied": "Copied", "copyFailed": "Copy failed" }, "replyQuote": { "photo": "[Photo]", "video": "[Video]", "document": "[Document]", "audio": "[Audio]", "voiceMessage": "[Voice message]", "location": "[Location]", "template": "[Template]", "message": "[Message]", "cancelReply": "Cancel reply" }, "templatePicker": { "sendTemplate": "Send template", "fillPlaceholders": "Fill in the placeholders to render this template. Meta requires every variable to be set.", "pickTemplate": "Pick an approved WhatsApp template to send to this contact.", "noApprovedTemplates": "No approved templates", "noApprovedTemplatesHint": "Approve a template in Meta WhatsApp Manager, then sync it from Settings → Templates.", "preview": "Preview", "headerValuePlaceholder": "Value for the header variable", "bodyValuePlaceholder": "Value for {val}", "urlSuffixValuePlaceholder": "URL suffix value", "finalUrl": "Final URL: {url}", "back": "Back", "cancel": "Cancel", "send": "Send template" }, "sidebar": { "contactInfo": "Contact info", "tags": "Tags", "notes": "Notes", "deals": "Deals", "noTags": "No tags", "noDeals": "No deals", "addNotePlaceholder": "Add a note..." }, "aiBanner": { "pausedTitle": "AI assistant is paused here", "activeText": "AI assistant is replying automatically", "takeOver": "Take over", "resume": "Resume AI", "tookOver": "You’ve taken over this chat.", "resumed": "AI resumed.", "updateError": "Couldn’t update the AI assistant.", "networkError": "Couldn’t reach the server." } }, "Contacts": { "page": { "title": "Contacts", "subtitle": "Manage your contact list. {count} total contacts.", "subtitleZero": "Manage your contact list.", "customFieldsBtn": "Custom fields", "importBtn": "Import", "addContactBtn": "Add Contact", "searchPlaceholder": "Search by name, phone, or email...", "filterByTags": "Filter by tags", "clearAll": "Clear all", "noTagsYet": "No tags yet.", "selectedCount": "{count} selected", "clearSelection": "Clear", "deleteSelected": "Delete selected", "tableColumns": { "name": "Name", "phone": "Phone", "email": "Email", "company": "Company", "tags": "Tags", "createdAt": "Created" }, "loading": "Loading contacts...", "noContactsMatch": "No contacts match your filters.", "noContactsYet": "No contacts yet.", "addFirstContact": "Add your first contact", "unnamed": "Unnamed", "editAction": "Edit", "deleteAction": "Delete", "showingPagination": "Showing {start}-{end} of {total}", "pageCount": "Page {page} of {total}", "deleteContactTitle": "Delete Contact", "deleteContactDesc": "Are you sure you want to delete {name}? This action cannot be undone.", "cancel": "Cancel", "deleteBtn": "Delete", "deleteBulkTitle": "Delete Contacts", "deleteBulkDesc": "Are you sure you want to delete {count} selected contacts? This action cannot be undone.", "toastFailedLoad": "Failed to load contacts", "toastFailedDelete": "Failed to delete contact", "toastDeleted": "Contact deleted", "toastBulkFailedDelete": "Failed to delete contacts", "toastBulkDeleted": "{count} contacts deleted" }, "form": { "addTitle": "Add Contact", "addDesc": "Create a new contact. Name is required.", "editTitle": "Edit Contact", "editDesc": "Update contact details and tags.", "nameLabel": "Name", "namePlaceholder": "Jane Doe", "phoneLabel": "Phone Number", "phonePlaceholder": "+1234567890", "phoneHint": "Include country code, e.g. +1 for US", "emailLabel": "Email", "emailPlaceholder": "jane@example.com", "companyLabel": "Company", "companyPlaceholder": "Acme Corp", "tagsLabel": "Tags", "tagsPlaceholder": "Select tags...", "noTagsFound": "No tags found.", "createTagAction": "Create tag \"{value}\"", "cancel": "Cancel", "save": "Save Contact", "update": "Update", "create": "Create", "toastSuccessAdd": "Contact created successfully", "toastSuccessEdit": "Contact updated successfully", "toastError": "Failed to save contact", "toastConflict": "A contact with this phone number already exists", "viewExisting": "View {name}", "dupExact": "A contact with this phone number already exists.", "dupSimilar": "A contact with a very similar number already exists.", "loadingTags": "Loading tags...", "noTagsAvailable": "No tags available. Create tags in Settings.", "phoneRequired": "Phone number is required" }, "detailView": { "tabs": { "details": "Details", "activity": "Activity", "notes": "Notes", "custom": "Custom Fields", "deals": "Deals", "tags": "Tags", "noTags": "No tags", "noDeals": "No deals", "addNotePlaceholder": "Add a note..." }, "actions": { "edit": "Edit", "message": "Message", "delete": "Delete" }, "contactInfo": "Contact Information", "unnamed": "Unknown", "contactDetailsDesc": "Contact details", "phone": "Phone", "email": "Email", "company": "Company", "createdAt": "Created At", "customFields": "Custom Fields", "noCustomFields": "No custom fields defined. Create them in Settings.", "manageFields": "Manage fields", "enterCustomField": "Enter {name}...", "activityTab": { "title": "Activity History", "noActivity": "No activity yet." }, "notesTab": { "title": "Internal Notes", "placeholder": "Write a note...", "save": "Add Note", "noNotes": "No notes yet." }, "dealsTab": { "noDeals": "No deals yet" }, "tagsTab": { "clickTagDesc": "Click a tag to add or remove it from this contact.", "noTagsAvailable": "No tags available. Create tags in Settings." }, "sendTemplateBtn": "Send template", "saveChangesBtn": "Save Changes", "saveCustomFieldsBtn": "Save Custom Fields", "toastPhoneRequired": "Phone number is required", "toastUpdateFailed": "Failed to update contact", "toastUpdated": "Contact updated", "toastNotAuthenticated": "Not authenticated", "toastNoteAddFailed": "Failed to add note", "toastNoteAdded": "Note added", "toastNoteDeleteFailed": "Failed to delete note", "toastNoteDeleted": "Note deleted", "toastCustomFieldsSaved": "Custom fields saved", "toastCustomFieldsFailed": "Failed to save custom fields", "toastTemplateSent": "Template \"{name}\" sent", "toastTemplateFailed": "Failed to send template: {reason}" }, "importModal": { "title": "Import Contacts", "desc": "Upload a CSV with a required phone column. Optional: name, email, company, tags (comma-separated; quote multi-tag cells).", "uploadDropzone": "Click to choose a CSV file", "uploadHint": ".csv up to your browser limit", "rowsReady": "{count} row ready", "rowsReady_plural": "{count} rows ready", "preview": "Preview · first {count}", "previewTags": "{tags} tag · {contacts} contact", "previewTags_plural": "{tags} tags · {contacts} contacts", "moreRows": "+ {count} more row not shown", "moreRows_plural": "+ {count} more rows not shown", "importComplete": "Import complete", "resultImported": "{count} imported", "resultTags": "{count} tag assigned", "resultTags_plural": "{count} tags assigned", "resultSkipped": "{count} skipped", "resultFailed": "{count} failed", "willBeCreated": "{name} (will be created on import)", "columns": { "phone": "Phone", "name": "Name", "email": "Email", "company": "Company", "tags": "Tags" }, "cancel": "Cancel", "close": "Close", "importBtn": "Import {count} contact", "importBtn_plural": "Import {count} contacts", "toastNoValidRows": "No valid rows found. Ensure CSV has a \"phone\" column header.", "toastTagsWarning": "Contacts imported, but some tag assignments failed.", "toastImported": "{count} contact imported", "toastImported_plural": "{count} contacts imported", "toastTagsAssigned": "{count} tag assignment applied", "toastTagsAssigned_plural": "{count} tag assignments applied", "toastTagsSkipped": "Unknown tags skipped (create them in Settings first): {sample}{more}", "toastSkipped": "{count} duplicate skipped", "toastSkipped_plural": "{count} duplicates skipped", "toastFailed": "{count} contact failed to import", "toastFailed_plural": "{count} contacts failed to import", "toastError": "Import failed" }, "customFields": { "title": "Custom fields", "desc": "Define extra contact fields (e.g. ZIP code, lead source). They appear on every contact and in the “Update Contact Field” automation action.", "addField": "Add", "fieldName": "New field name…", "loading": "Loading…", "empty": "No custom fields yet.", "renameAria": "Rename {name}", "deleteTitle": "Delete field", "deleteConfirm": "Delete \"{name}\"? This also removes its stored value on every contact. This cannot be undone.", "toastNoAccount": "Your profile is not linked to an account.", "toastDuplicate": "A field named \"{name}\" already exists.", "toastCreateFailed": "Could not create field. You may not have permission.", "toastCreated": "Created \"{name}\".", "toastRenameFailed": "Could not rename field.", "toastDeleteFailed": "Could not delete field.", "toastDeleted": "Deleted \"{name}\"." } }, "Pipelines": { "page": { "selectPipeline": "Select Pipeline", "noPipelinesYet": "No pipelines yet", "managePipelines": "Manage Pipelines", "addPipeline": "Add Pipeline", "addDeal": "Add Deal", "createToStartTracking": "Create a pipeline to start tracking deals", "createPipeline": "Create Pipeline", "newPipeline": "New Pipeline", "pipelineName": "Pipeline Name", "pipelineNamePlaceholder": "e.g., Enterprise Sales", "defaultStagesDesc": "Default stages (New Lead → Won) will be created automatically.", "cancel": "Cancel", "creating": "Creating...", "createPipelineBtn": "Create Pipeline", "toastFailedLoadPipelines": "Failed to load pipelines", "toastFailedMoveDeal": "Failed to move deal", "toastFailedCreatePipeline": "Failed to create pipeline", "toastPipelineCreated": "Pipeline created", "toastNotLinkedToAccount": "Your profile is not linked to an account." }, "board": { "dropDealHere": "Drop a deal here", "addDeal": "Add Deal" }, "card": { "noContact": "No contact", "won": "Won", "lost": "Lost" }, "form": { "editDeal": "Edit Deal", "newDeal": "New Deal", "title": "Title", "titlePlaceholder": "Deal title", "contact": "Contact", "selectContact": "Select a contact", "linkToConversation": "Link to Conversation", "value": "Value", "currency": "Currency", "expectedCloseDate": "Expected Close Date", "stage": "Stage", "assignedTo": "Assigned To", "unassigned": "Unassigned", "notes": "Notes", "notesPlaceholder": "Add notes...", "status": "Status", "markAsWon": "Mark as Won", "markAsLost": "Mark as Lost", "reopenDeal": "Reopen deal", "cancel": "Cancel", "saving": "Saving...", "saveChanges": "Save Changes", "createDeal": "Create Deal", "deletePrompt": "Delete this deal?", "confirm": "Confirm", "deleting": "Deleting...", "deleteDeal": "Delete Deal", "toastRequired": "Title, contact, and stage are required", "toastFailedSave": "Failed to save deal", "toastNotSignedIn": "Not signed in", "toastNotLinked": "Your profile is not linked to an account.", "toastFailedCreate": "Failed to create deal", "toastUpdated": "Deal updated", "toastCreated": "Deal created", "toastFailedStatus": "Failed to update deal status", "toastMarkedWon": "Marked as won", "toastMarkedLost": "Marked as lost", "toastReopened": "Deal reopened", "toastFailedDelete": "Failed to delete deal", "toastDeleted": "Deal deleted" }, "settings": { "managePipeline": "Manage Pipeline", "deletePipeline": "Delete Pipeline", "deletePipelineDesc": "This will archive all deals in this pipeline. This cannot be undone.", "cancel": "Cancel", "deleting": "Deleting...", "deletePipelineBtn": "Delete Pipeline", "pipelineName": "Pipeline Name", "stages": "Stages", "newStageNamePlaceholder": "New stage name", "add": "Add", "createNewPipeline": "Create a new pipeline", "saving": "Saving...", "saveChanges": "Save Changes", "dragToReorder": "Drag to reorder", "changeColor": "Change color", "toastFailedSave": "Failed to save pipeline", "toastSaved": "Pipeline saved", "toastFailedAddStage": "Failed to add stage", "toastMoveOrDeleteDeals": "Move or delete deals in this stage first", "toastFailedDeleteStage": "Failed to delete stage", "toastFailedDeletePipeline": "Failed to delete pipeline", "toastDeleted": "Pipeline deleted" }, "analytics": { "totalDeals": "Total Deals", "totalDealsTooltip": "Count of every deal in this pipeline that isn't marked as Lost. Won deals are still included.", "pipelineValue": "Pipeline Value", "pipelineValueTooltip": "Sum of the dollar values of all deals in this pipeline, excluding deals marked as Lost.", "avgDealSize": "Avg Deal Size", "avgDealSizeTooltip": "Pipeline Value divided by Total Deals — the average value of a single non-lost deal.", "weightedValue": "Weighted Value", "weightedValueTooltip": "Expected revenue: each open deal's value × its stage probability. First stage ≈ 10%, stages progress up to 90%, Won = 100%. Lost deals are excluded.", "wonThisMonth": "Won This Month", "wonThisMonthTooltip": "Deals marked as Won since the first day of the current month.", "lostThisMonth": "Lost This Month", "lostThisMonthTooltip": "Deals marked as Lost since the first day of the current month.", "howCalculated": "How {label} is calculated" } }, "Broadcasts": { "page": { "title": "Broadcasts", "subtitle": "Send bulk messages to your contacts using approved templates.", "newBroadcast": "New Broadcast", "noBroadcastsYet": "No broadcasts yet", "createFirst": "Create your first broadcast to reach your contacts at scale.", "table": { "name": "Name", "template": "Template", "recipients": "Recipients", "delivery": "Delivery", "read": "Read", "status": "Status", "date": "Date" }, "errorLoad": "Failed to load broadcasts", "retry": "Retry" }, "status": { "draft": "Draft", "scheduled": "Scheduled", "sending": "Sending", "sent": "Sent", "failed": "Failed", "pending": "Pending", "delivered": "Delivered", "read": "Read", "replied": "Replied", "unknown": "Unknown" }, "detail": { "backToBroadcasts": "Back to Broadcasts", "notFound": "Broadcast not found", "template": "Template: {name}", "createdAt": "Created {date}", "deletePrompt": "Delete this broadcast?", "cancel": "Cancel", "confirm": "Confirm", "deleting": "Deleting…", "delete": "Delete", "cannotDeleteSending": "Cannot delete while a broadcast is actively sending", "deleteHover": "Delete this broadcast", "funnel": "Funnel", "recipientsHeader": "Recipients ({filtered} of {total})", "recipientsHeaderAll": "Recipients ({total})", "allStatuses": "All statuses", "exportCsv": "Export CSV", "noRecipients": "No recipients found.", "noRecipientsFilter": "No recipients match this filter.", "table": { "contact": "Contact", "phone": "Phone", "status": "Status", "sent": "Sent", "delivered": "Delivered", "read": "Read", "error": "Error" }, "stats": { "totalRecipients": "Total Recipients", "sent": "Sent", "delivered": "Delivered", "read": "Read", "replied": "Replied", "failed": "Failed" }, "toastFailedDelete": "Failed to delete: {error}", "toastDeleted": "Broadcast deleted" }, "new": { "title": "New Broadcast", "subtitle": "Create and send a broadcast message to your contacts.", "steps": { "template": "Template", "audience": "Audience", "personalize": "Personalize", "send": "Send" }, "toastGiveName": "Give the broadcast a name before saving a draft.", "toastNotSignedIn": "Not signed in.", "toastNotLinked": "Your profile is not linked to an account.", "toastFailedDraft": "Failed to save draft: {error}", "toastDraftSaved": "Draft saved" }, "wizard": { "next": "Next", "back": "Back", "cancel": "Cancel", "chooseTemplate": { "title": "Choose a Template", "subtitle": "Select an approved message template for your broadcast.", "noTemplates": "No templates available.", "createFirst": "Create a template in Settings first.", "errorLoad": "Failed to load templates" }, "selectAudience": { "title": "Select Audience", "subtitle": "Choose who will receive this broadcast.", "method": { "all": "All Contacts", "tags": "Filter by Tags", "customField": "Custom Field", "csv": "Upload CSV" }, "allDesc": "Send to all {count} contacts in your database.", "allDescLoading": "Send to all contacts in your database.", "tagDesc": "Send to contacts matching specific tags.", "customFieldDesc": "Send to contacts matching a custom field rule.", "csvDesc": "Upload a CSV with phone numbers (and optional names).", "selectTags": "Select Tags", "searchTags": "Search tags...", "noTagsFound": "No tags found.", "excludeTags": "Exclude Tags (Optional)", "searchExcludeTags": "Search tags to exclude...", "field": "Field", "selectField": "Select a field...", "operator": "Operator", "operatorIs": "Is", "operatorIsNot": "Is not", "operatorContains": "Contains", "value": "Value", "valuePlaceholder": "Value to match", "uploadCsv": "Upload CSV File", "csvFormatDesc": "Must contain a 'phone' column (E.164 format). 'name' column is optional.", "csvContactsFound": "{count} valid contact(s) found in CSV.", "errorLoadTags": "Failed to load tags", "errorLoadFields": "Failed to load custom fields", "errorCsvParse": "Could not parse CSV file.", "errorCsvMissingPhone": "CSV must have a 'phone' column." }, "personalize": { "title": "Personalize Variables", "subtitle": "Map your template variables to contact fields or provide static values.", "headerImage": "Header Image", "headerImageDesc": "This template requires a header image.", "imageUrl": "Image URL", "imageUrlPlaceholder": "https://example.com/image.jpg", "variables": "Variables", "varDesc": "Set values for {{name}}", "type": "Type", "typeStatic": "Static Value", "typeContact": "Contact Field", "typeCustom": "Custom Field", "staticValue": "Static Value", "contactField": "Contact Field", "selectContactField": "Select field...", "customField": "Custom Field", "selectCustomField": "Select custom field...", "preview": "Preview", "previewSample": "Showing preview with sample data.", "noPreview": "Preview not available.", "fieldMap": { "name": "Name", "phone": "Phone", "email": "Email" } }, "scheduleSend": { "title": "Review & Send", "subtitle": "Give your broadcast a name and confirm sending.", "broadcastName": "Broadcast Name", "broadcastNamePlaceholder": "e.g., Summer Promo", "summary": "Summary", "template": "Template:", "audience": "Audience:", "audienceAll": "All contacts", "audienceTags": "Filtered by tags", "audienceField": "Filtered by custom field", "audienceCsv": "CSV upload", "variables": "Variables:", "variablesMapped": "{count} mapped", "saveDraft": "Save as Draft", "sendNow": "Send Broadcast", "sending": "Sending...", "preparing": "Preparing...", "progressDesc": "Processing {current} of {total} recipients...", "toastFailedPreview": "Failed to load preview data" } } }, "Automations": { "list": { "title": "Automations", "subtitle": "Build workflows that react to WhatsApp® events automatically.", "create": "Create Automation", "retry": "Retry", "templatesTitle": "Quick-start templates", "emptyTitle": "No automations yet", "emptyDesc": "Pick a template above or create one from scratch.", "runs": "{count} run", "runsPlural": "{count} runs", "lastRun": "last {time}", "activate": "Activate", "deactivate": "Deactivate", "edit": "Edit", "duplicate": "Duplicate", "viewLogs": "View Logs", "delete": "Delete", "cancel": "Cancel", "deleteTitle": "Delete automation", "deleteDesc": "This permanently removes {name} and its execution history. This cannot be undone.", "toasts": { "activated": "Automation activated", "paused": "Automation paused", "duplicated": "Automation duplicated", "deleted": "Automation deleted", "updateError": "Failed to update", "duplicateError": "Failed to duplicate", "deleteError": "Failed to delete" } }, "edit": { "loading": "Loading...", "loadError": "Failed to load ({status})", "back": "Back to Automations" }, "logs": { "title": "Execution logs", "loadError": "Failed to load logs", "emptyTitle": "No executions yet", "emptyDesc": "Trigger this automation to see runs here.", "unknownContact": "Unknown contact", "step": "{count} step", "stepPlural": "{count} steps", "noSteps": "No steps recorded.", "status": { "success": "success", "partial": "partial", "failed": "failed" }, "back": "Back", "backAria": "Back" }, "builder": { "steps": { "send_message": "Send Message", "send_buttons": "Send Buttons", "send_list": "Send List", "send_template": "Send Template", "add_tag": "Add Tag", "remove_tag": "Remove Tag", "assign_conversation": "Assign Conversation", "update_contact_field": "Update Contact Field", "create_deal": "Create Deal", "wait": "Wait", "condition": "Condition (If/Else)", "send_webhook": "Send Webhook", "close_conversation": "Close Conversation" }, "triggers": { "new_message_received": { "label": "New Message Received", "hint": "Any incoming message" }, "first_inbound_message": { "label": "First Message from Contact", "hint": "First time this contact ever messages you (works for manually-added contacts too)" }, "keyword_match": { "label": "Keyword Match", "hint": "Message contains specific keyword(s)" }, "interactive_reply": { "label": "Button / List Reply", "hint": "Customer taps a button or list row whose id matches — chain menus across automations" }, "new_contact_created": { "label": "New Contact Created", "hint": "When a contact is auto-created from an incoming message" }, "conversation_assigned": { "label": "Conversation Assigned", "hint": "When assigned to an agent" }, "tag_added": { "label": "Tag Added", "hint": "When a tag is added to a contact" }, "time_based": { "label": "Time-Based", "hint": "On a recurring schedule" } }, "trigger": "Trigger", "triggerType": "Trigger type", "keywords": "Keywords", "keywordsHint": "Comma-separated list (e.g. hello, help, buy)", "replyIds": "Reply IDs", "replyIdsHint": "yes, no, more_info", "replyIdsHelp": "Comma-separated button/list-row ids to match, exact. Use the same ids you set on a Send Buttons / Send List step.", "schedule": "Schedule", "scheduleHint": "Cron expression (e.g. 0 9 * * 1-5)", "active": "Active", "activeAria": "Active", "save": "Save", "saveDraft": "Save Draft", "untitled": "Untitled automation", "backToAutomations": "Back to automations", "toasts": { "saved": "Automation saved", "created": "Automation created", "saveFailed": "Save failed" }, "tags": { "select": "Select a tag…", "placeholder": "Tag id", "unknown": "{id} (unknown tag)" }, "fields": { "name": "Name", "email": "Email", "company": "Company", "customFields": "Custom fields", "unknown": "{id} (unknown field)" }, "agents": { "select": "Select an agent…", "placeholder": "Agent id", "unknown": "{id} (unknown agent)" }, "pipelines": { "pipelineLabel": "Pipeline", "pipelineIdLabel": "Pipeline id", "stageLabel": "Stage", "stageIdLabel": "Stage id", "selectPipeline": "Select a pipeline…", "selectStage": "Select a stage…", "selectPipelineFirst": "Select a pipeline first…", "unknownPipeline": "{id} (unknown pipeline)", "unknownStage": "{id} (unknown stage)" }, "templates": { "templateLabel": "Template", "templateNameLabel": "Template name", "languageLabel": "Language", "select": "Select a template…", "unknown": "{name} ({lang}) — not in approved list", "unknownLang": "unknown" }, "branches": { "yes": "Yes", "no": "No" }, "addStep": "Add step", "config": { "messageText": "Message text", "placeholderMessageText": "Hi! Thanks for reaching out…", "tagLabel": "Tag", "modeLabel": "Mode", "modes": { "round_robin": "Round-robin", "specific": "Specific agent" }, "agentLabel": "Agent", "fieldLabel": "Field", "valueLabel": "Value", "placeholderValue": "Text or {{ vars.x }} / {{ message.text }}", "titleLabel": "Title", "amountLabel": "Amount", "unitLabel": "Unit", "units": { "minutes": "Minutes", "hours": "Hours", "days": "Days" }, "subjectLabel": "Subject", "subjects": { "tag_presence": "Tag presence", "contact_field": "Contact field", "message_content": "Message content", "time_of_day": "Time of day" }, "operandLabel": "Operand", "placeholderTime": "HH:mm-HH:mm", "placeholderContact": "name / email / company", "placeholderTag": "tag id", "urlLabel": "URL", "headersLabel": "Headers", "placeholderHeaders": "{\"Authorization\": \"Bearer ...\"}", "bodyTemplateLabel": "Body template", "placeholderBody": "{\"id\": \"{{ contact.id }}\"}", "matchType": "Match type", "matchContains": "Contains", "matchExact": "Exact", "closeConversationHint": "Sets the conversation status to \"closed\". No configuration needed." } } }, "Flows": { "list": { "title": "Flows", "beta": "Beta", "description": "Build branching, button-driven WhatsApp conversations. Useful for menus, FAQs, and triage before a human steps in.", "newFlow": "New flow", "statusDraft": "Draft", "statusActive": "Active", "statusArchived": "Archived", "loadError": "Couldn't load flows.", "createError": "Couldn't create flow.", "cloneError": "Clone failed", "deleteConfirm": "Delete \"{name}\"? Any active runs will end immediately.", "deleteSuccess": "Flow deleted.", "deleteError": "Couldn't delete flow.", "emptyTitle": "No flows yet", "emptyDesc": "Build your first conversation — a welcome menu, an order lookup, an FAQ bot. Customers tap buttons; the bot routes them to the right answer (or the right agent).", "createFirst": "Create your first flow", "createTitle": "Create a new flow", "createDesc": "Start from a template or build from scratch.", "startTemplate": "Start from a template", "nodeCount": "{count} {count, plural, =1 {node} other {nodes}}", "startBlank": "Or start blank", "placeholderName": "e.g. Welcome menu", "cancel": "Cancel", "createBlank": "Create blank flow", "runCount": "{count} {count, plural, =1 {run} other {runs}}", "edit": "Edit", "delete": "Delete", "triggerKeywordNone": "Triggers on keyword (none set)", "triggerKeyword": "Triggers on: {keywords}", "triggerFirstInbound": "Triggers on a contact's first-ever inbound message", "triggerManual": "Manual trigger" }, "edit": { "notFound": "Flow not found.", "backToFlows": "← Back to flows", "loadError": "Couldn't load flow." }, "logs": { "title": "Runs", "description": "The 50 most recent times this flow ran. Expand a row to see the engine's per-step log.", "emptyState": "No runs yet. Trigger the flow from a personal WhatsApp number to see it appear here.", "loadError": "Couldn't load runs.", "unknownContact": "Unknown contact", "atNode": "at {node}", "started": "Started {time}", "reprompts": "{count} re-prompts", "ranFor": "ran for {duration}", "capturedVars": "Captured vars ({count})", "noEvents": "No events recorded for this run.", "statusActive": "Active", "statusCompleted": "Completed", "statusHandedOff": "Handed off", "statusTimedOut": "Timed out", "statusPaused": "Paused by agent", "statusFailed": "Failed" }, "builder": { "triggerTitle": "Trigger", "whenLabel": "When…", "triggerKeywordTitle": "A message contains a keyword", "triggerFirstInboundTitle": "Customer's first ever inbound message", "triggerManualTitle": "Manual only (no auto-trigger)", "keywordsLabel": "Keywords (comma-separated)", "keywordsPlaceholder": "support, help, hi", "entryNodeTitle": "Entry node:", "entryNodePlaceholder": "Pick the first node…", "nodesTitle": "Nodes ({count})", "nodesEmpty": "Add a Start node, then a Send buttons node, then a Handoff — that's the welcome-menu shape from the brief.", "addNode": "Add node", "setAsEntry": "Set as entry", "removeNode": "Remove node", "showAdvanced": "Show advanced", "hideAdvanced": "Hide advanced", "nodeKeyLabel": "Node key (internal identifier — keep stable for analytics)", "replyIdsHint": "Reply IDs for each option are shown inline above. They're returned by WhatsApp when a customer taps; you usually don't need to touch them.", "badgeEntry": "Entry", "noNodesYet": "No nodes yet.", "deleteNode": "Delete node", "canvasView": "Canvas", "listView": "List", "noNodeSelected": "No node selected", "noNodeDesc": "Select a node on the canvas to edit its configuration.", "form": { "advancesTo": "Advances to", "textToCustomer": "Text sent to the customer", "promptToCustomer": "Prompt sent to the customer", "varKeyLabel": "Variable key (stored in flow_runs.vars; alphanumeric + underscore)", "varKeyPlaceholder": "e.g. name, email, company", "varKeyHelp": "Interpolate in downstream prompts and handoff notes with", "advanceAfterCapture": "After capturing, advance to", "internalNote": "Internal note (for the agent picking up)", "endNodeHelp": "Terminal node. When the runner reaches this node the run is marked complete. No config needed.", "bodyText": "Body text", "footerText": "Footer (optional, 60 chars)", "buttonsHelp": "Buttons (1–3) — each one routes to a different next node", "optionTitlePlaceholder": "Visible title (≤20 chars)", "nextNodePlaceholder": "Next node…", "addButton": "Add button", "buttonLabel": "Tap-to-expand button label (≤20 chars)", "rowsHelp": "Rows (1–10 total across all sections)", "sectionTitlePlaceholder": "Section {count} title (optional)", "rowTitlePlaceholder": "Row title (≤24)", "addRow": "Add row", "addSection": "Add section", "ifLabel": "If", "capturedVariable": "Captured variable", "contactHasTag": "Contact has tag", "contactField": "Contact field", "varName": "var name", "tagLabel": "Tag", "fieldLabel": "Field", "pickTag": "Pick a tag…", "pickField": "Pick a field…", "operatorLabel": "Operator", "isPresent": "is present", "isAbsent": "is absent", "equals": "equals", "contains": "contains", "valueLabel": "Value", "ifTrueAdvance": "If true → advance to", "ifFalseAdvance": "If false → advance to", "actionLabel": "Action", "addTag": "Add tag", "removeTag": "Remove tag", "tagUuidPlaceholder": "Tag UUID", "thenAdvanceTo": "Then advance to", "mediaTypeLabel": "Media type", "imageLabel": "Image (PNG, JPEG, WebP)", "videoLabel": "Video (MP4, 3GP)", "documentLabel": "Document (PDF, Word, Excel, PowerPoint, TXT)", "fileLabel": "File", "removeFile": "Remove file", "uploading": "Uploading…", "clickToUpload": "Click to upload (max 16 MB)", "captionLabel": "Caption (optional, shown under the media)", "filenameLabel": "Filename shown to the customer (documents only)", "filenamePlaceholder": "invoice.pdf", "advanceAfterSending": "After sending, advance to", "pickNextNode": "Pick a next node…", "none": "— None —" }, "categories": { "messaging": "Messaging", "logic": "Logic & data", "flow": "Flow control" }, "nodes": { "start": { "label": "Start", "blurb": "Entry point of the flow" }, "send_message": { "label": "Send message", "blurb": "Sends a WhatsApp text message" }, "send_buttons": { "label": "Send buttons", "blurb": "Sends quick-reply buttons" }, "send_list": { "label": "Send list", "blurb": "Sends a tappable list of options" }, "send_media": { "label": "Send media", "blurb": "Sends an image, video, or document" }, "collect_input": { "label": "Collect input", "blurb": "Asks a question, saves the reply" }, "condition": { "label": "If / else", "blurb": "Branches on a rule" }, "set_tag": { "label": "Tag contact", "blurb": "Adds or removes a contact tag" }, "handoff": { "label": "Handoff to agent", "blurb": "Hands the conversation to a human" }, "end": { "label": "End", "blurb": "Ends the flow" } } }, "validation": { "noIssues": "No issues. Ready to activate.", "summary": "{errorCount} {errorCount, plural, =1 {error} other {errors}}, {warningCount} {warningCount, plural, =1 {warning} other {warnings}}", "jumpToNode": "Jump to node {key}" }, "editorState": { "saved": "Saved.", "fixIssues": "Fix the issues below before activating.", "statusActivated": "Flow activated.", "statusArchived": "Archived.", "statusDraft": "Saved as draft." }, "summary": { "options": "{count} {count, plural, =1 {option} other {options}}", "optionsAcrossSections": "{rowCount} {rowCount, plural, =1 {option} other {options}} across {sectionCount} {sectionCount, plural, =1 {section} other {sections}}", "noFile": "{label} (no file uploaded)", "media": "Media", "image": "Image", "video": "Video", "document": "Document", "audio": "Audio", "hasTag": "has tag {tag}", "opContains": "contains", "opExists": "exists", "opMissing": "missing", "modeAdd": "Add", "modeRemove": "Remove", "tagPicked": "{mode} tag {tag}…", "tagNone": "{mode} tag (none picked)" } }, "Settings": { "pageTitle": "Settings", "pageDesc": "Everything in one place — your account and your workspace. Pick a section to manage it.", "overview": { "notSetup": "Not set up yet", "connected": "Connected", "needsReconnecting": "Needs reconnecting", "viewTeamMembers": "View team members", "membersCount": "{count} {count, plural, =1 {member} other {members}}", "pendingInvites": "{count} pending {count, plural, =1 {invite} other {invites}}", "manageTemplates": "Manage message templates", "templatesCount": "{count} {count, plural, =1 {template} other {templates}}", "pendingReview": "{count} pending review", "tagsAndFields": "Tags and custom fields", "tagsCount": "{count} {count, plural, =1 {tag} other {tags}}", "fieldsCount": "{count} custom {count, plural, =1 {field} other {fields}}", "appearance": "{mode} mode · {theme} accent", "yourAccount": "Your account", "loading": "Loading…" }, "members": { "title": "Team members", "description": "People with access to this account. Roles control what each teammate can do.", "inviteMember": "Invite member", "online": "online", "away": "away", "offline": "offline", "memberCount": "{count} {count, plural, =1 {member} other {members}}", "you": "You", "unnamed": "Unnamed", "joined": "Joined {date}", "remove": "Remove", "removedToast": "Removed {name}", "updatedToast": "Updated {name} to {role}", "pendingInvitations": "Pending invitations", "inviteHint": "The plaintext invite URL is only shown once at creation for security — to re-share, revoke the invite below and create a new one.", "noPendingTitle": "No pending invitations.", "noPendingDesc": "Click Invite member above to generate a shareable link.", "untitledInvite": "Untitled invite", "created": "Created {date}", "expiresInDays": "expires in {days} {days, plural, =1 {day} other {days}}", "expiresInHours": "expires in {hours} {hours, plural, =1 {hour} other {hours}}", "expired": "expired", "revoke": "Revoke", "revokedToast": "Invitation revoked", "removeDialogTitle": "Remove member", "removeDialogDesc": "Remove {name} from the account? They'll be signed out of this account and given a fresh personal account on their next sign-in. Their login isn't deleted.", "cancel": "Cancel", "removing": "Removing...", "removeBtn": "Remove member" }, "invite": { "inviteCreated": "Invite created", "inviteCreatedDesc": "Share this link with your new teammate. They'll be able to sign up (or sign in) and join the account as {role}. The link is valid for {days} {days, plural, =1 {day} other {days}}.", "inviteLink": "Invite link", "copy": "Copy", "saveLinkNow": "Save this link now.", "saveLinkHint": "We never store the plaintext — once you close this dialog the URL is gone. To re-share, revoke this invite and create a new one.", "sendViaWhatsApp": "Send via WhatsApp", "done": "Done", "dialogTitle": "Invite a teammate", "dialogDesc": "Generate a one-time invite link. Share it via WhatsApp, Slack, or any channel you like — no email service required.", "roleLabel": "Role", "validForLabel": "Link valid for", "days1": "1 day", "days7": "7 days", "days30": "30 days", "labelTitle": "Label", "optional": "(optional)", "labelPlaceholder": "e.g. Sara — support team", "labelHint": "Helps you remember who you sent the link to in the pending list below.", "cancel": "Cancel", "creating": "Creating...", "generateLink": "Generate link", "labelTooLong": "Label must be {max} characters or fewer", "copied": "Invite link copied", "clipboardBlocked": "Clipboard blocked — copy the link manually", "whatsappMessage": "Join {accountName} on wacrm using this link (valid for {expiresInDays} days): {url}" }, "tagsAndFields": { "title": "Fields & tags", "description": "Two ways to organize contacts: colour-coded tags for quick grouping, and custom fields for structured data.", "tagsTitle": "Tags", "tagsDesc": "Colour-coded labels for grouping and filtering contacts.", "fieldsTitle": "Custom fields", "fieldsDesc": "Extra contact fields (e.g. ZIP code, lead source). They appear on every contact and in the “Update Contact Field” automation action.", "adminRole": "Admin", "failedToLoadTags": "Failed to load tags", "nameRequired": "Tag name is required", "notAuthenticated": "Not authenticated", "tagCreated": "Tag created", "failedToCreateTag": "Failed to create tag", "tagDeleted": "Tag deleted", "failedToDeleteTag": "Failed to delete tag", "deleteAria": "Delete {name}", "noTags": "No tags yet — create your first one below.", "placeholder": "e.g. Newsletter", "useColor": "Use {color}", "addTag": "Add tag", "deleteTag": "Delete tag", "deleteConfirm": "Delete the tag \"{name}\"? This removes it from all contacts and cannot be undone.", "cancel": "Cancel", "deleting": "Deleting...", "colors": { "red": "Red", "orange": "Orange", "amber": "Amber", "emerald": "Emerald", "cyan": "Cyan", "blue": "Blue", "violet": "Violet", "pink": "Pink" } }, "templates": { "title": "Message templates", "description": "Create templates and submit them to Meta for approval. Use \"Sync from Meta\" to pull templates approved elsewhere.", "syncFromMeta": "Sync from Meta", "syncing": "Syncing…", "syncTitle": "Pull approved templates from your Meta WhatsApp Business Account", "newTemplate": "New Template", "noTemplates": "No templates yet.", "createFirst": "Create your first message template to get started.", "editTitle": "Editing triggers Meta re-review — status flips to PENDING.", "editLabel": "Edit template", "edit": "Edit", "resubmitTitle": "Edit the template and resubmit to Meta for review.", "resubmitLabel": "Edit and resubmit template", "resubmit": "Resubmit", "deleteMetaLocallyAria": "Delete template from Meta and locally", "deleteLocallyAria": "Delete template locally", "deleteMetaLocallyTitle": "Delete from Meta and locally", "deleteLocallyTitle": "Delete locally", "dialogEditTitle": "Edit Message Template", "dialogNewTitle": "New Message Template", "dialogEditDesc": "Save your changes to re-submit to Meta. Status will flip back to PENDING during review.", "dialogNewDesc": "Build a template and submit it to Meta for approval. Once approved, you can use it in broadcasts and the inbox.", "authWarning": "AUTHENTICATION templates have a fixed body + OTP button shape that needs a different builder. Create them in Meta WhatsApp Manager for now and use Sync from Meta to bring them in.", "templateName": "Template Name", "namePlaceholder": "e.g. order_confirmation", "nameFixed": "Name is fixed once a template exists on Meta — create a new template to change it.", "nameHint": "Lowercase letters, digits, and underscores only.", "category": "Category", "language": "Language", "langFixed": "Language is fixed once a template exists on Meta.", "langHint": "Must match the exact code on Meta — en_US and en are distinct.", "header": "Header", "headerNone": "None", "headerText": "Text", "headerImage": "Image", "headerVideo": "Video", "headerDocument": "Document", "headerTextPlaceholder": "Header text (max 60 chars, optional {{1}})", "headerSampleAria": "Sample value for header variable", "headerSamplePlaceholder": "Sample value for {{1}} (required for Meta review)", "uploadImage": "Upload image", "uploadHint": "JPEG or PNG, ≤5 MB", "mediaUrlPlaceholder": "https://… (or paste a public {format} link)", "imageHint": "Upload a JPEG/PNG (≤5 MB, ≥800×418 px recommended) or paste a public HTTPS link — we upload it to Meta for review automatically.", "mediaHint": "Must be a publicly accessible HTTPS link. Meta fetches it once during review, so it needs to stay live for ~24 hrs.", "videoHint": " Recommended: MP4 / 3GPP, ≤16 MB, ≤60 seconds.", "documentHint": " Recommended: PDF, ≤100 MB.", "bodyText": "Body Text", "bodyPlaceholder": "Hello {{1}}, your order {{2}} is confirmed.", "bodyHint": "Use {{1}}, {{2}} for variables (must be contiguous starting at {{1}}).", "sampleValues": "Sample values (Meta uses these to review your template)", "sampleAria": "Sample value for body variable {var}", "samplePlaceholder": "Sample for {var}", "footer": "Footer (optional)", "footerPlaceholder": "Optional footer text (max 60 chars)", "buttons": "Buttons (optional)", "addButton": "Add Button", "buttonsLimit": "Up to {max} buttons. QUICK_REPLY buttons must come before URL / phone / copy-code buttons.", "btnQuickReply": "Quick Reply", "btnUrl": "URL", "btnPhone": "Phone", "btnCopyCode": "Copy Code", "btnLabelPlaceholder": "Button label", "urlPlaceholder": "https://example.com/path or with {{1}} suffix", "urlSamplePlaceholder": "Example value for {{1}} (required when URL has a variable)", "phonePlaceholder": "+15551234567", "codePlaceholder": "Example code (e.g. SUMMER20)", "cancel": "Cancel", "saving": "Saving…", "submitting": "Submitting…", "saveResubmit": "Save & Resubmit", "submitApproval": "Submit for Approval", "deleteDialogTitle": "Delete template?", "deleteMetaDesc": "\"{name}\" will be deleted from Meta and from wacrm. Active broadcasts using this template will start failing on their next send. This can't be undone.", "deleteLocalDesc": "\"{name}\" will be deleted from wacrm. It was never submitted to Meta, so no remote cleanup is needed.", "deleting": "Deleting…", "delete": "Delete", "toastLoadFailed": "Failed to load templates", "toastSubmitFailed": "Failed to submit", "toastSubmitEditSuccess": "Edit submitted — Meta typically reviews within 24 hours.", "toastSubmitNewSuccess": "Submitted to Meta — typical review time is 24 hours. Status updates automatically.", "toastSaveEditDry": "Template updated (dry-run — no Meta call)", "toastSaveNewDry": "Template saved (dry-run — no Meta call)", "toastSyncCount": "Synced {total} {total, plural, =1 {template} other {templates}} from Meta", "toastSyncDetails": " ({inserted} new, {updated} updated)", "toastSyncFailed": "Failed to sync: {preview}", "toastSyncTruncated": "Synced the first 2000 templates only — your account has more. Sync again to continue, or contact support if this persists.", "toastSyncError": "Failed to sync templates", "toastDeleteSuccess": "Template deleted", "toastDeleteError": "Failed to delete template", "toastInvalidImage": "Header image must be a JPEG or PNG.", "toastImageTooLarge": "Image is {size} MB — Meta's limit is 5 MB.", "toastUploadSuccess": "Image uploaded.", "toastUploadFailed": "Upload failed." }, "roles": { "admin": "Admin", "adminHint": "Manage members + everything", "agent": "Agent", "agentHint": "Use features; no settings", "viewer": "Viewer", "viewerHint": "Read-only across the app", "owner": "Owner", "ownerHint": "Full control over account and billing" }, "whatsapp": { "title": "WhatsApp connection", "description": "Connect your Meta WhatsApp Business API. Credentials, webhook, and setup steps all live here.", "tokenCorrupted": "Stored token can't be decrypted", "resetting": "Resetting...", "resetConfig": "Reset Configuration", "credentialsValid": "Credentials valid", "notConnected": "Not Connected", "connectedDesc": "Your access token authenticates with Meta. See Registration status below for whether webhooks are actually wired.", "notConnectedDesc": "Configure your Meta API credentials below to connect your WhatsApp Business account.", "registered": "Registered — Meta will deliver events to wacrm", "notRegistered": "Not registered — Meta will not deliver events", "verifyWithMeta": "Verify with Meta", "subscribedSince": "Subscribed since {date}. Click Verify with Meta if events stop arriving.", "unknownDate": "unknown", "lastAttemptFailed": "Last attempt failed with: ", "retryHint": "Enter (or correct) the 2-step PIN below and click Save Configuration to retry.", "noRegistrationHint": "This number was saved before registration tracking existed, or registration was skipped. Enter the 2-step PIN below and click Save Configuration to subscribe it.", "diagnosticLastRun": "Diagnostic — last run: ", "live": "live", "notLive": "not live", "apiCredentialsTitle": "API Credentials", "apiCredentialsDesc": "Enter your Meta WhatsApp Business API credentials.", "phoneNumberId": "Phone Number ID", "wabaId": "WhatsApp Business Account ID", "accessToken": "Permanent Access Token", "accessTokenPlaceholder": "Enter your access token", "tokenHidden": "Token is hidden for security. Re-enter it to update configuration.", "webhookVerifyToken": "Webhook Verify Token", "webhookVerifyTokenPlaceholder": "Create a custom verify token", "webhookVerifyTokenHint": "A custom string you create. Must match the token you set in Meta webhook settings.", "twoStepPin": "Two-step verification PIN", "optional": "(optional)", "pinPlaceholder": "6-digit PIN from Meta WhatsApp Manager", "pinHint": "Needed only to wire inbound messages for a production number. Set it in Meta Business Manager → WhatsApp Accounts → Phone Numbers → Two-step verification, then paste it here so wacrm can subscribe the number — otherwise Meta routes inbound events to whichever app last claimed it (the symptom that hits second numbers under a shared WABA). Meta test numbers have no PIN and are pre-registered — leave this blank for them. Leaving it blank also keeps an existing registration untouched.", "webhookTitle": "Webhook Configuration", "webhookDesc": "Use this URL as your webhook callback in the Meta App Dashboard.", "webhookUrl": "Webhook Callback URL", "saving": "Saving...", "saveConfig": "Save Configuration", "testing": "Testing...", "testConnection": "Test API Connection", "setupInstructions": "Setup Instructions", "setupInstructionsDesc": "Follow these steps to connect your WhatsApp Business API.", "step1": "Create a Meta App", "step1_1": "Go to developers.facebook.com", "step1_2": "Click \"My Apps\" and then \"Create App\"", "step1_3": "Select \"Business\" as the app type", "step1_4": "Fill in app details and create", "step2": "Add WhatsApp Product", "step2_1": "In your app dashboard, click \"Add Product\"", "step2_2": "Find \"WhatsApp\" and click \"Set Up\"", "step2_3": "Follow the setup wizard to link your business", "step3": "Get API Credentials", "step3_1": "Go to WhatsApp > API Setup", "step3_2": "Copy your Phone Number ID", "step3_3": "Copy your WhatsApp Business Account ID", "step3_4": "Generate a Permanent Access Token from Business Settings > System Users", "step4": "Configure Webhooks", "step4_1": "Go to WhatsApp > Configuration", "step4_2": "Click \"Edit\" on the Webhook section", "step4_3": "Paste the Webhook Callback URL from above", "step4_4": "Enter the same Verify Token you set here", "step4_5": "Subscribe to \"messages\" webhook field", "metaDocs": "Meta WhatsApp API Documentation" }, "sections": { "overview": "Overview", "profile": "Your profile", "security": "Login & security", "appearance": "Appearance", "whatsapp": "WhatsApp", "templates": "Templates", "fields": "Fields & tags", "deals": "Deals & currency", "members": "Team members", "api": "API keys" }, "groups": { "account": "Account", "workspace": "Workspace" }, "profile": { "title": "Your profile", "description": "How you show up across the app. Your avatar and name appear in the header, sidebar, and anywhere your teammates see you.", "changePhoto": "Change photo", "uploadPhoto": "Upload photo", "remove": "Remove", "photoHint": "PNG, JPG, WebP, or GIF. Up to 2 MB.", "displayName": "Display name", "email": "Email", "emailChangeHint": "Check the inbox for {oldEmail} and {newEmail} — both need to confirm before the change takes effect.", "accountDetails": "Account details", "role": "Role", "joined": "Joined", "userId": "User ID", "loading": "Loading your profile…", "saving": "Saving…", "saveChanges": "Save changes", "unsupportedImage": "Unsupported image type", "unsupportedImageDesc": "Use PNG, JPG, WebP, or GIF.", "imageTooLarge": "Image is too large", "imageTooLargeDesc": "Maximum 2 MB.", "nameRequired": "Display name is required", "invalidEmail": "Enter a valid email address", "uploadFailed": "Upload failed: {message}", "saveFailed": "Save failed: {message}", "profileSaved": "Profile saved", "emailChangeFailed": "Email change failed: {message}", "profileSavedEmailCheck": "Profile saved — check your email to confirm the address change", "passwordTitle": "Password", "passwordDesc": "Use at least {min} characters. You will stay signed in on this device after changing it.", "currentPassword": "Current password", "newPassword": "New password", "confirmPassword": "Confirm new password", "updating": "Updating…", "updatePassword": "Update password", "cannotChangeNoEmail": "Cannot change password without a current email", "passwordTooShort": "Password must be at least {min} characters", "passwordMismatch": "New password and confirmation do not match", "currentPasswordIncorrect": "Current password is incorrect", "passwordUpdateFailed": "Password update failed: {message}", "passwordUpdated": "Password updated", "sessionsTitle": "Active sessions", "sessionsDesc": "Sign out of every device where you're logged in — including this one. Useful if you lost a laptop or shared your password.", "signOutAll": "Sign out of all devices", "signOutConfirmTitle": "Sign out everywhere?", "signOutConfirmDesc": "Every device logged into this account will be signed out and will need to log in again. You will be redirected to the login page.", "cancel": "Cancel", "signingOut": "Signing out…", "signOutEverywhere": "Sign out everywhere", "signOutFailed": "Sign-out failed: {message}" }, "appearance": { "title": "Appearance", "description": "Set the mode and accent colour used across the app. Saved to this device — try it, it changes live.", "mode": "Mode", "useMode": "Use {mode} mode", "active": "Active", "accentColor": "Accent color", "useTheme": "Use {name} theme" }, "security": { "title": "Login & security", "description": "Change your password and sign out of your devices. These keep your account safe." }, "apiKeys": { "title": "API keys", "description": "Keys authenticate the public REST API (/api/v1) so you can build your own automations. Send them as Authorization: Bearer <key>.", "newApiKey": "New API key", "noApiKeys": "No API keys yet.", "createOneHint": "Click New API key to create one.", "askAdminHint": "Ask an admin to create one.", "revoked": "Revoked", "expired": "Expired", "noScopes": "No scopes", "created": "Created {date}", "lastUsed": "last used {date}", "neverUsed": "never used", "expires": "expires {date}", "revoke": "Revoke", "revokeSuccess": "Revoked \"{name}\"", "revokeFailed": "Failed to revoke key", "loadFailed": "Failed to load API keys", "createError": "Failed to create key", "nameRequired": "Give the key a name", "nameLabel": "Name", "namePlaceholder": "e.g. Zapier automation", "scopesLabel": "Scopes", "scopesHint": "A key with no scopes can still call GET /api/v1/me to verify it works.", "cancel": "Cancel", "creating": "Creating…", "createKey": "Create key", "copyTitle": "Copy your API key", "copyDesc": "This is the only time the full key is shown. Store it somewhere safe — if you lose it, revoke it and create a new one.", "apiKeyLabel": "API key", "copy": "Copy", "copySuccess": "API key copied", "copyFailed": "Copy failed — select and copy manually", "newKeyTitle": "New API key", "newKeyDesc": "Name it after the integration that will use it, and grant only the scopes it needs.", "done": "Done", "networkError": "Could not reach the server" }, "deals": { "title": "Deals & currency", "description": "The currency used for new deals and for pipeline and dashboard totals.", "defaultCurrency": "Default currency", "defaultCurrencyDesc": "New deals default to this currency, and pipeline and dashboard totals are shown in it. Existing deals keep the currency they were saved with.", "currencyLabel": "Currency", "adminOnlyHint": "Only account admins can change the default currency.", "save": "Save", "saving": "Saving...", "saveFailed": "Failed to save default currency", "saveSuccess": "Default currency updated" }, "aiConfig": { "title": "Agent setup", "description": "Bring your own OpenAI or Anthropic key. wacrm calls the provider directly with your key — no per-seat AI fees, and your data stays yours. This powers AI-drafted replies in the inbox, the auto-reply bot, and the Playground.", "adminOnlyConfig": "Only admins and owners can change the AI configuration.", "loadFailed": "Failed to load AI configuration", "providerAndKey": "Provider & key", "encryptionNotice": "Your key is encrypted at rest (AES-256-GCM) and never shown again after saving.", "provider": "Provider", "model": "Model", "apiKey": "API key", "testKey": "Test key", "testSuccess": "Key works — the provider responded.", "testRejected": "The provider rejected the request.", "testNetworkError": "Could not reach the provider.", "embeddingsKey": "Embeddings key", "optionalSemanticSearch": "(optional — enables semantic knowledge-base search)", "embeddingsHint": "An OpenAI key used only to embed your knowledge base (text-embedding-3-small){sameKeyText}. Leave blank to use keyword search instead. Clear it to turn semantic search off.", "sameKeyText": " — can be the same key as above", "behaviour": "Behaviour", "behaviourDesc": "Tell the assistant about your business — products, tone, what it may and may not promise. This context feeds both drafts and auto-replies.", "businessContext": "Business context & instructions", "promptPlaceholder": "e.g. We are Acme, a coffee-equipment store. Be warm and concise. Never quote prices or delivery dates — hand off to a human for those.", "enableAssistant": "Enable AI assistant", "enableAssistantDesc": "Master switch. Turns on the “Draft with AI” button in the inbox.", "autoReply": "Auto-reply to inbound messages", "autoReplyDesc": "The bot answers new inbound messages automatically (only when no flow handles them and no agent is assigned). Hands off to a human when it can’t help.", "maxAutoReplies": "Max auto-replies per conversation", "maxAutoRepliesDesc": "After this many bot replies in one thread, the bot goes quiet.", "handoffTo": "Hand off to", "handoffToDesc": "When the bot can’t help — or hits the reply cap — it pauses and routes the chat here, with a short note on what happened.", "handoffQueue": "Unassigned queue (any agent can pick it up)", "remove": "Remove", "save": "Save", "missingModel": "Enter a model name.", "missingApiKey": "Enter your API key.", "saveSuccess": "AI assistant saved.", "saveFailed": "Failed to save.", "removeSuccess": "AI configuration removed.", "removeFailed": "Failed to remove." }, "aiKnowledge": { "loadFailed": "Failed to load knowledge base", "openFailed": "Failed to open document", "titleContentRequired": "Title and content are required.", "saveSuccessNew": "Document added.", "saveSuccessUpdate": "Document updated.", "saveFailed": "Failed to save.", "removeSuccess": "Document removed.", "removeFailed": "Failed to remove.", "reindexSuccess": "Reindexed {count} document(s).", "reindexFailed": "Reindex failed.", "title": "Knowledge base", "description": "Add FAQs, policies, or product details. The assistant retrieves the relevant pieces when drafting and auto-replying, so it can answer instead of handing off.{searchType}", "semanticSearchOn": " Semantic search is on (embeddings key set).", "keywordSearchOn": " Using keyword search — add an embeddings key above for semantic search.", "noDocs": "No documents yet.", "editDocTitle": "Title", "editDocTitlePlaceholder": "e.g. Returns & refunds policy", "editDocContent": "Content", "editDocContentPlaceholder": "Paste the FAQ answer, policy text, or product details…", "cancel": "Cancel", "saveDoc": "Save document", "addDoc": "Add document", "reindex": "Reindex", "reindexTooltip": "Re-embed all documents (e.g. after adding an embeddings key)", "loading": "Loading…" } } }