iachat/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json
Cayo P. R. Oliveira c6bfd1eed3
feat: schedule messages recurrence (#240)
* feat(scheduled-messages): add recurring scheduled messages

Implements the recurring scheduled messages feature allowing agents to
configure recurrence rules when scheduling messages, with automatic
creation of subsequent scheduled messages after each send.

Backend:
- RecurringScheduledMessage model with JSONB recurrence_rule validation
- RecurrenceCalculatorService for next occurrence date calculation
- RecurrenceDescriptionService for human-readable rule descriptions
- CreateNextOccurrenceService for auto-creating child ScheduledMessages
- RecurringScheduledMessagesController with CRUD operations
- RecurringScheduledMessagePolicy for authorization
- Modified SendScheduledMessageJob to handle recurrence after send
- Updated due_for_sending scope to exclude resolved conversations
- ActionCable events for real-time updates
- Activity message i18n (en + pt-BR)

Frontend:
- RecurrenceDropdown.vue with contextual shortcut options
- RecurrenceCustomModal.vue for custom recurrence configuration
- RecurringScheduledMessageItem.vue for sidebar display
- Integration into ScheduledMessageModal.vue
- Updated ScheduledMessages.vue with recurrence section and filtering
- Vuex store module for recurring scheduled messages
- API client for CRUD operations
- WebSocket handlers in actionCable.js
- recurrenceHelpers.js utility functions
- i18n keys for en and pt-BR

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): fix creation and edit visibility

- Fix API payload key mismatch (snake_case vs camelCase) in modal submit
- Add status: 'active' to recurring creation payload
- Fix strong params to permit recurrence_rule array fields (week_days)
- Cast string values from strong params to integers for JSONB validation
- Show RecurrenceDropdown when editing (remove isEditing gate)
- Populate recurrenceRule from scheduled message's recurring parent
- Include recurring_scheduled_message_id and recurrence_rule in
  scheduled message jbuilder response

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): fix dropdown toggle and locale tag errors

- Use DropdownItem :click prop instead of @click to use the injected
  closeMenu from DropdownContainer context (default slot doesn't
  expose toggle)
- Normalize locale from pt_BR to pt-BR for Intl.DateTimeFormat
  compatibility in RecurringScheduledMessageItem

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(recurring-messages): add separator line and expandable history

- Add border separator between recurring messages section and
  pending/draft messages, matching the history section separator
- Replace static 'N enviadas' counter with clickable toggle that
  expands to show individual sent/failed child messages with
  status badges and formatted timestamps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(recurring-messages): add click-to-navigate on sent children

Make sent child messages in recurring message history clickable.
Clicking navigates to the actual message in the conversation using
the messageId query param, same pattern as ScheduledMessageItem.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(recurring-messages): allow editing recurring messages

- Add edit button to RecurringScheduledMessageItem (active only)
- Transform recurring message into scheduledMessage-compatible shape
  with recurring_scheduled_message_id set, so the modal reuses
  the existing update path
- Handle edge case of removing recurrence from a recurring message
  (cancels series without trying to update a non-existent standalone)
- Sent history is preserved by the backend update action

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): show recurrence field without date selection

Remove v-if="scheduledDate" gate so the recurrence dropdown is
always visible in the modal. Falls back to today's date for
contextual shortcut labels when no date is selected yet.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): ensure recurrence visible on edit and add pending_scheduled_message to API

- Add pending_scheduled_message to recurring_scheduled_message jbuilder
  so REST API data matches WebSocket push_event_data
- Add fallback in openEditRecurringModal to find pending child from
  scheduled_messages array when pending_scheduled_message is absent
- Add same fallback in nextSendLabel computed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(scheduled-messages): add sections for Drafts and Pending messages in the UI

* refactor(scheduled-messages): merge RecurringScheduledMessageItem into ScheduledMessageItem

Consolidate the recurring message card into the existing
ScheduledMessageItem component instead of maintaining a separate
component. The unified component detects recurring messages via
recurrence_rule and conditionally shows:
- Recurrence description header with repeat icon
- Next send time label
- Expandable sent/failed children history with click-to-navigate
- Stop button (replaces delete) with confirmation modal
- Active/completed/cancelled status badges

Delete the now-unused RecurringScheduledMessageItem.vue.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(scheduled-messages): use blue badge for active, keep green for sent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(scheduled-messages): remove draft and pending sections from UI and update recurrence title

* fix(recurring-messages): use Teleport for recurrence dropdown

Replace DropdownContainer with Teleport-based floating dropdown so
options render outside the modal. Fixes:
- Dropdown no longer enlarges the modal or causes scrolling
- Dropdown closes before Custom modal opens (no overlap)
- Auto-detects available space and opens above/below trigger

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): recalculate next date when recurrence rule changes

When editing a recurring message and changing the recurrence rule,
the pending occurrence date is now validated against the new rule.
If the user-provided date doesn't match (e.g. Thursday removed from
weekly days), the system computes the next valid date using
RecurrenceCalculatorService instead of blindly using the old date.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(scheduled-messages): resolve deprecated onClose and disabled type warnings

- Replace :on-close prop with @close event on woot-modal components
- Cast hasTemplate computed to boolean to fix disabled prop type check

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(scheduled-messages): replace remaining deprecated on-close props

- ScheduledMessages.vue delete confirm modal
- RecurrenceCustomModal.vue modal

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): address review feedback on PR #240

- Fix v-if/v-else bug hiding message list behind resolved warning
- Fix occurrences_sent incrementing on failed sends (skip_increment flag)
- Fix compute_next_valid_date using .min instead of .max
- Fix Vuex delete action to update state on cancel (not remove)
- Use atomic update_counters for occurrences_sent increment
- Add safe Date.iso8601 parsing with rescue in should_complete?
- Add null: false to occurrences_sent migration column
- Fix pt-BR accent: Recorrencia → Recorrências
- Use I18n.with_locale(account.locale) for all activity messages
- Fix N+1 in jbuilder partials (Ruby filtering + eager loading)
- Add interval >= 1 validation to RecurrenceCustomModal isValid
- Validate recurrence_rule presence when status is active
- Add ISO8601 date format validation for end_date
- Add unknown_agent i18n key for fallback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): wrap create/update in transactions, clean pending on deactivation

- Wrap create and update flows in ActiveRecord transactions
- Move attachment purge after save! to prevent data loss on validation failure
- Destroy pending children when status transitions to non-active
- Fixes critical bug where stopping recurrence could leave armed pending messages

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): prevent monthly/yearly day-of-month drift

Store the original intended day in recurrence_rule JSONB as month_day
(for monthly) and year_day/year_month (for yearly). The calculator
now uses these stored values instead of @last_date.day, preventing
drift after short months cap the day (e.g., Jan 31 → Feb 28 → all
subsequent months stuck on 28).

Backend:
- RecurrenceCalculatorService: use rule[:month_day] for monthly and
  rule[:year_day]/rule[:year_month] for yearly calculations
- Controller: permit and cast the new integer keys

Frontend:
- recurrenceHelpers: yearly shortcuts include year_day/year_month
- RecurrenceCustomModal: emit month_day for monthly day_of_month
  rules and year_day/year_month for yearly rules

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): i18n description services, align due_for_sending scope

Backend:
- RecurrenceDescriptionService: replace hardcoded English with I18n.t()
  calls; accept locale parameter and use I18n.with_locale
- RecurringScheduledMessage model: pass account locale to description service
- ScheduledMessage: align due_for_sending? instance method with scope by
  checking conversation status (open/pending)

Frontend:
- buildRecurrenceDescription: use t() i18n function instead of manual
  isPt locale branching
- Add DESCRIPTION i18n keys to en/conversation.json and pt_BR/conversation.json
- Update RecurrenceDropdown and ScheduledMessageItem callers to pass t

i18n:
- Add recurring_scheduled_messages.description.* keys to en.yml and pt_BR.yml

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): keep pending child when deactivating recurrence

When editing a recurring message to disable recurrence while setting a
future send date, the pending child message is now preserved instead of
being destroyed. This allows a 'final send' without creating new
recurrences (the send job already guards with recurring&.active?).

Backend:
- Add update_pending_on_deactivation: updates pending child's
  scheduled_at or creates a final pending occurrence
- Replace destroy_all in update's non-active branch

Frontend:
- activeRecurringMessages now includes non-active recurring messages
  that still have a pending child (pending_scheduled_message)
- Stop button hidden for already-cancelled recurring messages
- inactiveRecurringMessages excludes messages with pending children

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): prevent removing recurrence from existing recurring message

Once a scheduled message has recurrence, the 'Does not repeat' option is
hidden from the RecurrenceDropdown when editing. This avoids edge cases
where deactivating recurrence leaves the message in an ambiguous display
state.

- RecurrenceDropdown: add hideNoRepeat prop, filter NO_REPEAT from shortcuts
- ScheduledMessageModal: pass hideNoRepeat when isEditingRecurring
- Revert update_pending_on_deactivation (no longer reachable from UI)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): address CodeRabbit review feedback

- ScheduledMessage#push_event_data: expose recurring_scheduled_message_id
  in ActionCable payloads so frontend correctly classifies children
- RecurringScheduledMessagePolicy: add agent_bot? check for parity with
  ScheduledMessagePolicy
- RecurrenceCalculatorService: guard against nil/empty week_days
- Factory: bind inbox and account to conversation to prevent cross-account
  flakiness in specs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(recurring-messages): update schema to enforce non-null constraint on occurrences_sent

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2026-03-19 22:51:14 -03:00

636 lines
27 KiB
JSON

{
"CONVERSATION": {
"SELECT_A_CONVERSATION": "Por favor, selecione uma conversa no painel da esquerda",
"CSAT_REPLY_MESSAGE": "Por favor, classifique a conversa",
"404": "Desculpe, não conseguimos encontrar a conversa. Por favor, tente novamente",
"SWITCH_VIEW_LAYOUT": "Alternar o layout",
"DASHBOARD_APP_TAB_MESSAGES": "Mensagens",
"UNVERIFIED_SESSION": "A identidade deste usuário não foi verificada",
"NO_MESSAGE_1": "Oh oh! Parece que não há mensagens de clientes na sua caixa de entrada.",
"NO_MESSAGE_2": " para enviar uma mensagem para sua página!",
"NO_INBOX_1": "Hola! Parece que você não adicionou nenhuma caixa de entrada ainda.",
"NO_INBOX_2": " para começar",
"NO_INBOX_AGENT": "Uh Oh! Parece que você não faz parte de nenhuma caixa de entrada. Por favor, contate seu administrador",
"SEARCH_MESSAGES": "Pesquisar por mensagens nas conversas",
"VIEW_ORIGINAL": "Ver original",
"VIEW_TRANSLATED": "Ver traduzido",
"EMPTY_STATE": {
"CMD_BAR": "para abrir o menu de comando",
"KEYBOARD_SHORTCUTS": "para ver os atalhos de teclado"
},
"SEARCH": {
"TITLE": "Pesquisar mensagens",
"RESULT_TITLE": "Resultados da Pesquisa",
"LOADING_MESSAGE": "Preparando dados...",
"PLACEHOLDER": "Digite qualquer texto para pesquisar mensagens",
"NO_MATCHING_RESULTS": "Nenhum resultado encontrado."
},
"UNREAD_MESSAGES": "Mensagens não lidas",
"UNREAD_MESSAGE": "Mensagem não lida",
"CLICK_HERE": "Clique aqui",
"LOADING_INBOXES": "Carregando caixas de entrada",
"LOADING_CONVERSATIONS": "Carregando conversas",
"CANNOT_REPLY": "Você não pode responder porque",
"24_HOURS_WINDOW": "Restrições de janela de mensagem de 24 horas",
"48_HOURS_WINDOW": "Restrição de janela de mensagem de 48 horas",
"API_HOURS_WINDOW": "Você só pode responder a esta conversa em {hours} horas",
"NOT_ASSIGNED_TO_YOU": "Esta conversa não está atribuída a você. Gostaria de atribuir esta conversa a você mesmo?",
"ASSIGN_TO_ME": "Atribuir a mim",
"BOT_HANDOFF_MESSAGE": "Você está respondendo a uma conversa que é atualmente tratada por um assistente ou um robô.",
"BOT_HANDOFF_ACTION": "Marcar como aberta e atribuir a você",
"BOT_HANDOFF_REOPEN_ACTION": "Marcar conversa como aberta",
"BOT_HANDOFF_SUCCESS": "Uma conversa foi atribuída a você",
"BOT_HANDOFF_ERROR": "Falha ao resolver conversas. Por favor, tente novamente.",
"TWILIO_WHATSAPP_CAN_REPLY": "Você só pode responder a esta conversa usando um modelo de mensagem devido a",
"TWILIO_WHATSAPP_24_HOURS_WINDOW": "Restrições de janela de mensagem de 24 horas",
"ANNOUNCEMENT_MODE_BANNER": "Apenas administradores têm permissão para enviar mensagens neste grupo",
"GROUP_LEFT_BANNER": "Você não faz mais parte deste grupo e não pode enviar mensagens nele",
"GROUPS_DISABLED_BANNER": "As mensagens de grupo estão desativadas. Ative o suporte completo a grupos (gratuito) para ver e enviar mensagens.",
"GROUPS_DISABLED_CTA": "Saiba como ativar (gratuito)",
"OLD_INSTAGRAM_INBOX_REPLY_BANNER": "Esta conta do Instagram foi migrada para a nova caixa de entrada do canal do Instagram. Todas as novas mensagens serão mostradas lá. Você não poderá mais enviar mensagens desta conversa.",
"REPLYING_TO": "Você está respondendo a:",
"REMOVE_SELECTION": "Remover seleção",
"DOWNLOAD": "Baixar",
"UNKNOWN_FILE_TYPE": "Arquivo desconhecido",
"SAVE_CONTACT": "Salvar contato",
"NO_CONTENT": "Nenhum conteúdo a ser exibido",
"SHARED_ATTACHMENT": {
"CONTACT": "{sender} compartilhou um contato",
"LOCATION": "{sender} compartilhou uma localização",
"FILE": "{sender} compartilhou um arquivo",
"MEETING": "{sender} começou a reunião"
},
"UPLOADING_ATTACHMENTS": "Enviando anexos...",
"REPLIED_TO_STORY": "Respondido ao seu story",
"UNSUPPORTED_MESSAGE": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo.",
"UNSUPPORTED_MESSAGE_WHATSAPP": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo do WhatsApp.",
"UNSUPPORTED_MESSAGE_FACEBOOK": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo Facebook Messenger.",
"UNSUPPORTED_MESSAGE_INSTAGRAM": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo do Instagram.",
"SUCCESS_DELETE_MESSAGE": "Mensagem excluída com sucesso",
"FAIL_DELETE_MESSSAGE": "Não foi possível excluir a mensagem! Tente novamente",
"NO_RESPONSE": "Sem resposta",
"RESPONSE": "Resposta",
"RATING_TITLE": "Classificação",
"FEEDBACK_TITLE": "Feedback",
"REPLY_MESSAGE_NOT_FOUND": "Mensagem não disponível",
"CARD": {
"SHOW_LABELS": "Mostrar etiquetas",
"HIDE_LABELS": "Ocultar as etiquetas"
},
"VOICE_CALL": {
"INCOMING_CALL": "Chamada recebida",
"OUTGOING_CALL": "Chamada realizada",
"CALL_IN_PROGRESS": "Chamada em andamento",
"NO_ANSWER": "Sem resposta",
"MISSED_CALL": "Chamada perdida",
"CALL_ENDED": "Chamada encerrada",
"NOT_ANSWERED_YET": "Ainda não respondido",
"THEY_ANSWERED": "Eles responderam",
"YOU_ANSWERED": "Você respondeu"
},
"HEADER": {
"RESOLVE_ACTION": "Resolver",
"REOPEN_ACTION": "Reabrir",
"OPEN_ACTION": "Abrir",
"MORE_ACTIONS": "Mais ações",
"OPEN": "Mais",
"CLOSE": "Fechar",
"DETAILS": "detalhes",
"SNOOZED_UNTIL": "Adiar até",
"SNOOZED_UNTIL_TOMORROW": "Adiado até amanhã",
"SNOOZED_UNTIL_NEXT_WEEK": "Adiada até a próxima semana",
"SNOOZED_UNTIL_NEXT_REPLY": "Adiado até a próxima resposta",
"SLA_STATUS": {
"FRT": "FRT {status}",
"NRT": "NRT {status}",
"RT": "RT {status}",
"MISSED": "perdidas",
"DUE": "venceu"
}
},
"RESOLVE_DROPDOWN": {
"MARK_PENDING": "Deixar pendente",
"SNOOZE_UNTIL": "Adiar",
"SNOOZE": {
"TITLE": "Suspender até",
"NEXT_REPLY": "Próxima resposta",
"TOMORROW": "Amanhã",
"NEXT_WEEK": "Próxima semana"
}
},
"MENTION": {
"AGENTS": "Agentes",
"TEAMS": "Times"
},
"CUSTOM_SNOOZE": {
"TITLE": "Adiar até",
"APPLY": "Adiar",
"CANCEL": "Cancelar"
},
"PRIORITY": {
"TITLE": "Prioridade",
"OPTIONS": {
"NONE": "Nenhuma",
"URGENT": "Urgente",
"HIGH": "Alta",
"MEDIUM": "Média",
"LOW": "Baixa"
},
"CHANGE_PRIORITY": {
"SELECT_PLACEHOLDER": "Nenhuma",
"INPUT_PLACEHOLDER": "Selecionar prioridade",
"NO_RESULTS": "Nenhum resultado encontrado",
"SUCCESSFUL": "Alterada a prioridade do ID da conversa {conversationId} para {priority}",
"FAILED": "Não foi possível alterar a prioridade. Por favor, tente novamente."
}
},
"DELETE_CONVERSATION": {
"TITLE": "Excluir conversa #{conversationId}",
"DESCRIPTION": "Tem certeza que deseja excluir esta conversa?",
"CONFIRM": "Excluir"
},
"CARD_CONTEXT_MENU": {
"PENDING": "Deixar pendente",
"RESOLVED": "Marcar como resolvida",
"MARK_AS_UNREAD": "Marcar como não lida",
"MARK_AS_READ": "Marcar como lida",
"REOPEN": "Reabrir conversa",
"SNOOZE": {
"TITLE": "Adiar",
"NEXT_REPLY": "Até a próxima resposta",
"TOMORROW": "Até amanhã",
"NEXT_WEEK": "Até a próxima semana"
},
"ASSIGN_AGENT": "Atribuir Agente",
"ASSIGN_LABEL": "Atribuir etiqueta",
"AGENTS_LOADING": "Carregando agentes...",
"ASSIGN_TEAM": "Atribuir time",
"DELETE": "Excluir conversa",
"OPEN_IN_NEW_TAB": "Abrir em nova aba",
"COPY_LINK": "Copiar link da conversa",
"COPY_LINK_SUCCESS": "Link da conversa copiado",
"API": {
"AGENT_ASSIGNMENT": {
"SUCCESFUL": "ID da conversa {conversationId} atribuído para \"{agentName}\"",
"FAILED": "Não foi possível atribuir agente. Por favor, tente novamente."
},
"LABEL_ASSIGNMENT": {
"SUCCESFUL": "Etiqueta #{labelName} atribuída para a conversa {conversationId}",
"FAILED": "Não foi possível atribuir etiqueta. Por favor, tente novamente."
},
"TEAM_ASSIGNMENT": {
"SUCCESFUL": "Time {team} atribuído para o id de conversa {conversationId}",
"FAILED": "Não foi possível atribuir time. Por favor, tente novamente."
}
}
},
"FOOTER": {
"MESSAGE_SIGN_TOOLTIP": "Assinatura de mensagem",
"ENABLE_SIGN_TOOLTIP": "Ativar assinatura",
"DISABLE_SIGN_TOOLTIP": "Desativar assinatura",
"SIGNATURE_LABEL_TOP": "↓ Assinatura",
"SIGNATURE_LABEL_TOP_TOOLTIP": "A assinatura será enviada no início da mensagem",
"SIGNATURE_LABEL_BOTTOM": "↑ Assinatura",
"SIGNATURE_LABEL_BOTTOM_TOOLTIP": "A assinatura será enviada no final da mensagem",
"MSG_INPUT": "Shift + enter para nova linha. Digite '/' para selecionar uma Resposta Pronta.",
"PRIVATE_MSG_INPUT": "A mensagem será visível apenas para agentes",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "A assinatura da mensagem não está configurada. Por favor, configure-a nas configurações do perfil.",
"CLICK_HERE": "Clique aqui para atualizar",
"WHATSAPP_TEMPLATES": "Templates do Whatsapp",
"ANNOUNCEMENT_MODE_RESTRICTED": "Apenas administradores têm permissão para enviar mensagens neste grupo",
"GROUP_LEFT_RESTRICTED": "Você não faz mais parte deste grupo e não pode enviar mensagens nele",
"GROUPS_DISABLED_RESTRICTED": "As mensagens de grupo estão desativadas — ative gratuitamente"
},
"REPLYBOX": {
"REPLY": "Responder",
"PRIVATE_NOTE": "Mensagem Privada",
"SEND": "Enviar",
"CREATE": "Enviar",
"INSERT_READ_MORE": "Ler mais",
"DISMISS_REPLY": "Dispensar resposta",
"REPLYING_TO": "Respondendo a:",
"TIP_EMOJI_ICON": "Mostrar seletor de emoji",
"TIP_ATTACH_ICON": "Anexar arquivos",
"TIP_AUDIORECORDER_ICON": "Gravar áudio",
"TIP_AUDIORECORDER_PERMISSION": "Permitir acesso ao áudio",
"TIP_AUDIORECORDER_ERROR": "Não foi possível abrir o áudio",
"AUDIO_CONVERSION_FAILED": "Falha na conversão do áudio. Tente novamente.",
"DRAG_DROP": "Arraste e solte aqui para anexar",
"START_AUDIO_RECORDING": "Iniciar gravação de áudio",
"STOP_AUDIO_RECORDING": "Parar gravação de áudio",
"": "",
"EMAIL_HEAD": {
"TO": "Para",
"ADD_BCC": "Adicionar cco",
"CC": {
"LABEL": "CC",
"PLACEHOLDER": "E-mails separados por vírgulas",
"ERROR": "Por favor, insira endereços de e-mail válidos"
},
"BCC": {
"LABEL": "Cco",
"PLACEHOLDER": "E-mails separados por vírgulas",
"ERROR": "Por favor, insira endereços de e-mail válidos"
}
},
"UNDEFINED_VARIABLES": {
"TITLE": "Variáveis não definidas",
"MESSAGE": "Você tem {undefinedVariablesCount} variáveis não definidas em sua mensagem: {undefinedVariables}. Gostaria de enviar a mensagem mesmo assim?",
"CONFIRM": {
"YES": "Enviar",
"CANCEL": "Cancelar"
}
},
"QUOTED_REPLY": {
"ENABLE_TOOLTIP": "Incluir o encadeamento de e-mails citado",
"DISABLE_TOOLTIP": "Não incluir o encadeamento de e-mails citado",
"REMOVE_PREVIEW": "Remover o encadeamento de e-mails citado",
"COLLAPSE": "Recolher a prévia",
"EXPAND": "Expandir a prévia"
},
"SCHEDULE_SEND": "Agendar envio"
},
"VISIBLE_TO_AGENTS": "Mensagem Privada: Apenas visível para você e seu time",
"CHANGE_STATUS": "Estado da conversa mudou",
"CHANGE_STATUS_FAILED": "Mudança de status da conversa falhou",
"CHANGE_AGENT": "Novo agente atribuído",
"CHANGE_AGENT_FAILED": "Falha ao atribuir outro agente",
"ASSIGN_LABEL_SUCCESFUL": "Etiqueta atribuída com sucesso",
"ASSIGN_LABEL_FAILED": "Falha ao atribuir etiqueta",
"CHANGE_TEAM": "Status da conversa mudou",
"SUCCESS_DELETE_CONVERSATION": "Conversa excluída com sucesso",
"FAIL_DELETE_CONVERSATION": "Não foi possível excluir a conversa! Tente novamente",
"FILE_SIZE_LIMIT": "O arquivo excede os {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB do limite para anexos",
"MESSAGE_ERROR": "Não foi possível enviar esta mensagem, por favor, tente novamente mais tarde",
"SENT_BY": "Enviado por:",
"BOT": "Robôs",
"WHATSAPP": "WhatsApp",
"SEND_FAILED": "Não foi possível enviar a mensagem! Tente novamente",
"TRY_AGAIN": "tentar novamente",
"ASSIGNMENT": {
"SELECT_AGENT": "selecionar Agente",
"REMOVE": "Excluir",
"ASSIGN": "Atribuir"
},
"CONTEXT_MENU": {
"COPY": "Copiar",
"REPLY_TO": "Responder mensagem",
"DELETE": "Excluir",
"CREATE_A_CANNED_RESPONSE": "Adicionar às respostas prontas",
"TRANSLATE": "Traduzir",
"COPY_PERMALINK": "Copiar link para a mensagem",
"LINK_COPIED": "URL da mensagem copiada para a área de transferência",
"DELETE_CONFIRMATION": {
"TITLE": "Você tem certeza que deseja excluir esta mensagem?",
"MESSAGE": "Você não pode desfazer essa ação",
"DELETE": "Excluir",
"CANCEL": "Cancelar"
},
"EDIT": {
"LABEL": "Editar",
"TITLE": "Editar mensagem",
"PLACEHOLDER": "Digite o conteúdo da mensagem",
"SAVE": "Salvar",
"CANCEL": "Cancelar",
"SUCCESS": "Mensagem editada com sucesso",
"ERROR": "Falha ao editar mensagem",
"EMPTY_CONTENT": "O conteúdo da mensagem não pode estar vazio"
}
},
"SIDEBAR": {
"CONTACT": "Contatos",
"COPILOT": "Copiloto"
},
"VOICE_WIDGET": {
"INCOMING_CALL": "Chamada recebida",
"OUTGOING_CALL": "Chamada realizada",
"CALL_IN_PROGRESS": "Chamada em andamento",
"NOT_ANSWERED_YET": "Ainda não respondido",
"HANDLED_IN_ANOTHER_TAB": "Sendo atendida em outra aba",
"REJECT_CALL": "Recusar",
"JOIN_CALL": "Entrar na chamada",
"END_CALL": "Encerrar chamada"
},
"INBOX": {
"WHATSAPP_PROVIDER_CONNECTION": {
"NOT_CONNECTED": "O WhatsApp não está conectado. Por favor conecte o seu dispositivo novamente.",
"NOT_CONNECTED_CONTACT_ADMIN": "O WhatsApp não está conectado. Clique no botão ao lado para tentar reconectar, ou contate o seu administrador para conectar o dispositivo novamente.",
"LINK_DEVICE": "Conectar dispositivo",
"RECONNECT_FAILED": "Falha ao reconectar. Por favor, contate o seu administrador para conectar o dispositivo novamente."
}
}
},
"EMAIL_TRANSCRIPT": {
"TITLE": "Enviar transcrição de conversa",
"DESC": "Enviar uma cópia da transcrição da conversa para o endereço de e-mail especificado",
"SUBMIT": "Enviar",
"CANCEL": "Cancelar",
"SEND_EMAIL_SUCCESS": "A transcrição do chat foi enviada com sucesso",
"SEND_EMAIL_ERROR": "Ocorreu um erro, por favor tente novamente",
"FORM": {
"SEND_TO_CONTACT": "Envie a transcrição para o cliente",
"SEND_TO_AGENT": "Envie a transcrição para o agente designado",
"SEND_TO_OTHER_EMAIL_ADDRESS": "Enviar a transcrição para outro endereço de e-mail",
"EMAIL": {
"PLACEHOLDER": "Digite um endereço de e-mail",
"ERROR": "Por favor, insira um endereço de e-mail válido"
}
}
},
"ONBOARDING": {
"TITLE": "Olá, 👋. Bem-vindo ao {installationName}!",
"DESCRIPTION": "Obrigado por se inscrever. Queremos que você aproveite o máximo de {installationName}. Aqui estão algumas coisas que você consegue fazer em {installationName} para que tenha uma experiência agradável.",
"GREETING_MORNING": "👋 Bom dia, {name}. Bem-vindo a {installationName}.",
"GREETING_AFTERNOON": "👋 Boa tarde, {name}. Bem-vindo a {installationName}.",
"GREETING_EVENING": "👋 Boa noite, {name}. Bem-vindo a {installationName}.",
"READ_LATEST_UPDATES": "Leia as últimas atualizações",
"ALL_CONVERSATION": {
"TITLE": "Todas as suas conversas em um só lugar",
"DESCRIPTION": "Veja todas as conversas dos seus clientes em um único painel. Você pode filtrar as conversas pelo canal de entrada, rótulo e status.",
"NEW_LINK": "Clique aqui para criar uma caixa de entrada"
},
"TEAM_MEMBERS": {
"TITLE": "Convidar membros de seu time",
"DESCRIPTION": "Já que você está se preparando para conversar com seu cliente, traga seus colegas para ajudá-lo. Você pode convidar seus colegas adicionando os endereços de e-mail deles na lista de agentes.",
"NEW_LINK": "Clique aqui para convidar um membro do time"
},
"LABELS": {
"TITLE": "Organizar conversas com etiquetas",
"DESCRIPTION": "Etiquetas fornecem uma forma mais fácil de organizar a sua conversa. Criar algumas etiquetas como #solicitação-suporte, #fatura-assunto etc., assim você poderá futuramente utiliza-las em uma conversa posteriormente.",
"NEW_LINK": "Clique aqui para criar etiquetas"
},
"CANNED_RESPONSES": {
"TITLE": "Criar respostas prontas",
"DESCRIPTION": "Os modelos de respostas prontas ajudam você a responder rapidamente a uma conversa. Os agentes podem digitar o caractere '/' seguido pelo atalho para inserir uma resposta.",
"NEW_LINK": "Clique aqui para criar uma resposta pronta"
}
},
"CONVERSATION_SIDEBAR": {
"ASSIGNEE_LABEL": "Agente atribuído",
"SELF_ASSIGN": "Atribuir a mim",
"TEAM_LABEL": "Time atribuído",
"SELECT": {
"PLACEHOLDER": "Nenhuma"
},
"ACCORDION": {
"CONTACT_DETAILS": "Detalhes do contato",
"SCHEDULED_MESSAGES": "Mensagens agendadas",
"CONVERSATION_ACTIONS": "Ações da conversa",
"CONVERSATION_LABELS": "Etiquetas da conversa",
"CONVERSATION_INFO": "Informação da conversa",
"CONTACT_NOTES": "Notas do contato",
"CONTACT_ATTRIBUTES": "Atributos do contato",
"PREVIOUS_CONVERSATION": "Conversas anteriores",
"MACROS": "Macros",
"LINEAR_ISSUES": "Problemas do Linear vinculados",
"SHOPIFY_ORDERS": "Shopify Orders"
},
"SHOPIFY": {
"ORDER_ID": "Order #{id}",
"ERROR": "Error loading orders",
"NO_SHOPIFY_ORDERS": "No orders found",
"FINANCIAL_STATUS": {
"PENDING": "Pendentes",
"AUTHORIZED": "Authorized",
"PARTIALLY_PAID": "Partially Paid",
"PAID": "Paid",
"PARTIALLY_REFUNDED": "Partially Refunded",
"REFUNDED": "Refunded",
"VOIDED": "Voided"
},
"FULFILLMENT_STATUS": {
"FULFILLED": "Fulfilled",
"PARTIALLY_FULFILLED": "Partially Fulfilled",
"UNFULFILLED": "Unfulfilled"
}
}
},
"SCHEDULED_MESSAGES": {
"NEW_BUTTON": "Agendar mensagem",
"PAST_MESSAGES_SECTION": "Enviadas",
"EMPTY_STATE": "Ainda não há mensagens agendadas.",
"STATUS": {
"DRAFT": "Rascunho",
"PENDING": "Pendente",
"SENT": "Enviada",
"FAILED": "Falhou"
},
"ITEM": {
"SCHEDULED_FOR": "Agendada para {time}",
"NO_SCHEDULE": "Sem agendamento",
"TEMPLATE_PREVIEW": "Modelo: {name}",
"TEMPLATE_LABEL": "Modelo: {name}",
"ATTACHMENT_PREVIEW": "Anexo: {filename}",
"ATTACHMENT_LABEL": "Anexo: {filename}",
"EMPTY_PREVIEW": "Sem conteúdo",
"EXPAND": "Expandir",
"COLLAPSE": "Recolher",
"GO_TO_MESSAGE": "Ir para a mensagem",
"SEARCHING_MESSAGE": "Buscando mensagem...",
"MESSAGE_NOT_FOUND": "A mensagem vinculada não foi encontrada. Ela pode ter sido excluída."
},
"MODAL": {
"TITLE_NEW": "Agendar mensagem",
"TITLE_EDIT": "Editar mensagem agendada",
"MESSAGE_LABEL": "Mensagem",
"MESSAGE_PLACEHOLDER": "Escreva sua mensagem...",
"DATETIME_LABEL": "Data e hora de envio",
"ATTACHMENT_LABEL": "Anexo",
"ATTACHMENT_ADD": "Anexar arquivo",
"ATTACHMENT_CURRENT": "Anexo atual: {filename}",
"TEMPLATE_SELECT": "Usar modelo",
"TEMPLATE_SELECTED": "Modelo: {name}",
"TEMPLATE_ACTION": "Agendar mensagem",
"CANCEL": "Cancelar",
"SAVE_DRAFT": "Salvar como rascunho",
"SCHEDULE": "Agendar",
"SHORTCUTS": {
"TOMORROW_MORNING": "Amanhã de manhã",
"TOMORROW_AFTERNOON": "Amanhã à tarde",
"MONDAY_MORNING": "Segunda-feira de manhã",
"CUSTOM": "Digitar data e hora"
},
"CUSTOM_INPUT_PLACEHOLDER": "ex: amanhã às 14h, próxima sexta de manhã",
"CUSTOM_INPUT_HINT": "Tente: amanhã às 15h, próxima segunda, 20 de março às 10h",
"PARSED_DATE_IN_PAST": "Esta data já passou",
"DATEPICKER_TOOLTIP": "Escolher no calendário",
"SCHEDULE_LABEL": "Programar envio"
},
"CONFIRM_CLOSE": {
"TITLE": "Alterações não salvas",
"MESSAGE": "Você tem conteúdo não salvo. Deseja descartar suas alterações?",
"CONTINUE_EDITING": "Continuar editando",
"DISCARD": "Descartar",
"CANCEL": "Cancelar"
},
"CONFIRM_DELETE": {
"TITLE": "Excluir mensagem agendada",
"MESSAGE": "Tem certeza de que deseja excluir esta mensagem agendada? Esta ação não pode ser desfeita.",
"CANCEL": "Cancelar",
"DELETE": "Excluir"
},
"ERRORS": {
"CONTENT_REQUIRED": "Adicione uma mensagem, template ou anexo antes de salvar.",
"CONTENT_TOO_LONG": "A mensagem é muito longa. Máximo de {maxLength} caracteres permitidos.",
"DATETIME_REQUIRED": "Selecione uma data e hora para agendar a mensagem.",
"SCHEDULE_IN_PAST": "O horário agendado deve ser no futuro.",
"SAVE_FAILED": "Não foi possível salvar a mensagem agendada. Por favor, tente novamente.",
"DELETE_FAILED": "Não foi possível excluir a mensagem agendada. Por favor, tente novamente."
},
"META": {
"TOOLTIP": "Agendada em {time} por {author}",
"YOU": "Você",
"AUTHOR_YOU": "{name} (Você)",
"AUTOMATION": "Automação",
"UNKNOWN_AUTHOR": "Desconhecido"
},
"RECURRENCE": {
"SECTION_TITLE": "Recorrências",
"NO_REPEAT": "Não se repete",
"DAILY": "Todos os dias",
"WEEKLY": "Semanal: cada {day}",
"MONTHLY_NTH": "Mensal no(a) {nth} {day}",
"MONTHLY_LAST": "Mensal no(a) último(a) {day}",
"YEARLY": "Anual em {dayNum} de {month}",
"WEEKDAYS": "Todos os dias úteis (seg-sex)",
"CUSTOM": "Personalizado...",
"CUSTOM_MODAL": {
"TITLE": "Recorrência personalizada",
"REPEAT_EVERY": "Repetir a cada",
"FREQ_DAILY": "dia(s)",
"FREQ_WEEKLY": "semana(s)",
"FREQ_MONTHLY": "mês(es)",
"FREQ_YEARLY": "ano(s)",
"UNIT_DAY": "dia | dias",
"UNIT_WEEK": "semana | semanas",
"UNIT_MONTH": "mês | meses",
"UNIT_YEAR": "ano | anos",
"REPEAT_ON": "Repetir em",
"MONTHLY_ON_DAY": "Dia do mês",
"MONTHLY_ON_WEEKDAY": "Dia da semana",
"ENDS": "Termina",
"ENDS_NEVER": "Nunca",
"ENDS_ON_DATE": "Em data",
"ENDS_AFTER": "Após",
"ENDS_OCCURRENCES": "ocorrências",
"DONE": "Concluir",
"CANCEL": "Cancelar"
},
"STATUS_ACTIVE": "Ativa",
"STATUS_DRAFT": "Rascunho",
"STATUS_COMPLETED": "Concluída",
"STATUS_CANCELLED": "Cancelada",
"OCCURRENCES_SENT": "{count} enviadas",
"NEXT_SEND": "Próxima: {time}",
"EXPAND": "Expandir histórico",
"COLLAPSE": "Recolher histórico",
"STOP": "Parar recorrência",
"STOP_CONFIRM": {
"TITLE": "Parar recorrência",
"MESSAGE": "A mensagem pendente será removida e a recorrência será encerrada permanentemente.",
"CONFIRM": "Parar",
"CANCEL": "Cancelar"
},
"EDIT": "Editar recorrência",
"EDIT_WARNING": "Próximo envio: {oldDate} → {newDate}",
"WEEKDAYS_SHORT": {
"SUN": "D",
"MON": "S",
"TUE": "T",
"WED": "Q",
"THU": "Q",
"FRI": "S",
"SAT": "S"
},
"ORDINALS": {
"FIRST": "1º",
"SECOND": "2º",
"THIRD": "3º",
"FOURTH": "4º",
"FIFTH": "5º",
"LAST": "último(a)"
},
"DESCRIPTION": {
"DAILY_ONE": "Todos os dias",
"DAILY_OTHER": "A cada {count} dias",
"WEEKLY_ONE": "Semanal",
"WEEKLY_OTHER": "A cada {count} semanas",
"WEEKLY_ON": "{prefix}: {days}",
"MONTHLY_ONE": "Mensal",
"MONTHLY_OTHER": "A cada {count} meses",
"MONTHLY_ON_WEEKDAY": "{prefix} no(a) {ordinal} {weekday}",
"YEARLY_ONE": "Anual",
"YEARLY_OTHER": "A cada {count} anos",
"UNTIL_DATE": "até {date}",
"AFTER_COUNT": "{count} ocorrências"
},
"RESOLVED_WARNING": "Mensagens agendadas não serão enviadas enquanto a conversa estiver resolvida. Reabra a conversa para retomar o envio."
}
},
"CONVERSATION_CUSTOM_ATTRIBUTES": {
"ADD_BUTTON_TEXT": "Criar atributo",
"NO_RECORDS_FOUND": "Nenhum atributo encontrado",
"UPDATE": {
"SUCCESS": "Atributo atualizado com sucesso",
"ERROR": "Não foi possível atualizar o atributo. Por favor, tente mais tarde"
},
"ADD": {
"TITLE": "Adicionar",
"SUCCESS": "Atributo adicionado com sucesso",
"ERROR": "Não foi possível adicionar o atributo. Por favor, tente mais tarde"
},
"DELETE": {
"SUCCESS": "Atributo excluído com sucesso",
"ERROR": "Não foi possível excluir o atributo. Por favor, tente mais tarde"
},
"ATTRIBUTE_SELECT": {
"TITLE": "Adicionar atributos",
"PLACEHOLDER": "Procurar atributos",
"NO_RESULT": "Nenhum atributo encontrado"
}
},
"EMAIL_HEADER": {
"FROM": "De",
"TO": "Para",
"BCC": "CCO",
"CC": "Cc",
"SUBJECT": "Assunto",
"EXPAND": "Expandir e-mail"
},
"CONVERSATION_PARTICIPANTS": {
"SIDEBAR_MENU_TITLE": "Participantes",
"SIDEBAR_TITLE": "Participantes da conversa",
"NO_RECORDS_FOUND": "Nenhum resultado encontrado",
"ADD_PARTICIPANTS": "Selecionar participantes",
"REMANING_PARTICIPANTS_TEXT": "+{count} participantes",
"REMANING_PARTICIPANT_TEXT": "+{count} participante",
"TOTAL_PARTICIPANTS_TEXT": "{count} pessoas estão participando.",
"TOTAL_PARTICIPANT_TEXT": "{count} pessoa está participando.",
"NO_PARTICIPANTS_TEXT": "Ninguém está participando!",
"WATCH_CONVERSATION": "Participar da conversa",
"YOU_ARE_WATCHING": "Você está participando",
"API": {
"ERROR_MESSAGE": "Não foi possível atualizar, tente novamente!",
"SUCCESS_MESSAGE": "Participantes atualizados!"
}
},
"TRANSLATE_MODAL": {
"TITLE": "Ver conteúdo traduzido",
"DESC": "Você pode visualizar o conteúdo traduzido em cada idioma.",
"ORIGINAL_CONTENT": "Conteúdo original",
"TRANSLATED_CONTENT": "Conteúdo traduzido",
"NO_TRANSLATIONS_AVAILABLE": "Nenhuma tradução está disponível para este conteúdo"
},
"TYPING": {
"ONE": "{user} está digitando",
"TWO": "{user} e {secondUser} estão digitando",
"MULTIPLE": "{user} e {count} outros estão digitando"
},
"COPILOT": {
"TRY_THESE_PROMPTS": "Experimente estes comandos"
},
"GALLERY_VIEW": {
"ERROR_DOWNLOADING": "Não foi possível baixar o anexo. Por favor, tente novamente"
}
}