+
({
tab: "settings",
@@ -53,7 +62,6 @@ export default {
{
id: "settings",
icon: "mdi-cog",
- title: "Configurações",
components: [
"Options",
"Webhook",
@@ -66,7 +74,6 @@ export default {
{
id: "message",
icon: "mdi-message",
- title: "Mensagens",
components: [
"OpenSendMessage",
"HasWhatsapp",
@@ -75,6 +82,16 @@ export default {
"MyChats",
],
},
+ {
+ id: "profile",
+ icon: "mdi-account",
+ components: [
+ "ConnectionAlert",
+ "BasicInfo",
+ "ProfilePhoto",
+ "Privacy",
+ ],
+ },
],
}),
props: {
diff --git a/src/components/instance/InstanceHeader.vue b/src/components/instance/InstanceHeader.vue
index f9b9b2a..8ba0446 100644
--- a/src/components/instance/InstanceHeader.vue
+++ b/src/components/instance/InstanceHeader.vue
@@ -7,20 +7,15 @@
{{ statusMapper[instance.instance.status].icon }}
-
+
@@ -36,7 +31,24 @@
@click="copyApikey"
>
mdi-key
- {{ instance.instance.apikey.slice(0, 10) }}...
+ {{
+ (instance.instance?.apikey || "").slice(
+ 0,
+ apikeyReveled ? undefined : 7
+ )
+ }}{{ apikeyReveled ? "" : "..." }}
+
+
+ {{ apikeyReveled ? "mdi-eye-off" : "mdi-eye" }}
+
+
{{ copied ? "mdi-check" : "mdi-content-copy" }}
@@ -68,7 +80,7 @@
size="small"
>
mdi-restart
- {{ restart.success ? "Reiniciada!" : "Reiniciar" }}
+ {{ restart.success ? `${$t("restarted")}` : `${$t("restart")}` }}
mdi-cellphone-nfc-off
- {{ disconnect.confirm ? "Tem Certeza?" : "Desconectar" }}
+ {{ disconnect.confirm ? `${$t("sure")}` : `${$t("disconnect")}` }}
@@ -90,6 +102,7 @@
+
+
diff --git a/src/components/instance/profile/ConnectionAlert.vue b/src/components/instance/profile/ConnectionAlert.vue
new file mode 100644
index 0000000..27632db
--- /dev/null
+++ b/src/components/instance/profile/ConnectionAlert.vue
@@ -0,0 +1,25 @@
+
+
+ Não é possível alterar o perfil de uma instância desconectada.
+
+
+
+
+
+
diff --git a/src/components/instance/profile/Privacy.vue b/src/components/instance/profile/Privacy.vue
new file mode 100644
index 0000000..5d4b5ef
--- /dev/null
+++ b/src/components/instance/profile/Privacy.vue
@@ -0,0 +1,247 @@
+
+
+
+ mdi-shield-account
+ {{ $t("privacy.title") }}
+
+
+ mdi-chevron-down
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("save") }}
+
+
+
+
+
+
+
+
diff --git a/src/components/instance/profile/ProfilePhoto.vue b/src/components/instance/profile/ProfilePhoto.vue
new file mode 100644
index 0000000..39edbc5
--- /dev/null
+++ b/src/components/instance/profile/ProfilePhoto.vue
@@ -0,0 +1,179 @@
+
+
+
+ mdi-account-box
+ {{ $t("profilePicture.title") }}
+
+
+
+ mdi-chevron-down
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+ mdi-account-question
+ {{ $t("profilePicture.noPhoto") }}
+
+
+
+
+
+ mdi-upload
+ {{ $t("profilePicture.upload") }}
+
+
+
+ mdi-delete
+ {{ $t("profilePicture.remove") }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/instance/settings/Chatwoot.vue b/src/components/instance/settings/Chatwoot.vue
index a1ed595..1748cef 100644
--- a/src/components/instance/settings/Chatwoot.vue
+++ b/src/components/instance/settings/Chatwoot.vue
@@ -36,9 +36,9 @@
class="mb-3"
:rules="[
(url) => {
- if (!url) return 'URL é obrigatório';
+ if (!url) return this.$t('required', { field: 'URL' });
if (!url.startsWith('http'))
- return 'URL deve começar com http ou https';
+ return this.$t('httpHttps', { field: 'URL' });
return true;
},
]"
@@ -48,7 +48,7 @@
+
+
+
+
+
+
+ {{ $t("chatwoot.signMsg") }}
+ {{ $t("chatwoot.signMsgHelp") }}
+
+
+
+
+
- Assinar mensagens
+ {{ $t("chatwoot.reopenConversation") }}
- Adiciona o nome do atendente na primeira linha da mensagem
+ {{ $t("chatwoot.reopenConversationHelp") }}
+
- Reabrir conversa
+ {{ $t("chatwoot.conversationPending") }}
+
+ {{ $t("chatwoot.conversationPendingHelp") }}
+
+
+
+
+
+
+
+ {{ $t("chatwoot.importcontacts") }}
- Reabre a conversa do cliente quando ele inicia uma nova
- conversa em vez de criar uma nova conversa
+ {{ $t("chatwoot.importcontactsHelp") }}
@@ -118,25 +190,51 @@
- Iniciar conversas como pendente
+ {{ $t("chatwoot.importmessages") }}
- Inicia a conversa como pendente ao invés de aberta
+ {{ $t("chatwoot.importmessagesHelp") }}
+
+
+
+
+ {{ $t("chatwoot.autoCreate") }}
+ {{ $t("chatwoot.autoCreateHelp") }}
+
+
+
-
+
-
- Como configurar o chatwoot?
+
+ {{ $t("chatwoot.config.btn") }}
import ChatwootConfig from "@/components/modal/ChatwootConfig.vue";
import instanceController from "@/services/instanceController";
-
+import { useAppStore } from "@/store/app";
const defaultObj = () => ({
enabled: false,
url: "",
account_id: "",
token: "",
sign_msg: true,
+ sign_delimiter: "\n",
reopen_conversation: true,
conversation_pending: false,
+ auto_create: undefined,
+ import_contacts: false,
+ import_messages: false,
+ days_limit_import_messages: 0,
});
export default {
@@ -192,14 +295,19 @@ export default {
loading: false,
error: false,
valid: false,
+ AppStore: useAppStore(),
chatwootData: {
enabled: false,
url: "",
account_id: "",
token: "",
sign_msg: true,
+ sign_delimiter: "\n",
reopen_conversation: true,
conversation_pending: false,
+ import_contacts: false,
+ import_messages: false,
+ days_limit_import_messages: 0,
},
defaultChatwootData: {
enabled: false,
@@ -207,8 +315,12 @@ export default {
account_id: "",
token: "",
sign_msg: true,
+ sign_delimiter: "\n",
reopen_conversation: true,
conversation_pending: false,
+ import_contacts: false,
+ import_messages: false,
+ days_limit_import_messages: 0,
},
}),
methods: {
@@ -244,11 +356,11 @@ export default {
const chatwootData = await instanceController.chatwoot.get(
this.instance.instance.instanceName
);
- this.chatwootData = Object.assign(defaultObj(), chatwootData || {});
- this.defaultChatwootData = Object.assign(
- defaultObj(),
- chatwootData || {}
- );
+
+ const validData = chatwootData._doc || chatwootData;
+
+ this.chatwootData = Object.assign(defaultObj(), validData || {});
+ this.defaultChatwootData = Object.assign(defaultObj(), validData || {});
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
diff --git a/src/components/instance/settings/Options.vue b/src/components/instance/settings/Options.vue
index 3b5770f..760abeb 100644
--- a/src/components/instance/settings/Options.vue
+++ b/src/components/instance/settings/Options.vue
@@ -1,8 +1,13 @@
-
+
mdi-cellphone-cog
- Comportamento
+ {{ $t("options.title") }}
@@ -35,7 +40,7 @@
class="flex-grow-1 flex-shrink-0"
v-model="optionsData.msg_call"
:disabled="loading || !optionsData.reject_call"
- label="Mensagem de rejeição"
+ :label="$t('options.msgCall')"
hide-details
style="min-width: 200px"
>
@@ -45,7 +50,7 @@
class="flex-grow-0"
v-model="optionsData.groups_ignore"
:disabled="loading"
- label="Ignorar grupos"
+ :label="$t('options.groupsIgnore')"
hide-details
density="compact"
>
@@ -54,7 +59,7 @@
class="flex-grow-0"
v-model="optionsData.always_online"
:disabled="loading"
- label="Sempre online"
+ :label="$t('options.alwaysOnline')"
hide-details
density="compact"
>
@@ -63,7 +68,7 @@
class="flex-grow-0"
v-model="optionsData.read_messages"
:disabled="loading"
- label="Marcar mensagens como lidas"
+ :label="$t('options.readMessages')"
hide-details
density="compact"
>
@@ -72,10 +77,24 @@
class="flex-grow-0"
v-model="optionsData.read_status"
:disabled="loading"
- label="Marcar status como visto"
+ :label="$t('options.readStatus')"
hide-details
density="compact"
>
+
@@ -91,7 +110,7 @@
@click="saveOptions"
variant="tonal"
>
- Salvar
+ {{ $t("save") }}
@@ -99,16 +118,17 @@
diff --git a/src/components/instance/settings/Webhook.vue b/src/components/instance/settings/Webhook.vue
index 367420c..a5cc65f 100644
--- a/src/components/instance/settings/Webhook.vue
+++ b/src/components/instance/settings/Webhook.vue
@@ -36,26 +36,14 @@
class="mb-3"
:rules="[
(url) => {
- if (!url) return 'URL é obrigatório';
+ if (!url) return this.$t('required', { field: 'URL' });
if (!url.startsWith('http'))
- return 'URL deve começar com http ou https';
+ return this.$t('httpHttps', { field: 'URL' });
return true;
},
]"
/>
-
-
+
@@ -72,11 +60,17 @@
+ >
+
+ {{ $t("webhook.byEvents") }}
+
+ {{ $t("webhook.byEventsHelp") }}
+
+
+
@@ -84,7 +78,7 @@
- Salvar
+ {{ $t("save") }}
@@ -108,7 +102,7 @@
diff --git a/src/helpers/copyToClipboard.js b/src/helpers/copyToClipboard.js
new file mode 100644
index 0000000..92c9f81
--- /dev/null
+++ b/src/helpers/copyToClipboard.js
@@ -0,0 +1,16 @@
+export default (value) => {
+ if (navigator.clipboard) {
+ navigator.clipboard.writeText(value);
+ } else {
+ const el = document.createElement("textarea");
+ el.value = value;
+ el.setAttribute("readonly", "");
+ el.style.position = "absolute";
+ el.style.left = "-9999px";
+ document.body.appendChild(el);
+ el.select();
+ el.setSelectionRange(0, 99999);
+ document.execCommand("copy");
+ document.body.removeChild(el);
+ }
+}
\ No newline at end of file
diff --git a/src/helpers/mappers/typebotStatus.js b/src/helpers/mappers/typebotStatus.js
new file mode 100644
index 0000000..fe656ea
--- /dev/null
+++ b/src/helpers/mappers/typebotStatus.js
@@ -0,0 +1,19 @@
+// opened, paused, closed
+
+export default {
+ opened: {
+ color: "green",
+ text: "Aberto",
+ icon: "mdi-play",
+ },
+ paused: {
+ color: "warning",
+ text: "Pausado",
+ icon: "mdi-pause",
+ },
+ closed: {
+ color: "red",
+ text: "Fechado",
+ icon: "mdi-stop",
+ },
+}
\ No newline at end of file
diff --git a/src/i18n/en.js b/src/i18n/en.js
new file mode 100644
index 0000000..c84f9a8
--- /dev/null
+++ b/src/i18n/en.js
@@ -0,0 +1,215 @@
+// src/i18n/en.js
+import { en } from 'vuetify/locale'
+
+export default {
+ $vuetify: { ...en },
+ all: "All",
+ close: "Close",
+ cancel: "Cancel",
+ restart: "Restart",
+ restarted: "Restarted",
+ refresh: "Refresh",
+ disconnect: "Disconnect",
+ sure: "Sure?",
+ save: "Save",
+ step: "Passo {step}",
+ instance: "Instance | Instances",
+ search: "Search",
+ loading: "Loading",
+ noInstances: "No instances found",
+ unknown: "Unknown",
+ required: "{field} is required",
+ maxLength: "{field} must have a maximum of {length} characters",
+ https: "{field} must start with https://",
+ httpHttps: "{field} must start with http:// or https://",
+ enabled: "Enabled",
+ events: "Events",
+ name: "Name",
+ version: {
+ availableFrom: "Available from version {version}",
+ },
+ status: {
+ close: "Disconnected",
+ connecting: "Connecting",
+ open: "Connected",
+ },
+ toggleSelect: {
+ all: "Select all",
+ none: "Deselect all",
+ },
+ about: {
+ title: "About",
+ description: "Evolution Manager makes it easy to manage your APIs with an intuitive interface. It was created by independent developers, focusing on improving the user experience and administration of API functionalities.",
+ contribute: "Contribute to the project",
+ dataProcess: {
+ title: "Data Processing",
+ description: "Data processing and storage occur
locally in your browser, without the use of a centralized backend. This reinforces security and privacy, keeping your confidential information protected.",
+ https: "Due to all processing being done in the browser, it is necessary to access the Evolution API server through a secure connection (HTTPS)."
+ },
+ version: "Version",
+ },
+ createInstance: {
+ title: "Create instance",
+ name: "Instance name",
+ configInfo: "The WebHook, WebSocket, RabbitMQ, Chatwoot, and Typebot can be configured after creating the instance.",
+ integration: "Integration",
+ number: "Telephone number identifier",
+ },
+ contribute: {
+ title: "Contribute",
+ via: "Contribute via",
+ button: "Contribute",
+ },
+ connection: {
+ title: "Configure connection",
+ action: "Connect",
+ saved: "Connection saved | Connections saved",
+ },
+ instanceTabs: {
+ settings: "Settings",
+ message: "Messages",
+ profile: "Profile",
+ },
+ connectPhone: {
+ title: "Phone not connected",
+ apiGenericError: "Could not load QR Code, if the error persists, restart the API and try again.",
+ qr: "QR Code",
+ code: "Cdigo",
+ },
+ options: {
+ title: "Behavior",
+ rejectCall: "Reject call",
+ msgCall: "Rejection message",
+ groupsIgnore: "Ignore groups",
+ alwaysOnline: "Always online",
+ readMessages: "Mark messages as read",
+ readStatus: "Mark status as seen",
+ syncfullhistory: "sync full history",
+ },
+ webhook: {
+ byEvents: "Webhook by events",
+ byEventsHelp: "Adds the event name at the end of the URL (ex: /webhook/event_name )",
+ },
+ rabbitmq: {
+ info: "RabbitMQ is used by the API to queue notifications. It is NOT used to send messages."
+ },
+ chatwoot: {
+ account_id: "Account ID",
+ token: "Account Token",
+ dayslimitimportmessages: "Days limit to import messages",
+ signMsg: "Sign messages",
+ signMsgHelp: "Adds the agent name at the first line of the message",
+ signDelimiter: "Signature delimiter",
+ signDelimiterHelp: "Delimiter used to separate the signature from the message (\\n for line break)",
+ reopenConversation: "Reopen conversation",
+ reopenConversationHelp: "Reopens the customer's conversation when he starts a new conversation instead of creating a new conversation",
+ conversationPending: "Start conversation as pending",
+ conversationPendingHelp: "Starts the conversation as pending instead of open",
+ autoCreate: "Create Inbox",
+ autoCreateHelp: "Creates the inbox in Chatwoot if it doesn't exist",
+ importcontacts: "Import contacts",
+ importcontactsHelp: "Import contacts to Chatwoot",
+ importmessages: "Import messages",
+ importmessagesHelp: "Import message history messages to Chatwoot",
+ config: {
+ btn: "How to configure Chatwoot?",
+ title: "How to configure Chatwoot inbox?",
+ fullDoc: "View full documentation",
+ steps: {
+ "1": "Access settings > Inbox and click on \"Add Inbox\"",
+ "2": "Select \"API\" as the inbox type",
+ "3": "Fill in the inbox name and webhook. The values should be exactly as follows:",
+ "4": "Add agents to the inbox.",
+ "5": "Done! Now you can receive messages.",
+ }
+ }
+ },
+ typebot: {
+ typebot: "Typebot flow name",
+ typebotHelp: "The name of the Typebot flow to be used",
+ keywordFinish: "Finish keyword",
+ keywordFinishHelp: "Keyword to finish the flow",
+ expire: "Expiration time (in minutes)",
+ expireHelp: "Time to end the session if there is no interaction",
+ delayMessage: "Message typing time",
+ delayMessageUnit: "in milliseconds",
+ delayMessageHelp: "Typing simulation time",
+ unknownMessage: "Unknown message format",
+ unknownMessageHelp: "Message sent when the message format is not recognized",
+ unknownMessagePlaceholder: "Leave blank to not send message",
+ listeningFromMe: "Listen to messages sent by me",
+ listeningFromMeHelp: "Sends the messages sent by you to the Typebot flow",
+ session: {
+ title: "Typebot sessions",
+ btn: "See 0 sessions | See one session | See {count} sessions",
+ noData: "No sessions found",
+ headers: {
+ variable: "Variables",
+ createdAt: "Started at",
+ updatedAt: "Last message",
+ }
+ },
+ status: {
+ opened: "Open",
+ paused: "Paused",
+ closed: "Closed",
+ }
+ },
+ sendMessage: {
+ title: "Send message",
+ to: "To",
+ noContacts: "No contacts",
+ message: "Message",
+ presence: "Presence",
+ delay: "Delay",
+ delayHelp: "Delay in milliseconds",
+ send: "Send",
+ success: "Message sent successfully | Messages sent successfully",
+ },
+ phoneHasWhatsApp: {
+ title: "Has WhatsApp?",
+ phone: "WhatsApp number",
+ verify: "Verify",
+ exists: "WhatsApp found",
+ notExists: "WhatsApp not found",
+ invalid: "Invalid number",
+ },
+ contacts: {
+ title: "My contacts",
+ },
+ groups: {
+ title: "My groups",
+ headers: { creation: "Created at", }
+ },
+ chats: {
+ title: "My chats",
+ headers: { lastMsgTimestamp: "Last message", }
+ },
+ profile: {
+ title: "Name and Status",
+ name: "Name",
+ status: "Status"
+ },
+ profilePicture: {
+ title: "Profile Picture",
+ noPhoto: "No profile photo",
+ upload: "Select Photo",
+ remove: "Remove Photo",
+ },
+ privacy: {
+ title: "Privacy",
+ lastSeen: "Last Seen",
+ online: "Online",
+ profilePhoto: "Profile Photo",
+ status: "Status",
+ readreceipts: "Read Receipts",
+ groupadd: "Be Added to Groups",
+ options: {
+ all: "Everyone",
+ contacts: "My Contacts",
+ contactBlacklist: "My Contacts, Except Blacklisted",
+ matchLastSeen: "Match Last Seen",
+ none: "Nobody",
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/i18n/es.js b/src/i18n/es.js
new file mode 100644
index 0000000..b9aac3d
--- /dev/null
+++ b/src/i18n/es.js
@@ -0,0 +1,215 @@
+// src/i18n/en.js
+import { es } from 'vuetify/locale'
+
+export default {
+ $vuetify: { ...es },
+ all: "Todos",
+ close: "Cerrar",
+ cancel: "Cancelar",
+ restart: "Restart",
+ restarted: "Restarted",
+ refresh: "Actualizar",
+ disconnect: "Desconectar",
+ sure: "Estas Seguro?",
+ save: "Guardar",
+ step: "Passo {step}",
+ instance: "Instancia | Instancias",
+ search: "Buscar",
+ loading: "Cargando",
+ noInstances: "No se encontraron instancias",
+ unknown: "Unknown",
+ required: "{field} es requerido",
+ maxLength: "{field} debe tener un máximo de {length} caracteres",
+ https: "{field} debe comenzar con https://",
+ httpHttps: "{field} debe comenzar con http:// or https://",
+ enabled: "Activar",
+ events: "Eventos",
+ name: "Nombre",
+ version: {
+ availableFrom: "Disponible desde la versión {version}",
+ },
+ status: {
+ close: "Desconectado",
+ connecting: "Conectando",
+ open: "Conectado",
+ },
+ toggleSelect: {
+ all: "Seleccionar todos",
+ none: "Desmarcar todos",
+ },
+ about: {
+ title: "Acerca de",
+ description: "Evolution Manager facilita la gestión de sus API con una interfaz intuitiva. Fue creado por desarrolladores independientes, enfocándose en mejorar la experiencia del usuario y la administración de las funcionalidades API.",
+ contribute: "Contribuir con proyecto",
+ dataProcess: {
+ title: "Procesamiento de datos",
+ description: "El procesamiento y almacenamiento de datos se produce
localmente en su navegador, sin el uso de un servidor centralizado. Esto refuerza la seguridad y privacidad, manteniendo protegida su información confidencial.",
+ https: "Debido a que todo el procesamiento se realiza en el navegador, es necesario acceder al servidor API de Evolution a través de una conexión segura (HTTPS)."
+ },
+ version: "Version",
+ },
+ createInstance: {
+ title: "Crear instancia",
+ name: "Nombre de la instancia",
+ configInfo: "El WebHook, WebSocket, RabbitMQ, Chatwoot y Typebot se pueden configurar después de crear la instancia.",
+ integration: "Integración",
+ number: "Identificador de número de teléfono",
+ },
+ contribute: {
+ title: "Contribuir",
+ via: "Contribuir a través de",
+ button: "Contribuir",
+ },
+ connection: {
+ title: "Configurar conexión",
+ action: "Conectar",
+ saved: "Conexión guardada | Conexiones guardadas",
+ },
+ instanceTabs: {
+ settings: "Ajustes",
+ message: "Mensajes",
+ profile: "Perfil",
+ },
+ connectPhone: {
+ title: "Teléfono no conectado",
+ apiGenericError: "No se pudo cargar el código QR. Si el error persiste, reinicie la API y vuelva a intentarlo..",
+ qr: "QR Code",
+ code: "Código",
+ },
+ options: {
+ title: "Comportamiento",
+ rejectCall: "Rechazar Llamadas",
+ msgCall: "Mensaje de rechazo",
+ groupsIgnore: "Ignorar Grupos",
+ alwaysOnline: "Siempre en línea",
+ readMessages: "Marcar mensajes como leídos",
+ readStatus: "Marcar estado de lectura",
+ syncfullhistory: "Sincronizar el historial completo",
+ },
+ webhook: {
+ byEvents: "Webhook por eventos",
+ byEventsHelp: "Agrega nombre del evento al final de la URL. (ex: /webhook/event_name )",
+ },
+ rabbitmq: {
+ info: "La API utiliza RabbitMQ para poner en cola las notificaciones. NO se utiliza para enviar mensajes.."
+ },
+ chatwoot: {
+ account_id: "ID de Cuenta",
+ token: "Token de Cuenta",
+ dayslimitimportmessages: "Límite de días para importar mensajes",
+ signMsg: "Firmar en mensajes",
+ signMsgHelp: "Agrega el nombre del agente en la primera línea del mensaje.",
+ signDelimiter: "Delimitador de firma",
+ signDelimiterHelp: "Delimitador utilizado para separar la firma del mensaje (\\n para salto de línea)",
+ reopenConversation: "Reabrir conversación",
+ reopenConversationHelp: "Vuelve a abrir la conversación del cliente cuando inicia una nueva conversación en lugar de crear una nueva conversación.",
+ conversationPending: "Iniciar conversación en estado pendiente",
+ conversationPendingHelp: "Inicia la conversación como pendiente en lugar de abierta",
+ autoCreate: "Crear bandeja de entrada",
+ autoCreateHelp: "Crea la bandeja de entrada en Chatwoot si no existe",
+ importcontacts: "Importar contactos",
+ importcontactsHelp: "Importa contactos a Chatwoot",
+ importmessages: "Importar mensajes",
+ importmessagesHelp: "Importa mensajes historioco de mensajes a Chatwoot",
+ config: {
+ btn: "Cómo configurar Chatwoot?",
+ title: "Cómo configurar la bandeja de entrada de Chatwoot?",
+ fullDoc: "Ver documentación completa",
+ steps: {
+ "1": "Accede a configuración > Bandeja de entrada y haz clic en\"Add Inbox\"",
+ "2": "Seleccionar \"API\" como el tipo de bandeja de entrada",
+ "3": "Complete el nombre de la bandeja de entrada y el webhook. Los valores deben ser exactamente los siguientes:",
+ "4": "Agregar agentes a la bandeja de entrada.",
+ "5": "¡Hecho! Ahora puedes recibir mensajes.",
+ }
+ }
+ },
+ typebot: {
+ typebot: "Nombre del flujo de Typebot",
+ typebotHelp: "El nombre del flujo de Typebot que se utilizará.",
+ keywordFinish: "Palabra clave Finalizar",
+ keywordFinishHelp: "Palabra clave para finalizar el flujo",
+ expire: "Tiempo de vencimiento (en minutos)",
+ expireHelp: "Hora de finalizar la sesión si no hay interacción",
+ delayMessage: "Tiempo de escritura de mensajes",
+ delayMessageUnit: "en milisegundos",
+ delayMessageHelp: "Tiempo de simulación de escritura",
+ unknownMessage: "Mensaje para Formato desconocido",
+ unknownMessageHelp: "Mensaje enviado cuando no se reconoce el formato del mensaje",
+ unknownMessagePlaceholder: "Dejar en blanco para no enviar mensaje",
+ listeningFromMe: "Escuchar mensajes enviados por mi",
+ listeningFromMeHelp: "Envía los mensajes enviados por usted al flujo de Typebot",
+ session: {
+ title: "Sesiones de Typebot",
+ btn: "Ver 0 sesiones | Ver una sesión | Ver {count} sesiónes",
+ noData: "No se encontraron sesiones",
+ headers: {
+ variable: "Variables",
+ createdAt: "Empezó a las",
+ updatedAt: "Ultimo mensaje",
+ }
+ },
+ status: {
+ opened: "Abierto",
+ paused: "En pausa",
+ closed: "Cerrado",
+ }
+ },
+ sendMessage: {
+ title: "Enviar mensaje",
+ to: "A",
+ noContacts: "Sin contactos",
+ message: "Mensaje",
+ presence: "Presence",
+ delay: "Delay",
+ delayHelp: "Retraso en milisegundos",
+ send: "Enviar",
+ success: "Mensaje enviado con éxito | Mensajes enviados exitosamente",
+ },
+ phoneHasWhatsApp: {
+ title: "¿Tiene WhatsApp?",
+ phone: "Número whatsapp",
+ verify: "Verificar",
+ exists: "WhatsApp found",
+ notExists: "WhatsApp not found",
+ invalid: "Número invalido",
+ },
+ contacts: {
+ title: "Mis contactos",
+ },
+ groups: {
+ title: "Mis grupos",
+ headers: { creation: "Creado en", }
+ },
+ chats: {
+ title: "Mis chats",
+ headers: { lastMsgTimestamp: "Ultimo mensaje", }
+ },
+ profile: {
+ title: "Nombre y estado",
+ name: "Nombre",
+ status: "Estado"
+ },
+ profilePicture: {
+ title: "Foto de perfil",
+ noPhoto: "Sin foto de perfil",
+ upload: "Seleccione Foto",
+ remove: "Quitar foto",
+ },
+ privacy: {
+ title: "Privacidad",
+ lastSeen: "Ultima vez visto",
+ online: "Online",
+ profilePhoto: "Foto de perfil",
+ status: "Estado",
+ readreceipts: "Leer recibos",
+ groupadd: "Ser agregado a grupos",
+ options: {
+ all: "Todos",
+ contacts: "Mis contactos",
+ contactBlacklist: "Mis contactos, excepto los de la lista negra",
+ matchLastSeen: "Partido visto por última vez",
+ none: "Nadie",
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/i18n/pt.js b/src/i18n/pt.js
new file mode 100644
index 0000000..6deca97
--- /dev/null
+++ b/src/i18n/pt.js
@@ -0,0 +1,227 @@
+// src/i18n/pt.js
+import { pt } from "vuetify/locale";
+
+export default {
+ $vuetify: { ...pt },
+ all: "Todo | Todos",
+ close: "Fechar",
+ cancel: "Cancelar",
+ restart: "Reiniciar",
+ restarted: "Reiniciada",
+ refresh: "Atualizar",
+ disconnect: "Desconectar",
+ sure: "Tem certeza?",
+ save: "Salvar",
+ step: "Passo {step}",
+ instance: "Instância | Instâncias",
+ search: "Pesquisar",
+ loading: "Carregando",
+ noInstances: "Nenhuma instância encontrada",
+ unknown: "Desconhecido",
+ required: "{field} é obrigatório",
+ maxLength: "{field} deve ter no máximo {length} caracteres",
+ https: "{field} deve começar com https://",
+ httpHttps: "{field} deve começar com http:// ou https://",
+ enabled: "Habilitado",
+ events: "Eventos",
+ name: "Nome",
+ version: {
+ availableFrom: "Disponível a partir da versão {version}",
+ },
+ status: {
+ close: "Desconectado",
+ connecting: "Conectando",
+ open: "Conectado",
+ },
+ toggleSelect: {
+ all: "Selecionar todos",
+ none: "Desmarcar todos",
+ },
+ about: {
+ title: "Sobre",
+ description:
+ "O Evolution Manager facilita a gestão de suas APIs com uma interface intuitiva. Ele foi criado por desenvolvedores independentes, focando em melhorar a experiência do usuário e a administração das funcionalidades da API.",
+ contribute: "Contribua com o projeto",
+ dataProcess: {
+ title: "Processamento de dados",
+ description:
+ "O processamento e armazenamento de dados ocorre
localmente no seu navegador, sem uso de um backend centralizado. Isso reforça a segurança e privacidade, mantendo suas informações confidenciais e protegidas.",
+ https:
+ "Por conta de todo o processamento ser realizado no navegador, é necessário que o servidor da Evolution API seja acessado através de uma conexão segura (HTTPS).",
+ },
+ version: "Versão",
+ },
+ createInstance: {
+ title: "Criar instância",
+ name: "Nome da instância",
+ configInfo:
+ "O WebHook, WebSocket, RabbitMQ, Chatwoot e Typebot poderão ser configurados após a criação da instância.",
+ integration: "Integração",
+ number: "Identificador de número de telefone",
+ },
+ contribute: {
+ title: "Contribuir",
+ via: "Contribua via",
+ button: "Contribua",
+ },
+ connection: {
+ title: "Configurar conexão",
+ action: "Conectar",
+ saved: "Conexão salva | Conexões salvas",
+ },
+ instanceTabs: {
+ settings: "Configurações",
+ message: "Mensagens",
+ profile: "Perfil",
+ },
+ connectPhone: {
+ title: "Telefone não conectado",
+ apiGenericError:
+ "Não foi possível carregar o QR Code, se o erro persistir, reinicie a API e tente novamente.",
+ qr: "QR Code",
+ code: "Código",
+ },
+ options: {
+ title: "Comportamento",
+ rejectCall: "Rejeitar chamada",
+ msgCall: "Mensagem de rejeição",
+ groupsIgnore: "Ignorar grupos",
+ alwaysOnline: "Sempre online",
+ readMessages: "Marcar mensagens como lidas",
+ readStatus: "Marcar status como visto",
+ syncfullhistory: "Sinconizar histórico completo",
+ },
+ webhook: {
+ byEvents: "Webhook por eventos",
+ byEventsHelp:
+ "Adiciona o nome do evento no final da URL (ex: /webhook/event_name )",
+ },
+ rabbitmq: {
+ info: "O RabbitMQ é utilizado pela API para o enfileiramento das notificações. Ele NÃO é utilizado para o envio de mensagens.",
+ },
+ chatwoot: {
+ account_id: "ID da conta",
+ token: "Token da conta",
+ dayslimitimportmessages: "Limite de dias para importar mensagens",
+ signMsg: "Assinar mensagens",
+ signMsgHelp: "Adiciona o nome do atendente na primeira linha da mensagem",
+ signDelimiter: "Separador da assinatura da mensagem",
+ signDelimiterHelp:
+ "Delimitador utilizado para separar a assinatura da mensagem (\\n para quebra de linha)",
+ reopenConversation: "Reabrir conversa",
+ reopenConversationHelp:
+ "Reabre a conversa do cliente quando ele inicia uma nova conversa em vez de criar uma nova conversa",
+ conversationPending: "Iniciar conversa como pendente",
+ conversationPendingHelp:
+ "Inicia a conversa como pendente ao invés de aberta",
+ autoCreate: "Criar Caixa de Entrada",
+ autoCreateHelp: "Cria a caixa de entrada no Chatwoot caso ela não exista",
+ importcontacts: "Importar contatos",
+ importcontactsHelp: "Importar contatos para o Chatwoot",
+ importmessages: "Importar mensagens",
+ importmessagesHelp:
+ "Importar mensagens do histórico de mensagens para o Chatwoot",
+ config: {
+ btn: "Como configurar o chatwoot?",
+ title: "Como configurar a caixa de entrada do Chatwoot?",
+ fullDoc: "Ver documentação completa",
+ steps: {
+ 1: 'Acesse as configurações > Caixa de Entrada e "Adicionar Caixa"',
+ 2: 'Selecione "API" como tipo de caixa',
+ 3: "Preencha nome da caixa e webhook. Os valores devem ser exatamente os seguintes:",
+ 4: "Adicione os agentes à caixa de entrada.",
+ 5: "Pronto! Agora você pode receber mensagens.",
+ },
+ },
+ },
+ typebot: {
+ typebot: "Nome do fluxo do Typebot",
+ typebotHelp: "O nome do fluxo do Typebot que será utilizado",
+ keywordFinish: "Palavra-chave de finalização",
+ keywordFinishHelp: "Palavra-chave para finalizar o fluxo",
+ expire: "Tempo de expiração (em minutos)",
+ expireHelp: "Tempo para encerrar a sessão caso não haja interação",
+ delayMessage: "Tempo de digitação da mensagem",
+ delayMessageUnit: "em milisegundos",
+ delayMessageHelp: "Tempo de simulação de digitação",
+ unknownMessage: "Mensagem formato desconhecido",
+ unknownMessageHelp:
+ "Mensagem enviada quando o formato da mensagem não é reconhecido",
+ unknownMessagePlaceholder: "Deixe em branco para não enviar mensagem",
+ listeningFromMe: "Ouvir mensagens enviadas por mim",
+ listeningFromMeHelp:
+ "Envia as mensagens enviadas por você para o fluxo do Typebot",
+ session: {
+ title: "Sessões do Typebot",
+ btn: "Ver 0 sessões | Ver uma sessão | Ver {count} sessões",
+ noData: "Nenhuma sessão encontrada",
+ headers: {
+ variables: "Variáveis",
+ createdAt: "Iniciada em",
+ updatedAt: "Última mensagem",
+ },
+ },
+ status: {
+ opened: "Aberto",
+ paused: "Pausado",
+ closed: "Fechado",
+ },
+ },
+ sendMessage: {
+ title: "Enviar mensagem",
+ to: "Para",
+ noContacts: "Sem contatos",
+ message: "Mensagem",
+ presence: "Presença",
+ delay: "Atraso",
+ delayHelp: "Atraso em milisegundos",
+ send: "Enviar",
+ success: "Mensagem enviada com sucesso | Mensagens enviadas com sucesso",
+ },
+ phoneHasWhatsApp: {
+ title: "Tem WhatsApp?",
+ phone: "Número do WhatsApp",
+ verify: "Consultar",
+ exists: "WhatsApp encontrado",
+ notExists: "WhatsApp não encontrado",
+ invalid: "Número inválido",
+ },
+ contacts: {
+ title: "Meus contatos",
+ },
+ groups: {
+ title: "Meus grupos",
+ headers: { creation: "Criado em" },
+ },
+ chats: {
+ title: "Minhas conversas",
+ headers: { lastMsgTimestamp: "Última mensagem" },
+ },
+ profile: {
+ title: "Nome e Recado",
+ name: "Name",
+ status: "Recado (status)",
+ },
+ profilePicture: {
+ title: "Foto de perfil",
+ noPhoto: "Sem foto de perfil",
+ upload: "Selecionar Foto",
+ remove: "Remover Foto",
+ },
+ privacy: {
+ title: "Privacidade",
+ lastSeen: "Visto por último",
+ online: "Online",
+ profilePhoto: "Foto de perfil",
+ status: "Recado (status)",
+ readreceipts: "Confirmação de leitura",
+ groupadd: "Ser adicionado a grupos",
+ options: {
+ all: "Todos",
+ contacts: "Meus contatos",
+ contactBlacklist: "Meus contatos, exceto os da lista negra",
+ matchLastSeen: "Igual ao visto por último",
+ none: "Ninguém",
+ },
+ },
+};
diff --git a/src/layouts/default/AppBar.vue b/src/layouts/default/AppBar.vue
index 3906150..34adbcb 100644
--- a/src/layouts/default/AppBar.vue
+++ b/src/layouts/default/AppBar.vue
@@ -13,13 +13,43 @@
v-else-if="AppStore.validConnection"
color="success"
style="max-width: 35vw"
+ class="px-2"
>
-
mdi-check-circle
- {{
- AppStore.connection.host.replace(/https?:\/\//, "").replace(/\/$/, "")
- }}
+
+
mdi-check-circle
+
+
+ {{
+ AppStore.connection.host
+ .replace(/https?:\/\//, "")
+ .replace(/\/$/, "")
+ }}
+
+
+
+ {{ AppStore.version }}
+
+
mdi-alert-circle
+
+
+
+ mdi-translate
+ {{ currentLanguage }}
+
+
+
+
+ {{ lang }}
+
+
+
mdi-cog
@@ -45,6 +75,10 @@ export default {
SettingsModal,
},
methods: {
+ changei18n(locale) {
+ this.$vuetify.locale.current = locale;
+ window.localStorage.setItem("locale", locale);
+ },
toggleTheme() {
const theme = this.theme.global.current.dark ? "light" : "dark";
this.theme.global.name = theme;
@@ -75,11 +109,22 @@ export default {
dark() {
return this.theme.global.current.dark;
},
+ availableLanguages() {
+ return this.$i18n.availableLocales;
+ },
+ currentLanguage() {
+ return this.$i18n.locale;
+ },
},
async mounted() {
- const urlConnection = await this.loadConnectionFromUrl();
- if (!urlConnection) await this.AppStore.loadConnection();
- if (!this.AppStore.validConnection) this.openSettings();
+ try {
+ const urlConnection = await this.loadConnectionFromUrl();
+ if (!urlConnection) await this.AppStore.loadConnection();
+ } catch (e) {
+ console.error(e);
+ } finally {
+ if (!this.AppStore.validConnection) this.openSettings();
+ }
},
};
diff --git a/src/layouts/default/AppFooter.vue b/src/layouts/default/AppFooter.vue
index c000f3b..3994381 100644
--- a/src/layouts/default/AppFooter.vue
+++ b/src/layouts/default/AppFooter.vue
@@ -9,7 +9,7 @@
color="blue"
>
mdi-information
- Sobre
+ {{ $t("about.title") }}
mdi-hand-coin
- Contribua com o projeto
+ {{ $t("contribute.button") }}
v{{ version }}
@@ -70,7 +70,7 @@ export default {
{
title: "Doc",
icon: "mdi-book-open-page-variant",
- url: "https://doc.evolution-api.com/help-center",
+ url: "https://doc.evolution-api.com",
},
],
}),
diff --git a/src/layouts/doc/AppBar.vue b/src/layouts/doc/AppBar.vue
index 6b34266..9d7aea8 100644
--- a/src/layouts/doc/AppBar.vue
+++ b/src/layouts/doc/AppBar.vue
@@ -15,7 +15,7 @@
-