@@ -71,7 +68,7 @@ export default {
},
methods: {
onSubmit() {
- this.$store.dispatch('message/updateContactAttributes', {
+ this.$store.dispatch('message/update', {
email: this.email,
messageId: this.messageId,
});
diff --git a/app/javascript/widget/helpers/actionCable.js b/app/javascript/widget/helpers/actionCable.js
index 1e4a12523..a7706bbe5 100644
--- a/app/javascript/widget/helpers/actionCable.js
+++ b/app/javascript/widget/helpers/actionCable.js
@@ -14,6 +14,9 @@ class ActionCableConnector extends BaseActionCableConnector {
}
export const refreshActionCableConnector = pubsubToken => {
+ if (!pubsubToken) {
+ return;
+ }
window.chatwootPubsubToken = pubsubToken;
window.actionCable.disconnect();
window.actionCable = new ActionCableConnector(
diff --git a/app/javascript/widget/i18n/en.js b/app/javascript/widget/i18n/en.js
index c8aadd8da..4cac34d13 100644
--- a/app/javascript/widget/i18n/en.js
+++ b/app/javascript/widget/i18n/en.js
@@ -4,5 +4,8 @@ export default {
DOWNLOAD: 'Download',
UPLOADING: 'Uploading...',
},
+ FORM_BUBBLE: {
+ SUBMIT: 'Submit',
+ },
},
};
diff --git a/app/javascript/widget/store/index.js b/app/javascript/widget/store/index.js
index 076951c8b..d487ac991 100755
--- a/app/javascript/widget/store/index.js
+++ b/app/javascript/widget/store/index.js
@@ -5,6 +5,7 @@ import appConfig from 'widget/store/modules/appConfig';
import contacts from 'widget/store/modules/contacts';
import conversation from 'widget/store/modules/conversation';
import conversationLabels from 'widget/store/modules/conversationLabels';
+import events from 'widget/store/modules/events';
import message from 'widget/store/modules/message';
Vue.use(Vuex);
@@ -13,9 +14,10 @@ export default new Vuex.Store({
modules: {
agent,
appConfig,
- message,
contacts,
conversation,
conversationLabels,
+ events,
+ message,
},
});
diff --git a/app/javascript/widget/store/modules/conversation.js b/app/javascript/widget/store/modules/conversation.js
index 4388f6052..3a7762a42 100755
--- a/app/javascript/widget/store/modules/conversation.js
+++ b/app/javascript/widget/store/modules/conversation.js
@@ -188,7 +188,10 @@ export const mutations = {
updateMessage($state, { id, content_attributes }) {
$state.conversations[id] = {
...$state.conversations[id],
- content_attributes,
+ content_attributes: {
+ ...($state.conversations[id].content_attributes || {}),
+ ...content_attributes,
+ },
};
},
};
diff --git a/app/javascript/widget/store/modules/events.js b/app/javascript/widget/store/modules/events.js
new file mode 100644
index 000000000..3fa38147d
--- /dev/null
+++ b/app/javascript/widget/store/modules/events.js
@@ -0,0 +1,19 @@
+import events from 'widget/api/events';
+
+const actions = {
+ create: async (_, { name }) => {
+ try {
+ await events.create(name);
+ } catch (error) {
+ // Ignore error
+ }
+ },
+};
+
+export default {
+ namespaced: true,
+ state: {},
+ getters: {},
+ actions,
+ mutations: {},
+};
diff --git a/app/javascript/widget/store/modules/message.js b/app/javascript/widget/store/modules/message.js
index 4243023a7..839305d03 100644
--- a/app/javascript/widget/store/modules/message.js
+++ b/app/javascript/widget/store/modules/message.js
@@ -1,4 +1,4 @@
-import MessageAPI from 'widget/api/message';
+import MessageAPI from '../../api/message';
import { refreshActionCableConnector } from '../../helpers/actionCable';
const state = {
@@ -12,19 +12,24 @@ const getters = {
};
const actions = {
- updateContactAttributes: async ({ commit }, { email, messageId }) => {
+ update: async ({ commit }, { email, messageId, submittedValues }) => {
commit('toggleUpdateStatus', true);
try {
const {
- data: {
- contact: { pubsub_token: pubsubToken },
- },
- } = await MessageAPI.update({ email, messageId });
+ data: { contact: { pubsub_token: pubsubToken } = {} },
+ } = await MessageAPI.update({
+ email,
+ messageId,
+ values: submittedValues,
+ });
commit(
'conversation/updateMessage',
{
id: messageId,
- content_attributes: { submitted_email: email },
+ content_attributes: {
+ submitted_email: email,
+ submitted_values: email ? null : submittedValues,
+ },
},
{ root: true }
);
diff --git a/app/listeners/agent_bot_listener.rb b/app/listeners/agent_bot_listener.rb
index 848c09cb7..7155357c8 100644
--- a/app/listeners/agent_bot_listener.rb
+++ b/app/listeners/agent_bot_listener.rb
@@ -10,4 +10,28 @@ class AgentBotListener < BaseListener
payload = message.webhook_data.merge(event: __method__.to_s)
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
end
+
+ def message_updated(event)
+ message = extract_message_and_account(event)[0]
+ inbox = message.inbox
+ return unless message.reportable? && inbox.agent_bot_inbox.present?
+ return unless inbox.agent_bot_inbox.active?
+
+ agent_bot = inbox.agent_bot_inbox.agent_bot
+
+ payload = message.webhook_data.merge(event: __method__.to_s)
+ AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
+ end
+
+ def webwidget_triggered(event)
+ contact_inbox = event.data[:contact_inbox]
+ inbox = contact_inbox.inbox
+ return if inbox.agent_bot_inbox.blank?
+ return unless inbox.agent_bot_inbox.active?
+
+ agent_bot = inbox.agent_bot_inbox.agent_bot
+
+ payload = contact_inbox.webhook_data.merge(event: __method__.to_s)
+ AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
+ end
end
diff --git a/app/listeners/webhook_listener.rb b/app/listeners/webhook_listener.rb
index 0da0fdad4..3597a402e 100644
--- a/app/listeners/webhook_listener.rb
+++ b/app/listeners/webhook_listener.rb
@@ -6,6 +6,30 @@ class WebhookListener < BaseListener
return unless message.reportable?
payload = message.webhook_data.merge(event: __method__.to_s)
+ deliver_webhook_payloads(payload, inbox)
+ end
+
+ def message_updated(event)
+ message = extract_message_and_account(event)[0]
+ inbox = message.inbox
+
+ return unless message.reportable?
+
+ payload = message.webhook_data.merge(event: __method__.to_s)
+ deliver_webhook_payloads(payload, inbox)
+ end
+
+ def webwidget_triggered(event)
+ contact_inbox = event.data[:contact_inbox]
+ inbox = contact_inbox.inbox
+
+ payload = contact_inbox.webhook_data.merge(event: __method__.to_s)
+ deliver_webhook_payloads(payload, inbox)
+ end
+
+ private
+
+ def deliver_webhook_payloads(payload, inbox)
# Account webhooks
inbox.account.webhooks.account.each do |webhook|
WebhookJob.perform_later(webhook.url, payload)
diff --git a/app/models/channel/web_widget.rb b/app/models/channel/web_widget.rb
index 68fe67ae8..33a743f64 100644
--- a/app/models/channel/web_widget.rb
+++ b/app/models/channel/web_widget.rb
@@ -51,11 +51,12 @@ class Channel::WebWidget < ApplicationRecord
def create_contact_inbox
ActiveRecord::Base.transaction do
contact = inbox.account.contacts.create!(name: ::Haikunator.haikunate(1000))
- ::ContactInbox.create!(
+ contact_inbox = ::ContactInbox.create!(
contact_id: contact.id,
inbox_id: inbox.id,
source_id: SecureRandom.uuid
)
+ contact_inbox
rescue StandardError => e
Rails.logger e
end
diff --git a/app/models/concerns/content_attribute_validator.rb b/app/models/concerns/content_attribute_validator.rb
new file mode 100644
index 000000000..bbeac3a7f
--- /dev/null
+++ b/app/models/concerns/content_attribute_validator.rb
@@ -0,0 +1,52 @@
+class ContentAttributeValidator < ActiveModel::Validator
+ ALLOWED_SELECT_ITEM_KEYS = [:title, :value].freeze
+ ALLOWED_CARD_ITEM_KEYS = [:title, :description, :media_url, :actions].freeze
+ ALLOWED_CARD_ITEM_ACTION_KEYS = [:text, :type, :payload, :uri].freeze
+ ALLOWED_FORM_ITEM_KEYS = [:type, :placeholder, :label, :name, :options].freeze
+ ALLOWED_ARTICLE_KEYS = [:title, :description, :link].freeze
+
+ def validate(record)
+ case record.content_type
+ when 'input_select'
+ validate_items!(record)
+ validate_item_attributes!(record, ALLOWED_SELECT_ITEM_KEYS)
+ when 'cards'
+ validate_items!(record)
+ validate_item_attributes!(record, ALLOWED_CARD_ITEM_KEYS)
+ validate_item_actions!(record)
+ when 'form'
+ validate_items!(record)
+ validate_item_attributes!(record, ALLOWED_FORM_ITEM_KEYS)
+ when 'article'
+ validate_items!(record)
+ validate_item_attributes!(record, ALLOWED_ARTICLE_KEYS)
+ end
+ end
+
+ private
+
+ def validate_items!(record)
+ record.errors.add(:content_attributes, 'At least one item is required.') if record.items.blank?
+ record.errors.add(:content_attributes, 'Items should be a hash.') if record.items.reject { |item| item.is_a?(Hash) }.present?
+ end
+
+ def validate_item_attributes!(record, valid_keys)
+ item_keys = record.items.collect(&:keys).flatten.map(&:to_sym).compact
+ invalid_keys = item_keys - valid_keys
+ record.errors.add(:content_attributes, "contains invalid keys for items : #{invalid_keys}") if invalid_keys.present?
+ end
+
+ def validate_item_actions!(record)
+ if record.items.select { |item| item[:actions].blank? }.present?
+ record.errors.add(:content_attributes, 'contains items missing actions') && return
+ end
+
+ validate_item_action_attributes!(record)
+ end
+
+ def validate_item_action_attributes!(record)
+ item_action_keys = record.items.collect { |item| item[:actions].collect(&:keys) }
+ invalid_keys = item_action_keys.flatten.compact.map(&:to_sym) - ALLOWED_CARD_ITEM_ACTION_KEYS
+ record.errors.add(:content_attributes, "contains invalid keys for actions: #{invalid_keys}") if invalid_keys.present?
+ end
+end
diff --git a/app/models/contact_inbox.rb b/app/models/contact_inbox.rb
index c79786e1e..c528a9af0 100644
--- a/app/models/contact_inbox.rb
+++ b/app/models/contact_inbox.rb
@@ -31,4 +31,19 @@ class ContactInbox < ApplicationRecord
belongs_to :inbox
has_many :conversations, dependent: :destroy
+
+ def webhook_data
+ {
+ id: id,
+ contact: contact.try(:webhook_data),
+ inbox: inbox.webhook_data,
+ account: inbox.account.webhook_data,
+ current_conversation: current_conversation.try(:webhook_data),
+ source_id: source_id
+ }
+ end
+
+ def current_conversation
+ conversations.last
+ end
end
diff --git a/app/models/message.rb b/app/models/message.rb
index 1e434ffa2..cc323ebd0 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -38,11 +38,21 @@ class Message < ApplicationRecord
validates :account_id, presence: true
validates :inbox_id, presence: true
validates :conversation_id, presence: true
+ validates_with ContentAttributeValidator
enum message_type: { incoming: 0, outgoing: 1, activity: 2, template: 3 }
- enum content_type: { text: 0, input: 1, input_textarea: 2, input_email: 3 }
+ enum content_type: {
+ text: 0,
+ input_text: 1,
+ input_textarea: 2,
+ input_email: 3,
+ input_select: 4,
+ cards: 5,
+ form: 6,
+ article: 7
+ }
enum status: { sent: 0, delivered: 1, read: 2, failed: 3 }
- store :content_attributes, accessors: [:submitted_email], coder: JSON, prefix: :input
+ store :content_attributes, accessors: [:submitted_email, :items, :submitted_values], coder: JSON
# .succ is a hack to avoid https://makandracards.com/makandra/1057-why-two-ruby-time-objects-are-not-equal-although-they-appear-to-be
scope :unread_since, ->(datetime) { where('EXTRACT(EPOCH FROM created_at) > (?)', datetime.to_i.succ) }
@@ -63,6 +73,8 @@ class Message < ApplicationRecord
:execute_message_template_hooks,
:notify_via_mail
+ after_update :dispatch_update_event
+
def channel_token
@token ||= inbox.channel.try(:page_access_token)
end
@@ -88,6 +100,8 @@ class Message < ApplicationRecord
content: content,
created_at: created_at,
message_type: message_type,
+ content_type: content_type,
+ content_attributes: content_attributes,
source_id: source_id,
sender: user.try(:webhook_data),
contact: contact.try(:webhook_data),
@@ -107,6 +121,10 @@ class Message < ApplicationRecord
end
end
+ def dispatch_update_event
+ Rails.configuration.dispatcher.dispatch(MESSAGE_UPDATED, Time.zone.now, message: self)
+ end
+
def send_reply
channel_name = conversation.inbox.channel.class.to_s
if channel_name == 'Channel::FacebookPage'
diff --git a/app/views/api/v1/accounts/conversations/create.json.jbuilder b/app/views/api/v1/accounts/conversations/create.json.jbuilder
new file mode 100644
index 000000000..2d39b121c
--- /dev/null
+++ b/app/views/api/v1/accounts/conversations/create.json.jbuilder
@@ -0,0 +1 @@
+json.partial! 'api/v1/conversations/partials/conversation.json.jbuilder', conversation: @conversation
diff --git a/app/views/api/v1/accounts/conversations/messages/create.json.jbuilder b/app/views/api/v1/accounts/conversations/messages/create.json.jbuilder
index f47f86587..e01408e43 100644
--- a/app/views/api/v1/accounts/conversations/messages/create.json.jbuilder
+++ b/app/views/api/v1/accounts/conversations/messages/create.json.jbuilder
@@ -1,8 +1,10 @@
json.id @message.id
json.content @message.content
json.inbox_id @message.inbox_id
-json.conversation_id @message.conversation_id
+json.conversation_id @message.conversation.display_id
json.message_type @message.message_type_before_type_cast
+json.content_type @message.content_type
+json.content_attributes @message.content_attributes
json.created_at @message.created_at.to_i
json.private @message.private
json.attachment @message.attachment.push_event_data if @message.attachment
diff --git a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
index c4e416d81..4f511d3ba 100644
--- a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
+++ b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
@@ -22,3 +22,4 @@ json.user_last_seen_at conversation.user_last_seen_at.to_i
json.agent_last_seen_at conversation.agent_last_seen_at.to_i
json.unread_count conversation.unread_incoming_messages.count
json.additional_attributes conversation.additional_attributes
+json.account_id conversation.account_id
diff --git a/app/views/api/v1/widget/messages/update.json.jbuilder b/app/views/api/v1/widget/messages/update.json.jbuilder
index da1e28d00..e5abbd295 100644
--- a/app/views/api/v1/widget/messages/update.json.jbuilder
+++ b/app/views/api/v1/widget/messages/update.json.jbuilder
@@ -1 +1 @@
-json.contact @contact
+json.contact @contact if @contact
diff --git a/config/routes.rb b/config/routes.rb
index be63d95e9..8a9f0e568 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -39,7 +39,7 @@ Rails.application.routes.draw do
namespace :channels do
resource :twilio_channel, only: [:create]
end
- resources :conversations, only: [:index, :show] do
+ resources :conversations, only: [:index, :create, :show] do
scope module: :conversations do
resources :messages, only: [:index, :create]
resources :assignments, only: [:create]
@@ -109,10 +109,11 @@ Rails.application.routes.draw do
resources :agent_bots, only: [:index]
namespace :widget do
+ resources :events, only: [:create]
+ resources :messages, only: [:index, :create, :update]
resource :contact, only: [:update]
resources :inbox_members, only: [:index]
resources :labels, only: [:create, :destroy]
- resources :messages, only: [:index, :create, :update]
end
resources :webhooks, only: [] do
diff --git a/db/schema.rb b/db/schema.rb
index 4ce01e6ff..b64a28634 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -287,9 +287,11 @@ ActiveRecord::Schema.define(version: 2020_04_04_135009) do
t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
t.index ["taggable_id", "taggable_type", "tagger_id", "context"], name: "taggings_idy"
t.index ["taggable_id"], name: "index_taggings_on_taggable_id"
+ t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable_type_and_taggable_id"
t.index ["taggable_type"], name: "index_taggings_on_taggable_type"
t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type"
t.index ["tagger_id"], name: "index_taggings_on_tagger_id"
+ t.index ["tagger_type", "tagger_id"], name: "index_taggings_on_tagger_type_and_tagger_id"
end
create_table "tags", id: :serial, force: :cascade do |t|
diff --git a/docs/webhooks/add-webhooks-to-chatwoot.md b/docs/webhooks/add-webhooks-to-chatwoot.md
index 6e3576707..ddf45a031 100644
--- a/docs/webhooks/add-webhooks-to-chatwoot.md
+++ b/docs/webhooks/add-webhooks-to-chatwoot.md
@@ -28,7 +28,9 @@ Chatwoot currently supports webhooks for message creation only. Once a new messa
"id": "1", // Message ID
"content": "Hi", // Content of the message
"created_at": "2020-03-03 13:05:57 UTC", // Time at which the message was sent
- "message_type": "incoming", // This will have a type incoming or outgoing. Incoming messages are sent by the user from the widget, Outgoing messages are sent by the agent to the user.
+ "message_type": "incoming", // This will have a type incoming, outgoing or template. Incoming messages are sent by the user from the widget, Outgoing messages are sent by the agent to the user.
+ "content_type": "enum", // This is an enum, it can be input_select, cards, form or text. The message_type will be template if content_type is one og these. Default value is text
+ "content_attributes": {} // This will an object, different values are defined below
"source_id": "", // This would the external id if the inbox is a Twitter or Facebook integration.
"sender": { // This would provide the details of the agent who sent this message
"id": "1",
@@ -59,3 +61,70 @@ Chatwoot currently supports webhooks for message creation only. Once a new messa
}
}
```
+
+### Content Attributes
+
+#### 1. Options
+
+```json
+{
+ "items": [
+ {
+ "title": "Option 1",
+ "value": "option_1"
+ },
+ {
+ "title": "Option 2",
+ "value": "option_2"
+ }
+ ],
+ "submitted_values": [
+ {
+ "title": "Option 1",
+ "value": "option_1"
+ }
+ ]
+}
+```
+
+#### 2. Form
+
+```json
+{
+ "items": [
+ {
+ "type": "text/text_area/email",
+ "placeholder": "Placeholder",
+ "name": "unique_name_of_the_field",
+ "label": "Label"
+ },
+ ],
+ "submitted_values": [
+ {
+ "name": "unique_name_of_the_field 1",
+ "value": "sample_value"
+ }
+ ]
+}
+```
+
+#### 3. Cards
+
+```json
+{
+ "items": [
+ {
+ "media_url": "", // Url of the image to be displayed
+ "title": "", // Title of the card
+ "description": "", // Description of the card
+ "actions": [
+ {
+ "type": "link",
+ "text": "View More",
+ "uri": "" // Link to the website
+ }
+ ]
+ },
+ ],
+}
+```
diff --git a/lib/events/types.rb b/lib/events/types.rb
index 158312ee9..4e34509df 100644
--- a/lib/events/types.rb
+++ b/lib/events/types.rb
@@ -4,9 +4,11 @@ module Events::Types
CONVERSATION_CREATED = 'conversation.created'
CONVERSATION_RESOLVED = 'conversation.resolved'
CONVERSATION_READ = 'conversation.read'
+ WEBWIDGET_TRIGGERED = 'webwidget.triggered'
MESSAGE_CREATED = 'message.created'
FIRST_REPLY_CREATED = 'first.reply.created'
+ MESSAGE_UPDATED = 'message.updated'
CONVERSATION_REOPENED = 'conversation.reopened'
CONVERSATION_LOCK_TOGGLE = 'conversation.lock_toggle'
ASSIGNEE_CHANGED = 'assignee.changed'
diff --git a/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb b/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb
index 9f21f1fae..588a129ab 100644
--- a/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Conversation Messages API', type: :request do
let(:agent) { create(:user, account: account, role: :agent) }
it 'creates a new outgoing message' do
- params = { message: 'test-message', private: true }
+ params = { content: 'test-message', private: true }
post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id),
params: params,
@@ -28,12 +28,12 @@ RSpec.describe 'Conversation Messages API', type: :request do
expect(response).to have_http_status(:success)
expect(conversation.messages.count).to eq(1)
- expect(conversation.messages.first.content).to eq(params[:message])
+ expect(conversation.messages.first.content).to eq(params[:content])
end
it 'creates a new outgoing message with attachment' do
file = fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png')
- params = { message: 'test-message', attachment: { file: file } }
+ params = { content: 'test-message', attachment: { file: file } }
post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id),
params: params,
@@ -50,7 +50,7 @@ RSpec.describe 'Conversation Messages API', type: :request do
it 'creates a new outgoing message' do
create(:agent_bot_inbox, inbox: inbox, agent_bot: agent_bot)
- params = { message: 'test-message' }
+ params = { content: 'test-message' }
post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id),
params: params,
@@ -59,7 +59,39 @@ RSpec.describe 'Conversation Messages API', type: :request do
expect(response).to have_http_status(:success)
expect(conversation.messages.count).to eq(1)
- expect(conversation.messages.first.content).to eq(params[:message])
+ expect(conversation.messages.first.content).to eq(params[:content])
+ end
+
+ it 'creates a new outgoing input select message' do
+ create(:agent_bot_inbox, inbox: inbox, agent_bot: agent_bot)
+ select_item1 = build(:bot_message_select)
+ select_item2 = build(:bot_message_select)
+ params = { content_type: 'input_select', content_attributes: { items: [select_item1, select_item2] } }
+
+ post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id),
+ params: params,
+ headers: { api_access_token: agent_bot.access_token.token },
+ as: :json
+
+ expect(response).to have_http_status(:success)
+ expect(conversation.messages.count).to eq(1)
+ expect(conversation.messages.first.content_type).to eq(params[:content_type])
+ expect(conversation.messages.first.content).to eq nil
+ end
+
+ it 'creates a new outgoing cards message' do
+ create(:agent_bot_inbox, inbox: inbox, agent_bot: agent_bot)
+ card = build(:bot_message_card)
+ params = { content_type: 'cards', content_attributes: { items: [card] } }
+
+ post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id),
+ params: params,
+ headers: { api_access_token: agent_bot.access_token.token },
+ as: :json
+
+ expect(response).to have_http_status(:success)
+ expect(conversation.messages.count).to eq(1)
+ expect(conversation.messages.first.content_type).to eq(params[:content_type])
end
end
end
diff --git a/spec/controllers/api/v1/widget/events_controller_spec.rb b/spec/controllers/api/v1/widget/events_controller_spec.rb
new file mode 100644
index 000000000..e99686830
--- /dev/null
+++ b/spec/controllers/api/v1/widget/events_controller_spec.rb
@@ -0,0 +1,37 @@
+require 'rails_helper'
+
+RSpec.describe '/api/v1/widget/events', type: :request do
+ let(:account) { create(:account) }
+ let(:web_widget) { create(:channel_widget, account: account) }
+ let(:contact) { create(:contact, account: account) }
+ let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: web_widget.inbox) }
+ let(:payload) { { source_id: contact_inbox.source_id, inbox_id: web_widget.inbox.id } }
+ let(:token) { ::Widget::TokenService.new(payload: payload).generate_token }
+
+ describe 'POST /api/v1/widget/events' do
+ let(:params) { { website_token: web_widget.website_token, name: 'webwidget.triggered' } }
+
+ context 'with invalid website token' do
+ it 'returns unauthorized' do
+ post '/api/v1/widget/events', params: { website_token: '' }
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'with correct website token' do
+ before do
+ allow(Rails.configuration.dispatcher).to receive(:dispatch)
+ end
+
+ it 'dispatches the webwidget event' do
+ post '/api/v1/widget/events',
+ params: params,
+ headers: { 'X-Auth-Token' => token },
+ as: :json
+
+ expect(response).to have_http_status(:success)
+ expect(Rails.configuration.dispatcher).to have_received(:dispatch).with(params[:name], anything, contact_inbox: contact_inbox)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/api/v1/widget/messages_controller_spec.rb b/spec/controllers/api/v1/widget/messages_controller_spec.rb
index 9a0b73d02..8ce37e17a 100644
--- a/spec/controllers/api/v1/widget/messages_controller_spec.rb
+++ b/spec/controllers/api/v1/widget/messages_controller_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe '/api/v1/widget/messages', type: :request do
describe 'PUT /api/v1/widget/messages' do
context 'when put request is made with non existing email' do
it 'updates message in conversation and creates a new contact' do
- message = create(:message, account: account, inbox: web_widget.inbox, conversation: conversation)
+ message = create(:message, content_type: 'input_email', account: account, inbox: web_widget.inbox, conversation: conversation)
email = Faker::Internet.email
contact_params = { email: email }
put api_v1_widget_message_url(message.id),
@@ -75,14 +75,14 @@ RSpec.describe '/api/v1/widget/messages', type: :request do
expect(response).to have_http_status(:success)
message.reload
- expect(message.input_submitted_email).to eq(email)
+ expect(message.submitted_email).to eq(email)
expect(message.conversation.contact.email).to eq(email)
end
end
context 'when put request is made with invalid email' do
it 'rescues the error' do
- message = create(:message, account: account, inbox: web_widget.inbox, conversation: conversation)
+ message = create(:message, account: account, content_type: 'input_email', inbox: web_widget.inbox, conversation: conversation)
contact_params = { email: nil }
put api_v1_widget_message_url(message.id),
params: { website_token: web_widget.website_token, contact: contact_params },
@@ -95,7 +95,7 @@ RSpec.describe '/api/v1/widget/messages', type: :request do
context 'when put request is made with existing email' do
it 'updates message in conversation and deletes the current contact' do
- message = create(:message, account: account, inbox: web_widget.inbox, conversation: conversation)
+ message = create(:message, account: account, content_type: 'input_email', inbox: web_widget.inbox, conversation: conversation)
email = Faker::Internet.email
create(:contact, account: account, email: email)
contact_params = { email: email }
@@ -110,7 +110,7 @@ RSpec.describe '/api/v1/widget/messages', type: :request do
end
it 'ignores the casing of email, updates message in conversation and deletes the current contact' do
- message = create(:message, account: account, inbox: web_widget.inbox, conversation: conversation)
+ message = create(:message, content_type: 'input_email', account: account, inbox: web_widget.inbox, conversation: conversation)
email = Faker::Internet.email
create(:contact, account: account, email: email)
contact_params = { email: email.upcase }
diff --git a/spec/factories/bot_message/bot_message_card.rb b/spec/factories/bot_message/bot_message_card.rb
new file mode 100644
index 000000000..f2f77bb34
--- /dev/null
+++ b/spec/factories/bot_message/bot_message_card.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :bot_message_card, class: Hash do
+ title { Faker::Book.name }
+ description { Faker::Movie.quote }
+ media_url { 'https://via.placeholder.com/250x250.png' }
+ actions do
+ [{
+ text: 'Select',
+ type: 'postback',
+ payload: 'TACOS'
+ }, {
+ text: 'More info',
+ type: 'link',
+ uri: 'http://example.org'
+ }]
+ end
+
+ initialize_with { attributes }
+ end
+end
diff --git a/spec/factories/bot_message/bot_message_select.rb b/spec/factories/bot_message/bot_message_select.rb
new file mode 100644
index 000000000..c50f3d31b
--- /dev/null
+++ b/spec/factories/bot_message/bot_message_select.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :bot_message_select, class: Hash do
+ title { Faker::Book.name }
+ value { Faker::Book.name }
+
+ initialize_with { attributes }
+ end
+end
diff --git a/swagger/definitions/request/conversation/create_message.yml b/swagger/definitions/request/conversation/create_message.yml
index 02a5564cb..caa5dcd36 100644
--- a/swagger/definitions/request/conversation/create_message.yml
+++ b/swagger/definitions/request/conversation/create_message.yml
@@ -4,10 +4,16 @@ properties:
type: number
description: ID of the conversation
required: true
- message:
+ content:
type: string
description: The content of the message
required: true
private:
type: boolean
description: Flag to identify if it is a private note
+ content_type:
+ type: string
+ enum: ['input_select', 'form', 'cards']
+ content_attributes:
+ type: object
+ description: options/form object
diff --git a/swagger/definitions/resource/conversation.yml b/swagger/definitions/resource/conversation.yml
index 204810534..05126e1ab 100644
--- a/swagger/definitions/resource/conversation.yml
+++ b/swagger/definitions/resource/conversation.yml
@@ -5,6 +5,9 @@ properties:
description: ID of the conversation
messages:
type: array
+ account_id:
+ type: number
+ description: Account Id
inbox_id:
type: number
description: ID of the inbox
diff --git a/swagger/definitions/resource/message.yml b/swagger/definitions/resource/message.yml
index a27a88d76..78c8fd640 100644
--- a/swagger/definitions/resource/message.yml
+++ b/swagger/definitions/resource/message.yml
@@ -3,6 +3,13 @@ properties:
content:
type: string
description: The text content of the message
+ content_type:
+ type: string
+ enum: ["text", "input_select", "cards", "form"]
+ description: The type of the template message
+ content_attributes:
+ type: object
+ description: The content attributes for each content_type
message_type:
type: string
enum: ["incoming", "outgoing", "activity", "template"]
diff --git a/swagger/paths/conversation/list.yml b/swagger/paths/conversation/index_or_create.yml
similarity index 51%
rename from swagger/paths/conversation/list.yml
rename to swagger/paths/conversation/index_or_create.yml
index 1583bdfd5..b1a2dbdd4 100644
--- a/swagger/paths/conversation/list.yml
+++ b/swagger/paths/conversation/index_or_create.yml
@@ -37,3 +37,39 @@ get:
description: Bad Request Error
schema:
$ref: '#/definitions/bad_request_error'
+ description: Access denied
+
+post:
+ tags:
+ - Conversation
+ operationId: newConversation
+ summary: Create New Conversation
+ description: Create conversation
+ parameters:
+ - name: data
+ in: body
+ required: true
+ schema:
+ type: object
+ properties:
+ source_id:
+ type: string
+ description: Contact Source Id
+
+ responses:
+ 200:
+ description: Success
+ schema:
+ type: object
+ properties:
+ id:
+ type: number
+ description: ID of the conversation
+ account_id:
+ type: number
+ description: Account Id
+ inbox_id:
+ type: number
+ description: ID of the inbox
+ 403:
+ description: Access denied
diff --git a/swagger/paths/index.yml b/swagger/paths/index.yml
index 67069bdc9..e4944868d 100644
--- a/swagger/paths/index.yml
+++ b/swagger/paths/index.yml
@@ -10,15 +10,14 @@
/accounts/{account_id}/inboxes/{id}:
$ref: ./inboxes/update.yml
/accounts/{account_id}/inboxes/{id}/set_agent_bot:
- $ref: ./inboxes/update.yml
+ $ref: ./inboxes/set_agent_bot.yml
/agent_bots:
$ref: ./agent_bots/index.yml
-
# Conversations
/accounts/{account_id}/conversations:
- $ref: ./conversation/list.yml
+ $ref: ./conversation/index_or_create.yml
/accounts/{account_id}/conversations/{id}:
$ref: ./conversation/crud.yml
/accounts/{account_id}/conversations/{id}/toggle_status:
diff --git a/swagger/swagger.json b/swagger/swagger.json
index 67e3302c2..31ab3a226 100644
--- a/swagger/swagger.json
+++ b/swagger/swagger.json
@@ -201,13 +201,13 @@
}
},
"/accounts/{account_id}/inboxes/{id}/set_agent_bot": {
- "patch": {
+ "post": {
"tags": [
"Inbox"
],
- "operationId": "updateInbox",
- "summary": "Update Inbox",
- "description": "Add avatar and disable auto assignment for an inbox",
+ "operationId": "updateAgentBot",
+ "summary": "Add or remove agent bot",
+ "description": "To add an agent bot pass agent_bot id, to remove agent bot from an inbox pass null",
"parameters": [
{
"name": "id",
@@ -223,29 +223,21 @@
"schema": {
"type": "object",
"properties": {
- "enable_auto_assignment": {
- "type": "boolean",
+ "agent_bot": {
+ "type": "number",
"required": true,
- "description": "Enable Auto Assignment"
- },
- "avatar": {
- "type": "file",
- "required": false,
- "description": "Image file for avatar"
+ "description": "Agent bot ID"
}
}
}
}
],
"responses": {
- "200": {
- "description": "Success",
- "schema": {
- "$ref": "#/definitions/inbox"
- }
+ "204": {
+ "description": "Success"
},
"404": {
- "description": "Inbox not found"
+ "description": "Inbox not found, Agent bot not found"
},
"403": {
"description": "Access denied"
@@ -340,6 +332,56 @@
"schema": {
"$ref": "#/definitions/bad_request_error"
}
+ },
+ "description": "Access denied"
+ }
+ },
+ "post": {
+ "tags": [
+ "Conversation"
+ ],
+ "operationId": "newConversation",
+ "summary": "Create New Conversation",
+ "description": "Create conversation",
+ "parameters": [
+ {
+ "name": "data",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "object",
+ "properties": {
+ "source_id": {
+ "type": "string",
+ "description": "Contact Source Id"
+ }
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "number",
+ "description": "ID of the conversation"
+ },
+ "account_id": {
+ "type": "number",
+ "description": "Account Id"
+ },
+ "inbox_id": {
+ "type": "number",
+ "description": "ID of the inbox"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Access denied"
}
}
}
@@ -881,6 +923,10 @@
"messages": {
"type": "array"
},
+ "account_id": {
+ "type": "number",
+ "description": "Account Id"
+ },
"inbox_id": {
"type": "number",
"description": "ID of the inbox"
@@ -921,6 +967,20 @@
"type": "string",
"description": "The text content of the message"
},
+ "content_type": {
+ "type": "string",
+ "enum": [
+ "text",
+ "input_select",
+ "cards",
+ "form"
+ ],
+ "description": "The type of the template message"
+ },
+ "content_attributes": {
+ "type": "object",
+ "description": "The content attributes for each content_type"
+ },
"message_type": {
"type": "string",
"enum": [
@@ -1350,7 +1410,7 @@
"description": "ID of the conversation",
"required": true
},
- "message": {
+ "content": {
"type": "string",
"description": "The content of the message",
"required": true
@@ -1358,6 +1418,18 @@
"private": {
"type": "boolean",
"description": "Flag to identify if it is a private note"
+ },
+ "content_type": {
+ "type": "string",
+ "enum": [
+ "input_select",
+ "form",
+ "cards"
+ ]
+ },
+ "content_attributes": {
+ "type": "object",
+ "description": "options/form object"
}
}
}
From 991585264eacc103fec45c6a51272da5f43c5fc1 Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Mon, 13 Apr 2020 16:47:31 +0530
Subject: [PATCH 05/57] Update Crowdin configuration file
---
crowdin.yml | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 crowdin.yml
diff --git a/crowdin.yml b/crowdin.yml
new file mode 100644
index 000000000..b9b2815b2
--- /dev/null
+++ b/crowdin.yml
@@ -0,0 +1,6 @@
+files:
+ - source: app/javascript/dashboard/i18n/locale/en/*.json
+ translation: >-
+ app/javascript/dashboard/i18n/locale/%two_letters_code%/%original_file_name%
+ - source: config/locales/*.yml
+ translation: config/locales/%two_letters_code%.yml
From 9db8adab5faf4ae94029e4a5548e2d91ecaf8dbe Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Mon, 13 Apr 2020 19:01:00 +0530
Subject: [PATCH 06/57] Update Crowdin configuration file
---
crowdin.yml | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/crowdin.yml b/crowdin.yml
index b9b2815b2..3c0cf3380 100644
--- a/crowdin.yml
+++ b/crowdin.yml
@@ -1,6 +1,8 @@
files:
- - source: app/javascript/dashboard/i18n/locale/en/*.json
+ - source: /app/javascript/dashboard/i18n/locale/en/*.json
translation: >-
- app/javascript/dashboard/i18n/locale/%two_letters_code%/%original_file_name%
- - source: config/locales/*.yml
- translation: config/locales/%two_letters_code%.yml
+ /app/javascript/dashboard/i18n/locale/%two_letters_code%/%original_file_name%
+ - source: /config/locales/en.yml
+ translation: /config/locales/%two_letters_code%.yml
+ - source: /config/locales/devise.en.yml
+ translation: /config/locales/devise.%two_letters_code%.yml
From 55892e37f9017faef9ddc5c38dd3f2e378ad3082 Mon Sep 17 00:00:00 2001
From: Vishnu Narayanan
Date: Mon, 13 Apr 2020 21:14:17 +0530
Subject: [PATCH 07/57] =?UTF-8?q?Feature:=20Add=20Malayalam(=E0=B4=AE?=
=?UTF-8?q?=E0=B4=B2=E0=B4=AF=E0=B4=BE=E0=B4=B3=E0=B4=82)=20localization?=
=?UTF-8?q?=20(#707)=20(#708)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Add Malayalam localization
* Added Malayalam translations for dashboard locales (UI)
Translations for
* webhooks, signup, settings, set a new password, reset password, report, login, integrations
* Added Malayalam translations for dashboard translations for UI
* Added dashboard Malayalam translations for contact, conversation, general settings and inbox management.
* [707] Add Malayalam translations for dashboard
* [707] Add support for Malayalam
* [707] Fix review comments
* [707] fix review commetns
Co-authored-by: sony-mathew
---
app/javascript/dashboard/i18n/index.js | 2 +
.../dashboard/i18n/locale/ml/agentMgmt.json | 101 +++++++++++++
.../dashboard/i18n/locale/ml/billing.json | 19 +++
.../dashboard/i18n/locale/ml/cannedMgmt.json | 74 ++++++++++
.../dashboard/i18n/locale/ml/chatlist.json | 77 ++++++++++
.../dashboard/i18n/locale/ml/contact.json | 20 +++
.../i18n/locale/ml/conversation.json | 35 +++++
.../i18n/locale/ml/generalSettings.json | 27 ++++
.../dashboard/i18n/locale/ml/inboxMgmt.json | 138 ++++++++++++++++++
.../dashboard/i18n/locale/ml/index.js | 34 +++++
.../i18n/locale/ml/integrations.json | 54 +++++++
.../dashboard/i18n/locale/ml/login.json | 21 +++
.../dashboard/i18n/locale/ml/report.json | 19 +++
.../i18n/locale/ml/resetPassword.json | 15 ++
.../i18n/locale/ml/setNewPassword.json | 20 +++
.../dashboard/i18n/locale/ml/settings.json | 62 ++++++++
.../dashboard/i18n/locale/ml/signup.json | 32 ++++
.../dashboard/i18n/locale/ml/webhooks.json | 5 +
app/javascript/dashboard/i18n/ml.js | 40 +++++
.../dashboard/settings/account/Index.vue | 1 +
config/initializers/languages.rb | 3 +-
config/locales/ml.yml | 56 +++++++
22 files changed, 854 insertions(+), 1 deletion(-)
create mode 100644 app/javascript/dashboard/i18n/locale/ml/agentMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/billing.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/cannedMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/chatlist.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/contact.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/conversation.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/generalSettings.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/inboxMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/index.js
create mode 100644 app/javascript/dashboard/i18n/locale/ml/integrations.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/login.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/report.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/resetPassword.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/setNewPassword.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/settings.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/signup.json
create mode 100644 app/javascript/dashboard/i18n/locale/ml/webhooks.json
create mode 100644 app/javascript/dashboard/i18n/ml.js
create mode 100644 config/locales/ml.yml
diff --git a/app/javascript/dashboard/i18n/index.js b/app/javascript/dashboard/i18n/index.js
index 766640c66..4be079020 100644
--- a/app/javascript/dashboard/i18n/index.js
+++ b/app/javascript/dashboard/i18n/index.js
@@ -1,7 +1,9 @@
import en from './en';
import de from './de';
+import ml from './ml';
export default {
de,
en,
+ ml
};
diff --git a/app/javascript/dashboard/i18n/locale/ml/agentMgmt.json b/app/javascript/dashboard/i18n/locale/ml/agentMgmt.json
new file mode 100644
index 000000000..7a1a0e4eb
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/agentMgmt.json
@@ -0,0 +1,101 @@
+{
+ "AGENT_MGMT": {
+ "HEADER": "ഏജന്റുമാർ",
+ "HEADER_BTN_TXT": "ഏജന്റിനെ ചേർക്കുക",
+ "LOADING": "ഏജന്റ് പട്ടിക ലഭ്യമാക്കുന്നു",
+ "SIDEBAR_TXT": "
ഏജന്റുമാർ
ഒരു ഏജൻറ് നിങ്ങളുടെ ഉപഭോക്തൃ പിന്തുണാ ടീമിലെ ഒരു അംഗമാണ്.
ഏജന്റുമാർക്ക് നിങ്ങളുടെ ഉപയോക്താക്കളിൽ നിന്നുള്ള സന്ദേശങ്ങൾ കാണാനും മറുപടി നൽകാനും കഴിയും. നിങ്ങളുടെ അക്കൗണ്ടിലുള്ള എല്ലാ ഏജന്റുമാരെയും ഈ പട്ടിക കാണിക്കുന്നു. p>
ഒരു പുതിയ ഏജന്റിനെ ചേർക്കുന്നതിന് ഏജന്റിനെ ചേർക്കുക b> ബട്ടൺ ക്ലിക്കുചെയ്യുക. നിങ്ങൾ ചേർത്ത ഏജന്റിന് അവരുടെ അക്കൗണ്ട് സജീവമാക്കുന്നതിന് ഒരു സ്ഥിരീകരണ ലിങ്കുള്ള ഇമെയിൽ ലഭിക്കും. അതിനുശേഷം അവർക്ക് ചാറ്റ് വൂട്ട് ആക്സസ് ചെയ്യാനും സന്ദേശങ്ങളോട് പ്രതികരിക്കാനും കഴിയും.
ഏജൻറ് b> - ഈ റോൾ ഉള്ള ഏജന്റുമാർക്ക് ഇൻബോക്സുകൾ, റിപ്പോർട്ടുകൾ, സംഭാഷണങ്ങൾ എന്നിവ മാത്രമേ ആക്സസ് ചെയ്യാൻ കഴിയൂ. അവർക്ക് മറ്റ് ഏജന്റുമാരുടെയോ അല്ലെങ്കിൽ തങ്ങളുടേയോ സംഭാഷണങ്ങൾ നിർണ്ണയിക്കാനും സംഭാഷണങ്ങൾ പരിഹരിക്കാനും കഴിയും.
അഡ്മിനിസ്ട്രേറ്റർ - ഒരു സാധാരണ ഏജന്റിന്റെ പ്രത്യേകാവകാശങ്ങളോടൊപ്പം ക്രമീകരണങ്ങളും ബില്ലിംഗും ഉൾപ്പെടെ നിങ്ങളുടെ അക്കൗണ്ടിൽ ലഭ്യമായ എല്ലാ ചാറ്റ് വൂട്ട് സവിശേഷതകളിലേക്കും ആക്സസ് ഉണ്ടായിരിക്കുക. p> ",
+ "AGENT_TYPES": [
+ {
+ "name": "administrator",
+ "label": "അഡ്മിനിസ്ട്രേറ്റർ"
+ }, {
+ "name": "agent",
+ "label": "ഏജന്റ്"
+ }
+ ],
+ "LIST": {
+ "404": "ഈ അക്കൗണ്ടുമായി ബന്ധപ്പെട്ട ഏജന്റുകളൊന്നുമില്ല",
+ "TITLE": "നിങ്ങളുടെ ടീമിലെ ഏജന്റുമാരെ മാനേജുചെയ്യുക",
+ "DESC": "നിങ്ങൾക്ക് നിങ്ങളുടെ ടീമിലെ ഏജന്റുമാരെ ചേർക്കാനും നീക്കംചെയ്യാനും കഴിയും.",
+ "NAME": "പേര്",
+ "EMAIL": "ഇമെയിൽ",
+ "STATUS": "സ്റ്റാറ്റസ്",
+ "ACTIONS": "പ്രവർത്തനങ്ങൾ",
+ "VERIFIED": "പരിശോധിച്ചു",
+ "VERIFICATION_PENDING": "പരിശോധന തീർപ്പുകൽപ്പിച്ചിട്ടില്ല"
+ },
+ "ADD": {
+ "TITLE": "നിങ്ങളുടെ ടീമിലേക്ക് ഏജന്റിനെ ചേർക്കുക",
+ "DESC": "നിങ്ങളുടെ ഇൻബോക്സുകൾക്കുള്ള പിന്തുണ കൈകാര്യം ചെയ്യാൻ കഴിയുന്ന ആളുകളെ നിങ്ങൾക്ക് ചേർക്കാൻ കഴിയും.",
+ "FORM": {
+ "NAME" : {
+ "LABEL": "ഏജന്റിന്റെ പേര്",
+ "PLACEHOLDER": "ദയവായി ഏജന്റിന്റെ പേര് നൽകുക"
+ },
+ "AGENT_TYPE" : {
+ "LABEL": "ഏജന്റ് തരം",
+ "PLACEHOLDER": "ദയവായി ഒരു തരം തിരഞ്ഞെടുക്കുക",
+ "ERROR": "ഏജന്റ് തരം ആവശ്യമാണ്"
+ },
+ "EMAIL" : {
+ "LABEL": "ഇമെയിൽ വിലാസം",
+ "PLACEHOLDER": "ദയവായി ഏജന്റിന്റെ ഒരു ഇമെയിൽ വിലാസം നൽകുക"
+ },
+ "SUBMIT": "ഏജന്റിനെ ചേർക്കുക"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "ഏജന്റിനെ വിജയകരമായി ചേർത്തു",
+ "EXIST_MESSAGE": "ഏജന്റ് ഇമെയിൽ ഇതിനകം ഉപയോഗത്തിലാണ്, ദയവായി മറ്റൊരു ഇമെയിൽ വിലാസം പരീക്ഷിക്കുക",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "ഇല്ലാതാക്കുക",
+ "API": {
+ "SUCCESS_MESSAGE": "ഏജന്റിനെ വിജയകരമായി ഇല്ലാതാക്കി",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ },
+ "CONFIRM": {
+ "TITLE": "ഇല്ലാതാക്കൽ സ്ഥിരീകരിക്കുക",
+ "MESSAGE": "ഇല്ലാതാക്കണമെന്ന് ഉറപ്പാണോ",
+ "YES": "അതെ, ഇല്ലാതാക്കുക",
+ "NO": "ഇല്ല, സൂക്ഷിക്കുക"
+ }
+ },
+ "EDIT": {
+ "TITLE": "ഏജന്റിനെ എഡിറ്റുചെയ്യുക",
+ "FORM": {
+ "NAME" : {
+ "LABEL": "ഏജന്റിന്റെ പേര്",
+ "PLACEHOLDER": "ദയവായി ഏജന്റിന്റെ പേര് നൽകുക"
+ },
+ "AGENT_TYPE" : {
+ "LABEL": "ഏജന്റ് തരം",
+ "PLACEHOLDER": "ദയവായി ഒരു തരം തിരഞ്ഞെടുക്കുക",
+ "ERROR": "ഏജന്റ് തരം ആവശ്യമാണ്"
+ },
+ "EMAIL" : {
+ "LABEL": "ഇമെയിൽ വിലാസം",
+ "PLACEHOLDER": "ദയവായി ഏജന്റിന്റെ ഒരു ഇമെയിൽ വിലാസം നൽകുക"
+ },
+ "SUBMIT": "ഏജന്റിനെ എഡിറ്റുചെയ്യുക"
+ },
+ "BUTTON_TEXT": "എഡിറ്റുചെയ്യുക",
+ "CANCEL_BUTTON_TEXT": "റദ്ദാക്കുക",
+ "API": {
+ "SUCCESS_MESSAGE": "ഏജന്റിനെ വിജയകരമായി അപ്ഡേറ്റുചെയ്തു",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ },
+ "PASSWORD_RESET": {
+ "ADMIN_RESET_BUTTON": "പാസ്സ്വേർഡ് പുനഃസജ്ജീകരണം",
+
+ "ADMIN_SUCCESS_MESSAGE": "പാസ്വേഡ് പുനഃസജ്ജീകരണത്തിന് ഉള്ള ഒരു ഇമെയിൽ ഏജന്റിന് അയച്ചു",
+ "SUCCESS_MESSAGE": "ഏജന്റിന്റെ പാസ്വേഡ് വിജയകരമായി പുനഃസജീകരിച്ചു ",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ }
+ },
+ "SEARCH": {
+ "NO_RESULTS": "ഏജന്റകളെ ഒന്നും കണ്ടെത്താൻ സാധിച്ചില്ല"
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/billing.json b/app/javascript/dashboard/i18n/locale/ml/billing.json
new file mode 100644
index 000000000..92245823d
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/billing.json
@@ -0,0 +1,19 @@
+{
+ "BILLING": {
+ "HEADER": "ബില്ലിംഗ്",
+ "LOADING": "സബ്സ്ക്രിപ്ഷനുകൾ ലഭ്യമാക്കുന്നു",
+ "ACCOUNT_STATE": "അക്കൗണ്ടിന്റെ അവസ്ഥ",
+ "AGENT_COUNT": "ഏജന്റിന്റെ എണ്ണം ",
+ "PER_AGENT_COST": "ഓരോ ഏജന്റിന്റെ വില",
+ "TOTAL_COST": "ആകെ ചെലവ്",
+ "BUTTON": {
+ "ADD": "പേയ്മെന്റ് രീതി ചേർക്കുക",
+ "EDIT": "പേയ്മെന്റ് രീതി എഡിറ്റുചെയ്യുക"
+ },
+ "TRIAL": {
+ "TITLE": "നിങ്ങളുടെ ട്രയൽ കാലയളവ് അവസാനിച്ചു",
+ "MESSAGE": "ചാറ്റ് വൂട്ട് ഉപയോഗിക്കുന്നത് തുടരാൻ ഒരു പേയ്മെന്റ് രീതി ചേർക്കുക"
+ },
+ "ACCOUNT_LOCKED": "നിങ്ങളുടെ അക്കൗണ്ട് ഇപ്പോൾ ലഭ്യമല്ല. വീണ്ടും സജീവമാക്കുന്നതിന് ദയവായി നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക."
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/cannedMgmt.json b/app/javascript/dashboard/i18n/locale/ml/cannedMgmt.json
new file mode 100644
index 000000000..7e3ad9ba1
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/cannedMgmt.json
@@ -0,0 +1,74 @@
+{
+ "CANNED_MGMT": {
+ "HEADER": "ക്യാൻഡ് പ്രതികരണങ്ങൾ",
+ "HEADER_BTN_TXT": "ക്യാൻഡ് പ്രതികരണം ചേർക്കുക",
+ "LOADING": "ക്യാൻഡ് പ്രതികരണങ്ങൾ ലഭ്യമാക്കുന്നു",
+ "SEARCH_404": "ഈ ചോദ്യവുമായി പൊരുത്തപ്പെടുന്ന ഇനങ്ങളൊന്നുമില്ല",
+ "SIDEBAR_TXT": "
ക്യാൻഡ് പ്രതികരണങ്ങൾ
ക്യാൻഡ് പ്രതികരണങ്ങൾ എന്നാൽ മുൻനിശ്ചയിച്ച മറുപടി ടെംപ്ലേറ്റുകൾ ആണ്. ഇവ ഒരു സംഭാഷണത്തിന് വേഗത്തിൽ മറുപടി അയയ്ക്കാൻ ഉപയോഗിക്കാം.
ഒരു ക്യാൻഡ് പ്രതികരണം സൃഷ്ടിക്കുന്നതിന് ക്യാൻഡ് പ്രതികരണം ചേർക്കുക എന്നതിൽ ക്ലിക്കുചെയ്യുക. എഡിറ്റുചെയ്യുക അല്ലെങ്കിൽ ഇല്ലാതാക്കുക ബട്ടൺ ക്ലിക്കുചെയ്ത് നിങ്ങൾക്ക് നിലവിലുള്ള ക്യാൻഡ് പ്രതികരണം എഡിറ്റുചെയ്യാനോ ഇല്ലാതാക്കാനോ കഴിയും
ക്യാൻഡ് പ്രതികരണങ്ങൾ ഹ്രസ്വ കോഡുകളുടെ സഹായത്തോടെ ഉപയോഗിക്കുന്നു. ചാറ്റിൽ ആയിരിക്കുമ്പോൾ ഏജന്റുമാർക്ക് ക്യാൻഡ് പ്രതികരണങ്ങൾ ആക്സസ് ചെയ്യാൻ കഴിയും. ഇതിനായി '/' എന്ന് ടൈപ്പ് ചെയ്ത ശേഷം ഹ്രസ്വ കോഡ് നൽകുക.
ചാറ്റ് വൂട്ടിലേക്ക് നിങ്ങൾ ഒരു വെബ്സൈറ്റോ ഫേസ്ബുക്ക് പേജോ കണക്റ്റുചെയ്യുമ്പോൾ, അതിനെ ഇൻബോക്സ് എന്ന് വിളിക്കുന്നു. നിങ്ങളുടെ ചാറ്റ് വൂട്ട് അക്കൗണ്ടിൽ പരിധിയില്ലാത്ത ഇൻബോക്സുകൾ ഉണ്ടായിരിക്കാൻ കഴിയും.
ഒരു വെബ്സൈറ്റ് അല്ലെങ്കിൽ ഫേസ്ബുക് പേജ് ബന്ധിപ്പിക്കുന്നതിന് ഇൻബോക്സ് ചേർക്കുക ക്ലിക്കുചെയ്യുക.
ഡാഷ്ബോർഡ് , നിങ്ങളുടെ എല്ലാ ഇൻബോക്സുകളിൽ നിന്നുമുള്ള എല്ലാ സംഭാഷണങ്ങളും ഒരൊറ്റ സ്ഥലത്ത് കാണാനും `സംഭാഷണങ്ങൾ` ടാബിന് കീഴിൽ അവയോട് പ്രതികരിക്കാനും കഴിയും.
ഡാഷ്ബോർഡിന്റെ ഇടത് പാളിയിലെ ഇൻബോക്സ് ബട്ടണിൽ ക്ലിക്കുചെയ്ത് ഇൻബോക്സിൽ ഉള്ള സംഭാഷണങ്ങൾ കാണാൻ നിങ്ങൾക്കു സാധിക്കും .
",
+ "LIST": {
+ "404": "ഈ അക്കൗണ്ടിലേക്കു ഇൻബോക്സുകളൊന്നും ബന്ധിപ്പിച്ചിട്ടില്ല."
+ },
+ "CREATE_FLOW": [
+ { "title": "ചാനൽ തിരഞ്ഞെടുക്കുക", "route": "settings_inbox_new", "body": "ചാറ്റ് വൂട്ടുമായി സംയോജിപ്പിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്ന ദാതാവിനെ തിരഞ്ഞെടുക്കുക." },
+ { "title": "ഇൻബോക്സ് സൃഷ്ടിക്കുക", "route": "settings_inboxes_page_channel", "body": "നിങ്ങളുടെ അക്കൗണ്ട് പ്രാമാണീകരിക്കുകയും ഇൻബോക്സ് സൃഷ്ടിക്കുകയും ചെയ്യുക." },
+ { "title": "ഏജന്റുമാരെ ചേർക്കുക", "route": "settings_inboxes_add_agents", "body": "സൃഷ്ടിച്ച ഇൻബോക്സിലേക്ക് ഏജന്റുമാരെ ചേർക്കുക." },
+ { "title": "പൊളിച്ചു!", "route": "settings_inbox_finish", "body": "എല്ലാം ഭംഗിയായി പാപര്യവസാനിച്ചിരിക്കുന്നു. വരൂ നമുക്ക് പോകാം." }
+ ],
+ "ADD": {
+ "FB": {
+ "HELP": "സൈൻ ഇൻ ചെയ്യുന്നതിലൂടെ, നിങ്ങളുടെ പേജിന്റെ സന്ദേശങ്ങളിലേക്ക് മാത്രമേ ഞങ്ങൾക്ക് പ്രവേശനം ലഭിക്കൂ. നിങ്ങളുടെ സ്വകാര്യ സന്ദേശങ്ങൾ ഒരിക്കലും ചാറ്റ് വൂട്ട് ഉപയോഗിച്ച് ആക്സസ് ചെയ്യാൻ കഴിയില്ല."
+ },
+ "TWITTER": {
+ "HELP": "നിങ്ങളുടെ ട്വിറ്റർ പ്രൊഫൈൽ ഒരു ചാനലായി ചേർക്കുന്നതിന്, 'ട്വിറ്ററിനൊപ്പം പ്രവേശിക്കുക' ക്ലിക്കുചെയ്ത് നിങ്ങളുടെ ട്വിറ്റർ പ്രൊഫൈൽ പ്രാമാണീകരിക്കേണ്ടതുണ്ട്. "
+ },
+ "WEBSITE_CHANNEL": {
+ "TITLE": "വെബ്സൈറ്റ് ചാനൽ",
+ "DESC": "നിങ്ങളുടെ വെബ്സൈറ്റിനായി ഒരു ചാനൽ സൃഷ്ടിച്ച് ഞങ്ങളുടെ വെബ്സൈറ്റ് വിജറ്റ് വഴി ഉപഭോക്താക്കളെ പിന്തുണയ്ക്കാൻ ആരംഭിക്കുക.",
+ "LOADING_MESSAGE": "വെബ്സൈറ്റ് സപ്പോർട്ട് ചാനൽ സൃഷ്ടിക്കുന്നു",
+ "CHANNEL_NAME": {
+ "LABEL": "വെബ്സൈറ്റിന്റെ പേര്",
+ "PLACEHOLDER": "നിങ്ങളുടെ വെബ്സൈറ്റിന്റെ പേര് നൽകുക (ഉദാ: പുണ്ണ്യാളൻ അഗർബത്തീസ്)"
+ },
+ "CHANNEL_DOMAIN": {
+ "LABEL": "വെബ്സൈറ്റ് ഡൊമെയ്ൻ",
+ "PLACEHOLDER": "നിങ്ങളുടെ വെബ്സൈറ്റ് ഡൊമെയ്ൻ നൽകുക (ഉദാ: punnyalan.com)"
+ },
+ "WIDGET_COLOR": {
+ "LABEL": "വിജറ്റ് നിറം",
+ "PLACEHOLDER": "വിജറ്റിൽ ഉപയോഗിച്ച വിജറ്റ് നിറം അപ്ഡേറ്റ് ചെയ്യുക"
+ },
+ "SUBMIT_BUTTON":"ഇൻബോക്സ് സൃഷ്ടിക്കുക"
+ },
+ "TWILIO": {
+ "TITLE": "ട്വിലിയോ എസ്.എം.എസ് ചാനൽ",
+ "DESC": "ട്വിലിയോ സംയോജിപ്പിച്ച് എസ്.എം.എസ് വഴി നിങ്ങളുടെ ഉപഭോക്താക്കളെ പിന്തുണയ്ക്കാൻ ആരംഭിക്കുക.",
+ "ACCOUNT_SID": {
+ "LABEL": "അക്കൗണ്ട് എസ്.ഐ.ഡി",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ ട്വിലിയോ അക്കൗണ്ട് എസ്.ഐ.ഡി നൽകുക",
+ "ERROR": "ഈ ഫീൽഡ് ആവശ്യമാണ്"
+ },
+ "AUTH_TOKEN": {
+ "LABEL": "ഓത്ത് ടോക്കൺ",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ ട്വിലിയോ ഓത്ത് ടോക്കൺ നൽകുക",
+ "ERROR": "ഈ ഫീൽഡ് ആവശ്യമാണ്"
+ },
+ "CHANNEL_NAME": {
+ "LABEL": "ചാനലിന്റെ പേര്",
+ "PLACEHOLDER": "ഈ ചാനലിനു ദയവായി ഒരു പേര് നൽകുക",
+ "ERROR": "ഈ ഫീൽഡ് ആവശ്യമാണ്"
+ },
+ "PHONE_NUMBER": {
+ "LABEL": "ഫോൺ നമ്പർ",
+ "PLACEHOLDER": "ദയവായി സന്ദേശം അയയ്ക്കുന്ന ഫോൺ നമ്പർ നൽകുക.",
+ "ERROR": "ദയവായി സാധുവായ ഒരു ഫോൺ നമ്പർ നൽകുക. ഫോൺ നമ്പർ `+`ചിഹ്നത്തിൽ ആരംഭിക്കണം."
+ },
+ "SUBMIT_BUTTON": "ട്വിലിയോ ചാനൽ സൃഷ്ടിക്കുക",
+ "API": {
+ "ERROR_MESSAGE": "ഞങ്ങൾക്ക് ട്വിലിയോ ക്രെഡൻഷ്യലുകൾ പ്രാമാണീകരിക്കാൻ കഴിഞ്ഞില്ല, ദയവായി വീണ്ടും ശ്രമിക്കുക."
+ }
+ },
+ "AUTH": {
+ "TITLE": "ചാനലുകൾ",
+ "DESC": "നിലവിൽ ഞങ്ങൾ വെബ്സൈറ്റ് തത്സമയ ചാറ്റ് വിഡ്ജറ്റുകൾ, ഫേസ്ബുക്ക് പേജുകൾ, ട്വിറ്റർ പ്രൊഫൈലുകൾ എന്നിവ പ്ലാറ്റ്ഫോമുകളായി പിന്തുണയ്ക്കുന്നു. വാട്ട്സ്ആപ്പ്, ഇമെയിൽ, ടെലിഗ്രാം, ലൈൻ എന്നിവപോലുള്ള കൂടുതൽ പ്ലാറ്റ്ഫോമുകൾ ഞങ്ങളുടെ പക്കലുണ്ട്, അവ ഉടൻ പുറത്തിറങ്ങുന്നത് ആയിരിക്കും."
+ },
+ "AGENTS": {
+ "TITLE": "ഏജന്റുമാർ",
+ "DESC": "നിങ്ങളുടെ പുതുതായി സൃഷ്ടിച്ച ഇൻബോക്സ് മാനേജു ചെയ്യുന്നതിന് ഇവിടെ നിങ്ങൾക്ക് ഏജന്റുമാരെ ചേർക്കാൻ കഴിയും. ഈ തിരഞ്ഞെടുത്ത ഏജന്റുമാർക്ക് മാത്രമേ നിങ്ങളുടെ ഇൻബോക്സിലേക്ക് ആക്സസ് ഉണ്ടായിരിക്കുകയുള്ളൂ. ഈ ഇൻബോക്സിന്റെ ഭാഗമല്ലാത്ത ഏജന്റുമാർക്ക് ഈ ഇൻബോക്സിലെ സന്ദേശങ്ങൾ കാണാനോ പ്രതികരിക്കാനോ കഴിയില്ല. ഒരു അഡ്മിനിസ്ട്രേറ്റർ എന്ന നിലയിൽ, നിങ്ങൾക്ക് എല്ലാ ഇൻബോക്സുകളിലേക്കും ആക്സസ് ആവശ്യമുണ്ടെങ്കിൽ, നിങ്ങൾ സൃഷ്ടിക്കുന്ന എല്ലാ ഇൻബോക്സുകളിലേക്കും നിങ്ങൾ സ്വയം ഏജന്റായി ചേർക്കണം."
+ },
+ "DETAILS": {
+ "TITLE": "ഇൻബോക്സ് വിശദാംശങ്ങൾ",
+ "DESC": "ചുവടെയുള്ള ഡ്രോപ്പ്ഡൗണിൽ നിന്ന്, നിങ്ങൾക്ക് ചാറ്റ് വൂട്ടിലേക്ക് കണക്റ്റുചെയ്യാൻ ആഗ്രഹിക്കുന്ന ഫേസ്ബുക്ക് പേജ് തിരഞ്ഞെടുക്കുക. തിരിച്ചറിയലിനായി നിങ്ങളുടെ ഇൻബോക്സിനു ഒരു ഇച്ഛാനുസൃത പേര് നല്കാൻ കഴിയും."
+ },
+ "FINISH":{
+ "TITLE": "പൊളിച്ചു അടുക്കി",
+ "DESC": "നിങ്ങളുടെ ഫേസ്ബുക്ക് പേജ് ചാറ്റ് വൂട്ടുമായി സമന്വയിപ്പിക്കുന്നത് നിങ്ങൾ വിജയകരമായി പൂർത്തിയാക്കി. അടുത്ത തവണ ഒരു ഉപയോക്താവ് നിങ്ങളുടെ പേജിലേക്ക് സന്ദേശമയയ്ക്കുമ്പോൾ, സംഭാഷണം ഓട്ടോമാറ്റിക്കലി നിങ്ങളുടെ ഇൻബോക്സിൽ ദൃശ്യമാകും. നിങ്ങൾക്ക് എളുപ്പത്തിൽ സംയോജിപ്പിക്കാൻ കഴിയുന്ന ഒരു വിജറ്റ് സ്ക്രിപ്റ്റും ഞങ്ങൾ നിങ്ങൾക്ക് നൽകുന്നു. ഇത് നിങ്ങളുടെ വെബ്സൈറ്റിലേക്ക് ചേർക്കുക. ഇത് നിങ്ങളുടെ വെബ്സൈറ്റിൽ തത്സമയമായിക്കഴിഞ്ഞാൽ, ഉപയോക്താക്കൾക്ക് നിങ്ങളുടെ വെബ്സൈറ്റിൽ നിന്ന് നിങ്ങൾക്ക് സന്ദേശം അയയ്ക്കാൻ കഴിയും, ഒപ്പം സംഭാഷണം ചാറ്റ് വൂട്ടിൽ തന്നെ ദൃശ്യമാകും. കൊള്ളാം, അല്ലേ? :)"
+ }
+ },
+ "DETAILS": {
+ "LOADING_FB": "ഫേസ്ബുക് ഉപയോഗിച്ച് നിങ്ങളെ പ്രാമാണീകരിക്കുന്നു...",
+ "ERROR_FB_AUTH": "എന്തോ കുഴപ്പം സംഭവിച്ചു, ദയവായി പേജ് പുതുക്കുക...",
+ "CREATING_CHANNEL": "നിങ്ങളുടെ ഇൻബോക്സ് സൃഷ്ടിച്ചു കൊണ്ട് ഇരിക്കുകയാണ്...",
+ "TITLE": "ഇൻബോക്സ് വിശദാംശങ്ങൾ കോൺഫിഗർ ചെയ്യുക",
+ "DESC": ""
+ },
+ "AGENTS": {
+ "BUTTON_TEXT": "ഏജന്റുമാരെ ചേർക്കുക",
+ "ADD_AGENTS": "നിങ്ങളുടെ ഇൻബോക്സിലേക്ക് ഏജന്റുമാരെ ചേർക്കുകയാണ്..."
+ },
+ "FINISH": {
+ "TITLE": "നിങ്ങളുടെ ഇൻബോക്സ് തയ്യാറാണ്!",
+ "MESSAGE": "നിങ്ങളുടെ പുതിയ ചാനലിലൂടെ നിങ്ങൾക്ക് ഇപ്പോൾ ഉപഭോക്താക്കളുമായി ഇടപഴകാൻ കഴിയും. പിന്തുണയ്ക്കുന്നതിൽ സന്തോഷിക്കൂ.",
+ "BUTTON_TEXT": "എന്നെ അവിടേക്ക് കൊണ്ടുപോകുക",
+ "WEBSITE_SUCCESS": "നിങ്ങൾ ഒരു വെബ്സൈറ്റ് ചാനൽ സൃഷ്ടിക്കുന്നത് വിജയകരമായി പൂർത്തിയാക്കി. ചുവടെ കാണിച്ചിരിക്കുന്ന കോഡ് പകർത്തി നിങ്ങളുടെ വെബ്സൈറ്റിൽ ചേർക്കുക. അടുത്ത തവണ ഒരു ഉപഭോക്താവ് തത്സമയ ചാറ്റ് ഉപയോഗിക്കുമ്പോൾ, സംഭാഷണം ഓട്ടോമാറ്റിക് ആയി നിങ്ങളുടെ ഇൻബോക്സിൽ ദൃശ്യമാകും."
+ },
+ "REAUTH": "വീണ്ടും അംഗീകാരം നൽകുക",
+ "VIEW": "കാണുക",
+ "EDIT": {
+ "API": {
+ "SUCCESS_MESSAGE": "വിജറ്റ് നിറം വിജയകരമായി അപ്ഡേറ്റു ചെയ്തു",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "ഓട്ടോമാറ്റിക് അസൈൻമെന്റ് വിജയകരമായി അപ്ഡേറ്റുചെയ്തു",
+ "ERROR_MESSAGE": "വിജറ്റ് നിറം അപ്ഡേറ്റ് ചെയ്യാൻ കഴിഞ്ഞില്ല. ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക."
+ },
+ "AUTO_ASSIGNMENT": {
+ "ENABLED": "പ്രവർത്തനക്ഷമമാക്കി",
+ "DISABLED": "പ്രവർത്തനരഹിതമാക്കി"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "ഇല്ലാതാക്കുക",
+ "CONFIRM": {
+ "TITLE": "ഇല്ലാതാക്കൽ സ്ഥിരീകരിക്കുക",
+ "MESSAGE": "ഇല്ലാതാക്കണമെന്നു ഉറപ്പാണോ ",
+ "YES": "അതെ, ഇല്ലാതാക്കുക ",
+ "NO": "ഇല്ല, സൂക്ഷിക്കുക "
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "ഇൻബോക്സ് വിജയകരമായി ഇല്ലാതാക്കിയിരിക്കുന്നു",
+ "ERROR_MESSAGE": "ഇൻബോക്സ് ഇല്ലാതാക്കാൻ കഴിഞ്ഞില്ല. ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക."
+ }
+ },
+ "SETTINGS": "ക്രമീകരണങ്ങൾ",
+ "SETTINGS_POPUP": {
+ "MESSENGER_HEADING": "മെസഞ്ചർ സ്ക്രിപ്റ്റ്",
+ "MESSENGER_SUB_HEAD": "ഈ ബട്ടൺ നിങ്ങളുടെ ബോഡി ടാഗിനുള്ളിൽ സ്ഥാപിക്കുക",
+ "INBOX_AGENTS": "ഏജന്റുമാർ",
+ "INBOX_AGENTS_SUB_TEXT": "ഈ ഇൻബോക്സിൽ നിന്ന് ഏജന്റുമാരെ ചേർക്കുക അല്ലെങ്കിൽ നീക്കംചെയ്യുക",
+ "UPDATE": "അപ്ഡേറ്റ്",
+ "AUTO_ASSIGNMENT": "ഓട്ടോ അസൈൻമെന്റ് പ്രവർത്തനക്ഷമമാക്കുക",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "പുതിയ സംഭാഷണങ്ങളിൽ ലഭ്യമായ ഏജന്റുമാരുടെ ഓട്ടോമാറ്റിക് അസൈൻമെന്റ് പ്രാപ്തമാക്കുകയോ അപ്രാപ്തമാക്കുകയോ ചെയ്യുക"
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/index.js b/app/javascript/dashboard/i18n/locale/ml/index.js
new file mode 100644
index 000000000..351906dd9
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/index.js
@@ -0,0 +1,34 @@
+/* eslint-disable */
+import { default as _agentMgmt } from './agentMgmt.json';
+import { default as _billing } from './billing.json';
+import { default as _cannedMgmt } from './cannedMgmt.json';
+import { default as _chatlist } from './chatlist.json';
+import { default as _contact } from './contact.json';
+import { default as _conversation } from './conversation.json';
+import { default as _inboxMgmt } from './inboxMgmt.json';
+import { default as _login } from './login.json';
+import { default as _report } from './report.json';
+import { default as _resetPassword } from './resetPassword.json';
+import { default as _setNewPassword } from './setNewPassword.json';
+import { default as _settings } from './settings.json';
+import { default as _signup } from './signup.json';
+import { default as _integrations } from './integrations.json';
+import { default as _generalSettings } from './generalSettings.json';
+
+export default {
+ ..._agentMgmt,
+ ..._billing,
+ ..._cannedMgmt,
+ ..._chatlist,
+ ..._contact,
+ ..._conversation,
+ ..._inboxMgmt,
+ ..._login,
+ ..._report,
+ ..._resetPassword,
+ ..._setNewPassword,
+ ..._settings,
+ ..._signup,
+ ..._integrations,
+ ..._generalSettings,
+};
diff --git a/app/javascript/dashboard/i18n/locale/ml/integrations.json b/app/javascript/dashboard/i18n/locale/ml/integrations.json
new file mode 100644
index 000000000..77e19c7fb
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/integrations.json
@@ -0,0 +1,54 @@
+{
+ "INTEGRATION_SETTINGS": {
+ "HEADER": "സംയോജനങ്ങൾ",
+ "WEBHOOK": {
+ "TITLE": "വെബ്ഹൂക്ക്",
+ "CONFIGURE": "കോൺഫിഗർ",
+ "HEADER": "വെബ്ഹൂക്ക് ക്രമീകരണങ്ങൾ",
+ "HEADER_BTN_TXT": "പുതിയ വെബ്ഹൂക്ക് ഉണ്ടാക്കുക",
+ "INTEGRATION_TXT": "നിങ്ങളുടെ ചാറ്റ് വൂട്ട് അക്കൗണ്ടിൽ എന്താണ് സംഭവിക്കുന്നതെന്നതിനെക്കുറിച്ചുള്ള തത്സമയ വിവരങ്ങൾ വെബ്ഹൂക്ക് ഇവന്റുകൾ നൽകുന്നു. സ്ലാക്ക് അല്ലെങ്കിൽ ഗിറ്റ്ഹബ് പോലുള്ള നിങ്ങളുടെ പ്രിയപ്പെട്ട അപ്ലിക്കേഷനുകളിലേക്ക് ആശയവിനിമയം നടത്താൻ നിങ്ങൾക്ക് വെബ്ഹൂക്കുകൾ ഉപയോഗിക്കാൻ കഴിയും. നിങ്ങളുടെ വെബ്ഹൂക്കുകൾ സജ്ജീകരിക്കുന്നതിന് കോൺഫിഗർ ചെയ്യുക ക്ലിക്കു ചെയ്യുക.",
+ "LOADING": "അറ്റാച്ചുചെയ്ത വെബ്ഹൂക്കുകൾ ലഭ്യമാക്കുന്നു...",
+ "SEARCH_404": "ഈ ചോദ്യവുമായി പൊരുത്തപ്പെടുന്ന ഇനങ്ങളൊന്നുമില്ല",
+ "SIDEBAR_TXT": "
വെബ്ഹൂക്കുകൾ
എല്ലാ അക്കൗണ്ടിനും നിർവചിക്കാവുന്ന എച്ച്.ടി.ടി.പി കോൾബാക്കുകളാണ് വെബ്ഹൂക്കുകൾ. ചാറ്റ്വൂട്ടിലെ സന്ദേശ സൃഷ്ടിക്കൽ പോലുള്ള ഇവന്റുകളാണ് അവ പ്രവർത്തനക്ഷമമാക്കുന്നത്. ഈ അക്കൗണ്ടിനായി നിങ്ങൾക്ക് ഒന്നിൽ കൂടുതൽ വെബ്ഹൂക്കുകൾ സൃഷ്ടിക്കാൻ കഴിയും.
ഒരു വെബ്ഹൂക്ക് സൃഷ്ടിക്കുന്നതിന്, പുതിയ വെബ്ഹൂക്ക് ഉണ്ടാക്കുക ബട്ടണിൽ ക്ലിക്കുചെയ്യുക. ഇല്ലാതാക്കുക ബട്ടണിൽ ക്ലിക്കുചെയ്ത് നിങ്ങൾക്ക് നിലവിലുള്ള ഏതെങ്കിലും വെബ്ഹൂക്ക് നീക്കംചെയ്യാനും കഴിയും.
",
+ "LIST": {
+ "404": "ഈ അക്കൗണ്ടിനായി വെബ്ഹൂക്കുകളൊന്നും ക്രമീകരിച്ചിട്ടില്ല.",
+ "TITLE": "വെബ്ഹൂക്കുകൾ നിയന്ത്രിക്കുക",
+ "DESC": "വെബ്ഹൂക്കുകൾ മുൻനിശ്ചയിച്ച മറുപടി ടെംപ്ലേറ്റുകളാണ്, അവ ടിക്കറ്റുകൾക്ക് വേഗത്തിൽ മറുപടി അയയ്ക്കാൻ ഉപയോഗിക്കാം.",
+ "TABLE_HEADER": [
+ "വെബ്ഹൂക്ക് എൻഡ്പോയിന്റ്",
+ "പ്രവർത്തനങ്ങൾ"
+ ]
+ },
+ "ADD": {
+ "CANCEL": "റദ്ദാക്കുക",
+ "TITLE": "പുതിയ വെബ്ഹൂക്ക് ഉണ്ടാക്കുക",
+ "DESC": "നിങ്ങളുടെ ചാറ്റ് വൂട്ട് അക്കൗണ്ടിൽ എന്താണ് സംഭവിക്കുന്നതെന്നതിനെക്കുറിച്ചുള്ള തത്സമയ വിവരങ്ങൾ വെബ്ഹൂക്ക് ഇവന്റുകൾ നൽകുന്നു. ഒരു കോൾബാക്ക് കോൺഫിഗർ ചെയ്യുന്നതിന് സാധുവായ ഒരു യു.ആർ.എൽ നൽകുക.",
+ "FORM": {
+ "END_POINT": {
+ "LABEL": "വെബ്ഹുക്ക് യു.ആർ.എൽ",
+ "PLACEHOLDER": "ഉദാഹരണം: https://example/api/webhook",
+ "ERROR": "ദയവായി സാധുവായ ഒരു യു.ആർ.എൽ നൽകുക"
+ },
+ "SUBMIT": "വെബ്ഹുക്ക് സൃഷ്ടിക്കുക"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "വെബ്ഹുക്ക് വിജയകരമായി ചേർത്തു",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക."
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "ഇല്ലാതാക്കുക",
+ "API": {
+ "SUCCESS_MESSAGE": "വെബ്ഹൂക്ക് വിജയകരമായി ഇല്ലാതാക്കി",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക."
+ },
+ "CONFIRM": {
+ "TITLE": "ഇല്ലാതാക്കൽ സ്ഥിരീകരിക്കുക",
+ "MESSAGE": "ഇല്ലാതാക്കണമെന്ന് ഉറപ്പാണോ ",
+ "YES": "അതെ, ഇല്ലാതാക്കുക ",
+ "NO": "ഇല്ല, സൂക്ഷിക്കുക "
+ }
+ }
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/login.json b/app/javascript/dashboard/i18n/locale/ml/login.json
new file mode 100644
index 000000000..85002fd74
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/login.json
@@ -0,0 +1,21 @@
+{
+ "LOGIN": {
+ "TITLE": "ചാറ്റ് വൂട്ടിലേക്ക് ലോഗിൻ ചെയ്യുക",
+ "EMAIL": {
+ "LABEL": "ഇമെയിൽ",
+ "PLACEHOLDER": "ഇമെയിൽ ഉദാ: someone@example.com"
+ },
+ "PASSWORD": {
+ "LABEL": "പാസ്വേഡ്",
+ "PLACEHOLDER": "പാസ്വേഡ്"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "ലോഗിൻ വിജയകരം",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റു ചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക",
+ "UNAUTH": "ഉപയോക്തൃനാമം / പാസ്വേഡ് തെറ്റാണ്. ദയവായി വീണ്ടും ശ്രമിക്കുക."
+ },
+ "FORGOT_PASSWORD": "നിങ്ങളുടെ പാസ്വേഡ് മറന്നോ?",
+ "CREATE_NEW_ACCOUNT": "പുതിയ അക്കൗണ്ട് സൃഷ്ടിക്കുക",
+ "SUBMIT": "സൈൻ ഇൻ"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/report.json b/app/javascript/dashboard/i18n/locale/ml/report.json
new file mode 100644
index 000000000..6438b4774
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/report.json
@@ -0,0 +1,19 @@
+{
+ "REPORT": {
+ "HEADER": "റിപ്പോർട്ടുകൾ",
+ "LOADING_CHART": "ചാർട്ട് ഡാറ്റ ലോഡു ചെയ്യുകയാണ്...",
+ "NO_ENOUGH_DATA": "റിപ്പോർട്ട് സൃഷ്ടിക്കുന്നതിന് ആവശ്യമായ ഡാറ്റ ഞങ്ങൾക്ക് ലഭിച്ചിട്ടില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക.",
+ "METRICS": [
+ { "NAME": "സംഭാഷണങ്ങൾ", "KEY": "conversations_count", "DESC": "(ആകെ)" },
+ { "NAME": "ഇൻകമിംഗ് സന്ദേശങ്ങൾ", "KEY": "incoming_messages_count", "DESC": "( ആകെ )" },
+ { "NAME": "ഔട്ട് ഗോയിങ് സന്ദേശങ്ങൾ", "KEY": "outgoing_messages_count", "DESC": "( ആകെ )" },
+ { "NAME": "ആദ്യ പ്രതികരണ സമയം", "KEY": "avg_first_response_time", "DESC": "( ശരാശരി )" },
+ { "NAME": "മിഴിവ് സമയം", "KEY": "avg_resolution_time", "DESC": "( ശരാശരി )" },
+ { "NAME": "മിഴിവ് എണ്ണം", "KEY": "resolutions_count", "DESC": "( ആകെ )" }
+ ],
+ "DATE_RANGE": [
+ { "id": 0, "name": "കഴിഞ്ഞ 7 ദിവസം" },
+ { "id": 1, "name": "കഴിഞ്ഞ 30 ദിവസം" }
+ ]
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/resetPassword.json b/app/javascript/dashboard/i18n/locale/ml/resetPassword.json
new file mode 100644
index 000000000..66b59eec0
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/resetPassword.json
@@ -0,0 +1,15 @@
+{
+ "RESET_PASSWORD": {
+ "TITLE": "പാസ്വേഡ് പുനഃസജീകരിക്കുക",
+ "EMAIL": {
+ "LABEL": "ഇമെയിൽ",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ ഇമെയിൽ നൽകുക",
+ "ERROR": "ദയവായി സാധുവായ ഒരു ഇമെയിൽ നൽകുക"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "പാസ്വേഡ് പുനഃസജ്ജീകരണ ലിങ്ക് നിങ്ങളുടെ ഇമെയിലിലേക്ക് അയച്ചു",
+ "ERROR_MESSAGE": "വൂട്ട് സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ },
+ "SUBMIT": "സമർപ്പിക്കുക"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/setNewPassword.json b/app/javascript/dashboard/i18n/locale/ml/setNewPassword.json
new file mode 100644
index 000000000..6fbacf70c
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/setNewPassword.json
@@ -0,0 +1,20 @@
+{
+ "SET_NEW_PASSWORD": {
+ "TITLE": "പുതിയ പാസ്വേഡ് സജ്ജമാക്കുക",
+ "PASSWORD": {
+ "LABEL": "പാസ്വേഡ്",
+ "PLACEHOLDER": "പാസ്വേഡ്",
+ "ERROR": "പാസ്വേഡ് വളരെ ചെറുതാണ്"
+ },
+ "CONFIRM_PASSWORD": {
+ "LABEL": "പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
+ "PLACEHOLDER": "പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
+ "ERROR": "പാസ്വേഡുകൾ പൊരുത്തപ്പെടുന്നില്ല"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "പാസ്വേഡ് വിജയകരമായി മാറ്റി",
+ "ERROR_MESSAGE": "സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ },
+ "SUBMIT": "സമർപ്പിക്കുക"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/settings.json b/app/javascript/dashboard/i18n/locale/ml/settings.json
new file mode 100644
index 000000000..1543573b4
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/settings.json
@@ -0,0 +1,62 @@
+{
+ "PROFILE_SETTINGS": {
+ "LINK": "പ്രൊഫൈൽ ക്രമീകരണങ്ങൾ",
+ "TITLE": "പ്രൊഫൈൽ ക്രമീകരണങ്ങൾ",
+ "BTN_TEXT": "പ്രൊഫൈൽ അപ്ഡേറ്റ് ചെയ്യുക",
+ "AFTER_EMAIL_CHANGED": "നിങ്ങളുടെ പ്രൊഫൈൽ വിജയകരമായി അപ്ഡേറ്റു ചെയ്തിരിക്കുന്നു, ലോഗിൻ ക്രെഡൻഷ്യലുകൾ മാറ്റിയതിനാൽ ദയവായി വീണ്ടും ലോഗിൻ ചെയ്യുക",
+ "FORM": {
+ "AVATAR": "പ്രൊഫൈൽ ചിത്രം",
+ "ERROR": "ദയവായി ഫോമിലെ പിശകുകൾ പരിഹരിക്കുക",
+ "REMOVE_IMAGE": "നീക്കം ചെയ്യുക",
+ "UPLOAD_IMAGE": "ചിത്രം അപ്ലോഡു ചെയ്യുക",
+ "UPDATE_IMAGE": "ചിത്രം അപ്ഡേറ്റു ചെയ്യുക",
+ "PROFILE_SECTION" : {
+ "TITLE": "പ്രൊഫൈൽ",
+ "NOTE": "നിങ്ങളുടെ ഇമെയിൽ വിലാസം നിങ്ങളുടെ ഐഡന്റിറ്റിയാണ്, ഒപ്പം ലോഗിൻ ചെയ്യാൻ ഇതാണ് ഉപയോഗിക്കേണ്ടത്."
+ },
+ "PASSWORD_SECTION" : {
+ "TITLE": "പാസ്വേഡ്",
+ "NOTE": "നിങ്ങളുടെ പാസ്വേഡ് അപ്ഡേറ്റ് ചെയ്യുന്നത് ഒന്നിലധികം ഉപകരണങ്ങളിൽ നിങ്ങളുടെ ലോഗിനുകൾ പുനഃസജ്ജീകരിക്കും."
+ },
+ "ACCESS_TOKEN": {
+ "TITLE": "ആക്സസ് ടോക്കൺ",
+ "NOTE": "നിങ്ങൾ ഒരു എ.പി.ഐ അടിസ്ഥാനമാക്കിയുള്ള സംയോജനം നിർമ്മിക്കുകയാണെങ്കിൽ ഈ ടോക്കൺ ഉപയോഗിക്കാൻ കഴിയും"
+ },
+ "EMAIL_NOTIFICATIONS_SECTION" : {
+ "TITLE": "ഇമെയിൽ അറിയിപ്പുകൾ",
+ "NOTE": "നിങ്ങളുടെ ഇമെയിൽ അറിയിപ്പ് മുൻഗണനകൾ ഇവിടെ അപ്ഡേറ്റു ചെയ്യുക.",
+ "CONVERSATION_ASSIGNMENT": "ഒരു സംഭാഷണം എനിക്ക് നിയോഗിക്കുമ്പോൾ ഇമെയിൽ അറിയിപ്പുകൾ അയയ്ക്കുക",
+ "CONVERSATION_CREATION": "ഒരു പുതിയ സംഭാഷണം സൃഷ്ടിക്കുമ്പോൾ ഇമെയിൽ അറിയിപ്പുകൾ അയയ്ക്കുക",
+ "UPDATE_SUCCESS": "നിങ്ങളുടെ ഇമെയിൽ അറിയിപ്പ് മുൻഗണനകൾ വിജയകരമായി അപ്ഡേറ്റു ചെയ്തു",
+ "UPDATE_ERROR": "മുൻഗണനകൾ അപ്ഡേറ്റു ചെയ്യുമ്പോൾ ഒരു പിശക് ഉണ്ട്, ദയവായി വീണ്ടും ശ്രമിക്കുക"
+ },
+ "PROFILE_IMAGE":{
+ "LABEL": "പ്രൊഫൈൽ ചിത്രം"
+ },
+ "NAME": {
+ "LABEL": "നിങ്ങളുടെ പേര്",
+ "ERROR": "ദയവായി സാധുവായ ഒരു പേര് നൽകുക",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ പേര് നൽകുക, ഇത് സംഭാഷണങ്ങളിൽ ദൃശ്യമാകും"
+ },
+ "EMAIL": {
+ "LABEL": "നിങ്ങളുടെ ഇമെയിൽ വിലാസം",
+ "ERROR": "ദയവായി സാധുവായ ഒരു ഇമെയിൽ വിലാസം നൽകുക",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ ഇമെയിൽ വിലാസം നൽകുക, ഇത് സംഭാഷണങ്ങളിൽ ദൃശ്യമാകും"
+ },
+ "PASSWORD": {
+ "LABEL": "പാസ്വേഡ്",
+ "ERROR": "ദയവായി 6 അല്ലെങ്കിൽ അതിൽ കൂടുതൽ ദൈർഘ്യമുള്ള പാസ്വേഡ് നൽകുക",
+ "PLACEHOLDER": "ദയവായി ഒരു പുതിയ പാസ്വേഡ് നൽകുക"
+ },
+ "PASSWORD_CONFIRMATION": {
+ "LABEL": "പുതിയ പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
+ "ERROR": "പാസ്വേഡുകൾ പൊരുത്തപ്പെടുന്നില്ല",
+ "PLACEHOLDER": "ദയവായി നിങ്ങളുടെ പാസ്വേഡ് വീണ്ടും നൽകുക"
+ }
+ }
+ },
+ "SIDEBAR_ITEMS": {
+ "PROFILE_SETTINGS": "പ്രൊഫൈൽ ക്രമീകരണങ്ങൾ",
+ "LOGOUT": "ലോഗൗട്ട്"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/signup.json b/app/javascript/dashboard/i18n/locale/ml/signup.json
new file mode 100644
index 000000000..3128ec300
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/signup.json
@@ -0,0 +1,32 @@
+{
+ "REGISTER": {
+ "TRY_WOOT": "ഒരു അക്കൗണ്ട് രജിസ്റ്റർ ചെയ്യുക",
+ "TITLE": "രജിസ്റ്റർ",
+ "TERMS_ACCEPT": "സൈൻ അപ്പ് ചെയ്യുന്നതിലൂടെ, നിങ്ങൾ ഞങ്ങളുടെ ഉപാധികളും നിബന്ധനകളുംസ്വകാര്യതാ നയങ്ങളും അംഗീകരിക്കുന്നു.",
+ "ACCOUNT_NAME": {
+ "LABEL": "അക്കൗണ്ട് നാമം",
+ "PLACEHOLDER": "പുണ്ണ്യാളൻ അഗർബത്തീസ്",
+ "ERROR": "അക്കൗണ്ട് നാമം വളരെ ചെറുതാണ്"
+ },
+ "EMAIL": {
+ "LABEL": "ഇമെയിൽ",
+ "PLACEHOLDER": "punyalan@agarbathis.in",
+ "ERROR": "ഇമെയിൽ അസാധുവാണ്"
+ },
+ "PASSWORD": {
+ "LABEL": "പാസ്വേഡ്",
+ "PLACEHOLDER": "പാസ്വേഡ്",
+ "ERROR": "പാസ്വേഡ് വളരെ ചെറുതാണ്"
+ },
+ "CONFIRM_PASSWORD": {
+ "LABEL": "പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
+ "PLACEHOLDER": "പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
+ "ERROR": "പാസ്വേഡുകൾ പൊരുത്തപ്പെടുന്നില്ല"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "രജിസ്ട്രേഷൻ വിജയകരമാണ്",
+ "ERROR_MESSAGE": "സെർവറിലേക്ക് കണക്റ്റുചെയ്യാനായില്ല, ദയവായി പിന്നീട് വീണ്ടും ശ്രമിക്കുക"
+ },
+ "SUBMIT": "സമർപ്പിക്കുക"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ml/webhooks.json b/app/javascript/dashboard/i18n/locale/ml/webhooks.json
new file mode 100644
index 000000000..a628f5e01
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ml/webhooks.json
@@ -0,0 +1,5 @@
+{
+ "WEBHOOKS_SETTINGS": {
+ "HEADER": "വെബ്ഹൂക്ക് ക്രമീകരണങ്ങൾ"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/ml.js b/app/javascript/dashboard/i18n/ml.js
new file mode 100644
index 000000000..1fcce9edc
--- /dev/null
+++ b/app/javascript/dashboard/i18n/ml.js
@@ -0,0 +1,40 @@
+import ml from './locale/ml';
+
+export default {
+ ...ml,
+ APP_GLOBAL: {
+ TRIAL_MESSAGE: 'ദിവസത്തെ ട്രയൽ ശേഷിക്കുന്നു.',
+ TRAIL_BUTTON: 'ഇപ്പോൾ വാങ്ങുക',
+ },
+ COMPONENTS: {
+ CODE: {
+ BUTTON_TEXT: 'പകർത്തുക',
+ COPY_SUCCESSFUL: 'കോഡ് വിജയകരമായി ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തി',
+ },
+ FILE_BUBBLE: {
+ DOWNLOAD: 'ഡൗൺലോഡുചെയ്യുക',
+ UPLOADING: 'അപ്ലോഡുചെയ്യുന്നു...',
+ },
+ FORM_BUBBLE: {
+ SUBMIT: 'സമർപ്പിക്കുക',
+ },
+ },
+ CONFIRM_EMAIL: 'പരിശോധിച്ചുറപ്പിക്കുന്നു...',
+ SETTINGS: {
+ INBOXES: {
+ NEW_INBOX: 'ഇൻബോക്സ് ചേർക്കുക',
+ },
+ },
+ SIDEBAR: {
+ CONVERSATIONS: 'സംഭാഷണങ്ങൾ',
+ REPORTS: 'റിപ്പോർട്ടുകൾ',
+ SETTINGS: 'ക്രമീകരണങ്ങൾ',
+ HOME: 'ഹോം',
+ AGENTS: 'ഏജന്റുമാർ',
+ INBOXES: 'ഇൻബോക്സുകൾ',
+ CANNED_RESPONSES: 'ക്യാൻഡ് പ്രതികരണങ്ങൾ',
+ BILLING: 'ബില്ലിംഗ്',
+ INTEGRATIONS: 'സംയോജനങ്ങൾ',
+ ACCOUNT_SETTINGS: 'അക്കൗണ്ട് ക്രമീകരണങ്ങൾ',
+ },
+};
diff --git a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
index f87bd20b0..f4a983294 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
@@ -26,6 +26,7 @@
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.ERROR') }}
diff --git a/config/initializers/languages.rb b/config/initializers/languages.rb
index 3d463955f..c04f47a55 100644
--- a/config/initializers/languages.rb
+++ b/config/initializers/languages.rb
@@ -14,5 +14,6 @@ LANGUAGES_CONFIG = {
9 => { name: 'Portugues', iso_639_3_code: 'por', iso_639_1_code: 'pt' },
10 => { name: 'Russian', iso_639_3_code: 'rus', iso_639_1_code: 'ru' },
11 => { name: 'Chinese', iso_639_3_code: 'zho', iso_639_1_code: 'zh' },
- 12 => { name: 'Spanish', iso_639_3_code: 'spa', iso_639_1_code: 'es' }
+ 12 => { name: 'Spanish', iso_639_3_code: 'spa', iso_639_1_code: 'es' },
+ 13 => { name: 'Malayalam', iso_639_3_code: 'mal', iso_639_1_code: 'ml' }
}.freeze
diff --git a/config/locales/ml.yml b/config/locales/ml.yml
new file mode 100644
index 000000000..e8d183d8c
--- /dev/null
+++ b/config/locales/ml.yml
@@ -0,0 +1,56 @@
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# The following keys must be escaped otherwise they will not be retrieved by
+# the default I18n backend:
+#
+# true, false, on, off, yes, no
+#
+# Instead, surround them with single quotes.
+#
+# en:
+# 'true': 'foo'
+#
+# To learn more, please read the Rails Internationalization guide
+# available at https://guides.rubyonrails.org/i18n.html.
+
+ml:
+ hello: "ലോകത്തിനു നമസ്ക്കാരം 🙏"
+ messages:
+ reset_password_success: Woot! പാസ്വേഡ് പുനസജ്ജീകരണത്തിനുള്ള അഭ്യർത്ഥന വിജയകരമാണ്. നിർദ്ദേശങ്ങൾക്കായി നിങ്ങളുടെ മെയിൽ പരിശോധിക്കുക.
+ reset_password_failure: ക്ഷമിക്കണം! നിർദ്ദിഷ്ട ഇമെയിൽ ഉള്ള ഒരു ഉപയോക്താവിനെയും ഞങ്ങൾക്ക് കണ്ടെത്താൻ കഴിഞ്ഞില്ല.
+
+ errors:
+ signup:
+ disposable_email: ഡിസ്പോസിബിൾ ഇമെയിലുകൾ ഞങ്ങൾ അനുവദിക്കുന്നില്ല
+ invalid_email: നിങ്ങൾ ഒരു അസാധുവായ ഇമെയിൽ നൽകി
+ email_already_exists: "നിങ്ങൾ ഇതിനകം ഈ %{email} ഉപയോഗിച്ചു ഒരു അക്കൗണ്ടിനായി സൈൻ അപ്പ് ചെയ്തു"
+ failed: സൈനപ്പ് പരാജയപ്പെട്ടു
+
+ conversations:
+ activity:
+ status:
+ resolved: "സംഭാഷണം %{user_name} പരിഹരിച്ചതായി അടയാളപ്പെടുത്തി"
+ open: "സംഭാഷണം %{user_name} വീണ്ടും തുറന്നു"
+ assignee:
+ assigned: "%{assignee_name} %{user_name}-നെ നിയുക്തനാക്കി "
+ removed: "%{user_name} സംഭാഷണം നിയുക്തമല്ലാതാക്കി"
+ templates:
+ typical_reply_message_body: "%{account_name} സാധാരണ കുറച്ച് മണിക്കൂറിനുള്ളിൽ മറുപടി നൽകുന്നു."
+ ways_to_reach_you_message_body: "നിങ്ങളിലേക്ക് എത്താൻ ടീമിന് ഒരു വഴി നൽകുക."
+ email_input_box_message_body: "ഇമെയിൽ വഴി അറിയിപ്പ് നേടുക"
From 743bddc0657c800ca5b932ba405fa70e3291cb46 Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Thu, 16 Apr 2020 15:05:01 +0530
Subject: [PATCH 08/57] Chore: Housekeeping tasks (#721)
- End point to return api version
- Move agent bot listener to sync dispatcher
- gem update
---
Gemfile.lock | 32 ++++++++++++-------------
app/controllers/api_controller.rb | 8 +++++++
app/dispatchers/async_dispatcher.rb | 2 +-
app/dispatchers/sync_dispatcher.rb | 2 +-
config/app.yml | 14 +++++++++++
config/application.rb | 7 ++++++
config/routes.rb | 1 +
spec/controllers/api_controller_spec.rb | 11 +++++++++
8 files changed, 59 insertions(+), 18 deletions(-)
create mode 100644 app/controllers/api_controller.rb
create mode 100644 config/app.yml
create mode 100644 spec/controllers/api_controller_spec.rb
diff --git a/Gemfile.lock b/Gemfile.lock
index 0ad798ef4..6c9edc7ef 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -82,10 +82,10 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.0)
attr_extras (6.2.3)
- aws-eventstream (1.0.3)
- aws-partitions (1.294.0)
- aws-sdk-core (3.92.0)
- aws-eventstream (~> 1.0, >= 1.0.2)
+ aws-eventstream (1.1.0)
+ aws-partitions (1.296.0)
+ aws-sdk-core (3.94.0)
+ aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
@@ -113,7 +113,7 @@ GEM
bindex (0.8.1)
bootsnap (1.4.6)
msgpack (~> 1.0)
- brakeman (4.8.0)
+ brakeman (4.8.1)
browser (4.0.0)
builder (3.2.4)
bullet (6.1.0)
@@ -179,7 +179,7 @@ GEM
foreman (0.87.1)
globalid (0.4.2)
activesupport (>= 4.2.0)
- google-api-client (0.37.2)
+ google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
@@ -193,20 +193,20 @@ GEM
google-cloud-env (1.3.1)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.0)
- google-cloud-storage (1.25.1)
+ google-cloud-storage (1.26.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
- googleauth (0.11.0)
+ googleauth (0.12.0)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
- signet (~> 0.12)
+ signet (~> 0.14)
groupdate (5.0.0)
activesupport (>= 5)
haikunator (1.1.0)
@@ -253,7 +253,7 @@ GEM
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
- loofah (2.4.0)
+ loofah (2.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@@ -284,21 +284,21 @@ GEM
orm_adapter (0.5.0)
os (1.1.0)
parallel (1.19.1)
- parser (2.7.1.0)
+ parser (2.7.1.1)
ast (~> 2.4.0)
pg (1.2.3)
- pry (0.13.0)
+ pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
- public_suffix (4.0.3)
+ public_suffix (4.0.4)
puma (4.3.3)
nio4r (~> 2.0)
pundit (2.1.0)
activesupport (>= 3.0.0)
rack (2.2.2)
- rack-cache (1.11.0)
+ rack-cache (1.11.1)
rack (>= 0.4)
rack-cors (1.1.1)
rack (>= 2.0.0)
@@ -388,7 +388,7 @@ GEM
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
- rubocop-rails (2.5.1)
+ rubocop-rails (2.5.2)
activesupport
rack (>= 1.1)
rubocop (>= 0.72.0)
@@ -463,7 +463,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
uniform_notifier (1.13.0)
- valid_email2 (3.2.1)
+ valid_email2 (3.2.2)
activemodel (>= 3.2)
mail (~> 2.5)
virtus (1.0.5)
diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb
new file mode 100644
index 000000000..3d7f59f0c
--- /dev/null
+++ b/app/controllers/api_controller.rb
@@ -0,0 +1,8 @@
+class ApiController < ApplicationController
+ skip_before_action :set_current_user, only: [:index]
+ skip_before_action :check_subscription, only: [:index]
+
+ def index
+ render json: { version: Chatwoot.config[:version], timestamp: Time.now.utc.to_formatted_s(:db) }
+ end
+end
diff --git a/app/dispatchers/async_dispatcher.rb b/app/dispatchers/async_dispatcher.rb
index 65569c1b0..72e44a1c2 100644
--- a/app/dispatchers/async_dispatcher.rb
+++ b/app/dispatchers/async_dispatcher.rb
@@ -9,7 +9,7 @@ class AsyncDispatcher < BaseDispatcher
end
def listeners
- listeners = [AgentBotListener.instance, EmailNotificationListener.instance, ReportingListener.instance, WebhookListener.instance]
+ listeners = [EmailNotificationListener.instance, ReportingListener.instance, WebhookListener.instance]
listeners << EventListener.instance
listeners << SubscriptionListener.instance if ENV['BILLING_ENABLED']
listeners
diff --git a/app/dispatchers/sync_dispatcher.rb b/app/dispatchers/sync_dispatcher.rb
index e3bad28a1..509a42727 100644
--- a/app/dispatchers/sync_dispatcher.rb
+++ b/app/dispatchers/sync_dispatcher.rb
@@ -5,6 +5,6 @@ class SyncDispatcher < BaseDispatcher
end
def listeners
- [ActionCableListener.instance]
+ [ActionCableListener.instance, AgentBotListener.instance]
end
end
diff --git a/config/app.yml b/config/app.yml
new file mode 100644
index 000000000..2fb8246aa
--- /dev/null
+++ b/config/app.yml
@@ -0,0 +1,14 @@
+shared: &shared
+ version: '1.4.0'
+
+development:
+ <<: *shared
+
+production:
+ <<: *shared
+
+staging:
+ <<: *shared
+
+test:
+ <<: *shared
\ No newline at end of file
diff --git a/config/application.rb b/config/application.rb
index e336393d7..c7421cb4b 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -30,5 +30,12 @@ module Chatwoot
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'ALLOWALL'
}
+
+ # Custom chatwoot configurations
+ config.x = config_for(:app).with_indifferent_access
+ end
+
+ def self.config
+ @config ||= Rails.configuration.x
end
end
diff --git a/config/routes.rb b/config/routes.rb
index 8a9f0e568..a86f8b83a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -17,6 +17,7 @@ Rails.application.routes.draw do
resource :widget, only: [:show]
+ get '/api', to: 'api#index'
namespace :api, defaults: { format: 'json' } do
namespace :v1 do
# ----------------------------------
diff --git a/spec/controllers/api_controller_spec.rb b/spec/controllers/api_controller_spec.rb
new file mode 100644
index 000000000..b2948e28a
--- /dev/null
+++ b/spec/controllers/api_controller_spec.rb
@@ -0,0 +1,11 @@
+require 'rails_helper'
+
+RSpec.describe 'API Base', type: :request do
+ describe 'request to api base url' do
+ it 'returns api version' do
+ get '/api/'
+ expect(response).to have_http_status(:success)
+ expect(response.body).to include(Chatwoot.config[:version])
+ end
+ end
+end
From c2167fcaafa4a57ca917d8cb76c1ae95e6f53992 Mon Sep 17 00:00:00 2001
From: Fernando Verdugo
Date: Thu, 16 Apr 2020 11:58:23 +0200
Subject: [PATCH 09/57] Feature: Add catalan (Catalonia) language (#672)
Co-authored-by: Pranav Raj S
---
app/javascript/dashboard/i18n/ca.js | 37 +++++
app/javascript/dashboard/i18n/index.js | 4 +-
.../dashboard/i18n/locale/ca/agentMgmt.json | 100 +++++++++++++
.../dashboard/i18n/locale/ca/billing.json | 19 +++
.../dashboard/i18n/locale/ca/cannedMgmt.json | 74 ++++++++++
.../dashboard/i18n/locale/ca/chatlist.json | 77 ++++++++++
.../dashboard/i18n/locale/ca/contact.json | 20 +++
.../i18n/locale/ca/conversation.json | 34 +++++
.../i18n/locale/ca/generalSettings.json | 27 ++++
.../dashboard/i18n/locale/ca/inboxMgmt.json | 138 ++++++++++++++++++
.../dashboard/i18n/locale/ca/index.js | 34 +++++
.../i18n/locale/ca/integrations.json | 54 +++++++
.../dashboard/i18n/locale/ca/login.json | 21 +++
.../dashboard/i18n/locale/ca/report.json | 19 +++
.../i18n/locale/ca/resetPassword.json | 15 ++
.../i18n/locale/ca/setNewPassword.json | 20 +++
.../dashboard/i18n/locale/ca/settings.json | 62 ++++++++
.../dashboard/i18n/locale/ca/signup.json | 32 ++++
.../dashboard/i18n/locale/ca/webhooks.json | 5 +
.../dashboard/settings/account/Index.vue | 3 +-
config/initializers/languages.rb | 3 +-
config/locales/ca.yml | 56 +++++++
22 files changed, 851 insertions(+), 3 deletions(-)
create mode 100644 app/javascript/dashboard/i18n/ca.js
create mode 100644 app/javascript/dashboard/i18n/locale/ca/agentMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/billing.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/cannedMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/chatlist.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/contact.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/conversation.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/generalSettings.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/index.js
create mode 100644 app/javascript/dashboard/i18n/locale/ca/integrations.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/login.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/report.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/resetPassword.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/setNewPassword.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/settings.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/signup.json
create mode 100644 app/javascript/dashboard/i18n/locale/ca/webhooks.json
create mode 100644 config/locales/ca.yml
diff --git a/app/javascript/dashboard/i18n/ca.js b/app/javascript/dashboard/i18n/ca.js
new file mode 100644
index 000000000..796cced41
--- /dev/null
+++ b/app/javascript/dashboard/i18n/ca.js
@@ -0,0 +1,37 @@
+import en from './locale/ca';
+
+export default {
+ ...en,
+ APP_GLOBAL: {
+ TRIAL_MESSAGE: 'dies de prova restants.',
+ TRAIL_BUTTON: 'Comprar ara',
+ },
+ COMPONENTS: {
+ CODE: {
+ BUTTON_TEXT: 'Copiar',
+ COPY_SUCCESSFUL: 'Codi copiat al porta-retalls correctament',
+ },
+ FILE_BUBBLE: {
+ DOWNLOAD: 'Descarrega',
+ UPLOADING: "S'està pujant...",
+ },
+ },
+ CONFIRM_EMAIL: "S'està verificant...",
+ SETTINGS: {
+ INBOXES: {
+ NEW_INBOX: "Afegeix una safata d'entrada",
+ },
+ },
+ SIDEBAR: {
+ CONVERSATIONS: 'Conversacions',
+ REPORTS: 'Informes',
+ SETTINGS: 'Configuració',
+ HOME: 'Inici',
+ AGENTS: 'Agents',
+ INBOXES: "Safates d'entrada",
+ CANNED_RESPONSES: 'Respostes Predeterminades',
+ BILLING: 'Facturació',
+ INTEGRATIONS: 'Integracions',
+ ACCOUNT_SETTINGS: 'Configuració del compte',
+ },
+};
diff --git a/app/javascript/dashboard/i18n/index.js b/app/javascript/dashboard/i18n/index.js
index 4be079020..f9169ab02 100644
--- a/app/javascript/dashboard/i18n/index.js
+++ b/app/javascript/dashboard/i18n/index.js
@@ -1,9 +1,11 @@
+import ca from './ca';
import en from './en';
import de from './de';
import ml from './ml';
export default {
+ ca,
de,
en,
- ml
+ ml,
};
diff --git a/app/javascript/dashboard/i18n/locale/ca/agentMgmt.json b/app/javascript/dashboard/i18n/locale/ca/agentMgmt.json
new file mode 100644
index 000000000..36a30dca3
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/agentMgmt.json
@@ -0,0 +1,100 @@
+{
+ "AGENT_MGMT": {
+ "HEADER": "Agents",
+ "HEADER_BTN_TXT": "Afegir Agent",
+ "LOADING": "S'està recollint la llista d'Agents",
+ "SIDEBAR_TXT": "
Agents
Un Agent és un membre del teu equip de suport al client.
Els agents podran veure i respondre als missatges dels vostres usuaris. La llista mostra tots els agents que hi ha actualment al vostre compte.
Clica en Afegir Agent per afegir un nou agent. L’agent que afegiu rebrà un correu electrònic amb un enllaç de confirmació per activar el seu compte, després del qual podran accedir a Chatwoot i respondre als missatges.
L’accés a les funcions de Chatwoot es basa en els següents rols.
Agent - els agents amb aquest rol només poden accedir a bústies de sortida, informes i converses.
Administrador/a - L’administrador/a tindrà accés a totes les funcions de Chatwoot habilitades per al vostre compte, incloses les configuracions i la facturació, juntament amb tots els privilegis dels agents normals.
",
+ "AGENT_TYPES": [
+ {
+ "name": "administrador/a",
+ "label": "Administrador/a"
+ }, {
+ "name": "agent",
+ "label": "Agent"
+ }
+ ],
+ "LIST": {
+ "404": "No hi ha agents associats a aquest compte",
+ "TITLE": "Gestiona agents en el teu equip",
+ "DESC": "Pots afegir/esborrar agents del teu equip.",
+ "NAME": "Nom",
+ "EMAIL": "Correu electrònic",
+ "STATUS": "Estat",
+ "ACTIONS": "Accions",
+ "VERIFIED": "Verificat",
+ "VERIFICATION_PENDING": "Verificació pendent"
+ },
+ "ADD": {
+ "TITLE": "Afegir agent al teu equip",
+ "DESC": "Podeu afegir persones que podran gestionar suport per a les vostres safates d'entrada.",
+ "FORM": {
+ "NAME" : {
+ "LABEL": "Nom de l'Agent",
+ "PLACEHOLDER": "Introduïu el nom de l'agent"
+ },
+ "AGENT_TYPE" : {
+ "LABEL": "Tipus d'Agent",
+ "PLACEHOLDER": "Selecciona un tipus",
+ "ERROR": "El tipus d'Agent és necessari"
+ },
+ "EMAIL" : {
+ "LABEL": "Adreça de correu electrònic",
+ "PLACEHOLDER": "Introduïu l'adreça de correu electrònic de l'agent"
+ },
+ "SUBMIT": "Afegir Agent"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Agent afegit correctament",
+ "EXIST_MESSAGE": "L'adreça de correu electrònic de l'agent ja està en ús. Introduïu una altre adreça",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "Esborrar",
+ "API": {
+ "SUCCESS_MESSAGE": "Agent esborrat correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "CONFIRM": {
+ "TITLE": "Confirma l'esborrat",
+ "MESSAGE": "N'estas segur? ",
+ "YES": "Si, esborra ",
+ "NO": "No, manten-la "
+ }
+ },
+ "EDIT": {
+ "TITLE": "Edita l'agent",
+ "FORM": {
+ "NAME" : {
+ "LABEL": "Nom de l'Agent",
+ "PLACEHOLDER": "Please enter a name of the agent"
+ },
+ "AGENT_TYPE" : {
+ "LABEL": "Agent Type",
+ "PLACEHOLDER": "Please select a type",
+ "ERROR": "Agent type is required"
+ },
+ "EMAIL" : {
+ "LABEL": "Email Address",
+ "PLACEHOLDER": "Please enter an email address of the agent"
+ },
+ "SUBMIT": "Edit Agent"
+ },
+ "BUTTON_TEXT": "Edit",
+ "CANCEL_BUTTON_TEXT": "Cancel",
+ "API": {
+ "SUCCESS_MESSAGE": "Agent updated successfully",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "PASSWORD_RESET": {
+ "ADMIN_RESET_BUTTON": "Reset Password",
+ "ADMIN_SUCCESS_MESSAGE": "An email with reset password instructions has been sent to the agent",
+ "SUCCESS_MESSAGE": "Agent password reset successfully",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ }
+ },
+ "SEARCH": {
+ "NO_RESULTS": "No s'han trobat agents."
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/billing.json b/app/javascript/dashboard/i18n/locale/ca/billing.json
new file mode 100644
index 000000000..c44ba0dbf
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/billing.json
@@ -0,0 +1,19 @@
+{
+ "BILLING": {
+ "HEADER": "Facturació",
+ "LOADING": "S'estan obtenin les suscripcions",
+ "ACCOUNT_STATE": "Estat del compte",
+ "AGENT_COUNT": "Compte d'agent",
+ "PER_AGENT_COST": "Per cost d'agent",
+ "TOTAL_COST": "Cost total",
+ "BUTTON": {
+ "ADD": "Afegir mètode de pagament",
+ "EDIT": "EDITAR Mètode de pagament"
+ },
+ "TRIAL": {
+ "TITLE": "S'ha acabat el període de prova",
+ "MESSAGE": "Afegiu un mètode de pagament per continuar utilitzant Chatwoot."
+ },
+ "ACCOUNT_LOCKED": "El seu compte no està disponible de moment. Poseu-vos en contacte amb l'administrador per reactivar-lo."
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/cannedMgmt.json b/app/javascript/dashboard/i18n/locale/ca/cannedMgmt.json
new file mode 100644
index 000000000..40bb31696
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/cannedMgmt.json
@@ -0,0 +1,74 @@
+{
+ "CANNED_MGMT": {
+ "HEADER": "Respostes predeterminades",
+ "HEADER_BTN_TXT": "Afegeix una resposta predeterminada",
+ "LOADING": "S'estan recollint les respostes predeterminades",
+ "SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta",
+ "SIDEBAR_TXT": "
Respostes predeterminades
Les respostes predeterminades són plantilles de resposta que es poden utilitzar per enviar ràpidament una resposta a una conversa .
Per crear una Resposta Predeterminada, clica en Afegir Resposta Predeterminada. També pots editar o suprimir una resposta predeterminada fent clic al botó Edita o Suprimeix
Les respostes predeterminades s'utilitzen amb l'ajuda dels Codi curt. Els agents poden accedir a les respostes predeterminades en un xat escrivint '/' seguit del codi curt.
",
+ "LIST": {
+ "404": "No hi ha respostes predeterminades disponibles en aquest compte.",
+ "TITLE": "Gestiona les respostes predeterminades",
+ "DESC": "Les respostes predeterminades són plantilles de resposta predefinides que es poden utilitzar per enviar ràpidament respostes a les converses.",
+ "TABLE_HEADER": [
+ "Codi curt",
+ "Contingut",
+ "Accions"
+ ]
+ },
+ "ADD": {
+ "TITLE": "Afegeix Resposta Predeterminada",
+ "DESC": "Les respostes predeterminades són plantilles de resposta que es poden utilitzar per enviar ràpidament les respostes a les converses.",
+ "FORM": {
+ "SHORT_CODE" : {
+ "LABEL": "Codi curt",
+ "PLACEHOLDER": "Introduïu un codi curt",
+ "ERROR": "És necessari el codi curt"
+ },
+ "CONTENT" : {
+ "LABEL": "Contingut",
+ "PLACEHOLDER": "Introduïu un contingut",
+ "ERROR": "És necessari un contingut"
+ },
+ "SUBMIT": "Envia"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Resposta predeterminada afegida correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ }
+ },
+ "EDIT": {
+ "TITLE": "Edita la resposta predeterminada",
+ "FORM": {
+ "SHORT_CODE" : {
+ "LABEL": "Codi curt",
+ "PLACEHOLDER": "Introduïu un codi curt",
+ "ERROR": "És necessari el codi curt"
+ },
+ "CONTENT" : {
+ "LABEL": "Content",
+ "PLACEHOLDER": "Introduïu un contingut",
+ "ERROR": "És necessari un contingut"
+ },
+ "SUBMIT": "Envia"
+ },
+ "BUTTON_TEXT": "Edita",
+ "API": {
+ "SUCCESS_MESSAGE": "Resposta predeterminada actualitzada correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "Esborra",
+ "API": {
+ "SUCCESS_MESSAGE": "Resposta predeterminada eliminada correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "CONFIRM": {
+ "TITLE": "Confirma esborrat",
+ "MESSAGE": "N'estas segur? ",
+ "YES": "Si, esborra ",
+ "NO": "No, manten-la "
+ }
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/chatlist.json b/app/javascript/dashboard/i18n/locale/ca/chatlist.json
new file mode 100644
index 000000000..803ef4c55
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/chatlist.json
@@ -0,0 +1,77 @@
+{
+ "CHAT_LIST": {
+ "LOADING": "S'estan obtenint converses",
+ "LOAD_MORE_CONVERSATIONS": "Carrega més converses",
+ "EOF": "Totes les converses carregades 🎉",
+ "LIST": {
+ "404": "No hi ha converses actives en aquest grup."
+ },
+ "TAB_HEADING": "Converses",
+ "SEARCH": {
+ "INPUT": "Cerca persones, xats, respostes desades .."
+ },
+ "STATUS_TABS": [{
+ "NAME": "Obrir",
+ "KEY": "openCount"
+ },
+ {
+ "NAME": "Resoltes",
+ "KEY": "allConvCount"
+ }
+ ],
+
+ "ASSIGNEE_TYPE_TABS": [{
+ "NAME": "Meves",
+ "KEY": "me",
+ "COUNT_KEY": "mineCount"
+ },
+ {
+ "NAME": "Sense assignar",
+ "KEY": "unassigned",
+ "COUNT_KEY": "unAssignedCount"
+ },
+ {
+ "NAME": "Totes",
+ "KEY": "all",
+ "COUNT_KEY": "allCount"
+ }
+ ],
+
+ "CHAT_STATUS_ITEMS": [{
+ "TEXT": "Obertes",
+ "VALUE": "open"
+ },
+ {
+ "TEXT": "Resoltes",
+ "VALUE": "resolved"
+ }
+ ],
+
+ "ATTACHMENTS": {
+ "image": {
+ "ICON": "ion-image",
+ "CONTENT": "Missatge d'imatge"
+ },
+ "audio": {
+ "ICON": "ion-volume-high",
+ "CONTENT": "Missatge d'audio"
+ },
+ "video": {
+ "ICON": "ion-ios-videocam",
+ "CONTENT": "Missatge de vídeo"
+ },
+ "file": {
+ "ICON": "ion-document",
+ "CONTENT": "Fitxer adjunt"
+ },
+ "location": {
+ "ICON": "ion-ios-location",
+ "CONTENT": "Ubicació"
+ },
+ "fallback": {
+ "ICON": "ion-link",
+ "CONTENT": "ha compartit una URL"
+ }
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/contact.json b/app/javascript/dashboard/i18n/locale/ca/contact.json
new file mode 100644
index 000000000..5b88ca198
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/contact.json
@@ -0,0 +1,20 @@
+{
+ "CONTACT_PANEL": {
+ "CONVERSATION_TITLE": "Detalls de les converses",
+ "BROWSER": "Navegador",
+ "OS": "Sistema operatiu",
+ "INITIATED_FROM": "Iniciada des de ",
+ "INITIATED_AT": "Iniciada a les",
+ "CONVERSATIONS": {
+ "NO_RECORDS_FOUND": "No hi han converses prècies associades a aquest contacte.",
+ "TITLE": "Converses prèvies"
+ },
+ "LABELS": {
+ "TITLE": "Etiquetes de converses",
+ "UPDATE_BUTTON": "Actualitza etiquetes",
+ "UPDATE_ERROR": "No s'han pogut actualitzar les etiquetes, torna-ho a provar.",
+ "TAG_PLACEHOLDER": "Afegeix una etiqueta nova",
+ "PLACEHOLDER": "Cerca o afegeix una etiqueta"
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/conversation.json b/app/javascript/dashboard/i18n/locale/ca/conversation.json
new file mode 100644
index 000000000..bc8f13511
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/conversation.json
@@ -0,0 +1,34 @@
+{
+ "CONVERSATION": {
+ "404": "Si us plau, selecciona una conversa al panell de l’esquerra",
+ "NO_MESSAGE_1": "Uh oh! Sembla que no hi ha missatges de clients a la safata d'entrada.",
+ "NO_MESSAGE_2": " per enviar un missatge a la vostra pàgina!",
+ "NO_INBOX_2": " per començar",
+ "NO_INBOX_AGENT": "Uh Oh! Sembla que no ets a cap safata d'entrada. Si us plau, poseu-vos en contacte amb l'administrador",
+ "CLICK_HERE": "Clica aquí",
+ "LOADING_INBOXES": "S'estàn carregant les safates d'entrada",
+ "LOADING_CONVERSATIONS": "S'estàn carregant les converses",
+ "DOWNLOAD": "Descarrega",
+ "HEADER": {
+ "RESOLVE_ACTION": "Resoldre",
+ "REOPEN_ACTION": "Tornar a obrir",
+ "OPEN": "Més",
+ "CLOSE": "Tanca",
+ "DETAILS": "detalls"
+ },
+ "FOOTER": {
+ "MSG_INPUT": "Maj + enter per a una línia nova. Comença amb '/' per seleccionar una resposta predeterminada.",
+ "PRIVATE_MSG_INPUT": "Shift + enter per una línia nova. Això serà visible només per als Agents"
+ },
+ "REPLYBOX": {
+ "REPLY": "Respon",
+ "PRIVATE_NOTE": "Nota privada",
+ "SEND": "Envia",
+ "CREATE": "Afegeix una nota",
+ "TWEET": "Tweet"
+ },
+ "VISIBLE_TO_AGENTS": "Nota privada: Només és visible per tu i el vostre equip",
+ "CHANGE_STATUS": "Estat de la conversa canviat",
+ "CHANGE_AGENT": "Assignació de la conversa canviat"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/generalSettings.json b/app/javascript/dashboard/i18n/locale/ca/generalSettings.json
new file mode 100644
index 000000000..520f28928
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/generalSettings.json
@@ -0,0 +1,27 @@
+{
+ "GENERAL_SETTINGS": {
+ "TITLE": "Configuració del compte",
+ "SUBMIT": "Actualització de la configuració",
+ "UPDATE": {
+ "ERROR": "No s'ha pogut actualitzar la configuració, torna-ho a provar!",
+ "SUCCESS": "La configuració del compte s'ha actualitzat correctament"
+ },
+ "FORM": {
+ "ERROR": "Corregiu els errors del formulari",
+ "GENERAL_SECTION": {
+ "TITLE": "Configuració general",
+ "NOTE": ""
+ },
+ "NAME": {
+ "LABEL": "Nom del compte",
+ "PLACEHOLDER": "El nom del vostre compte",
+ "ERROR": "Introduïu un nom de compte vàlid"
+ },
+ "LANGUAGE": {
+ "LABEL": "Idioma del lloc (Beta)",
+ "PLACEHOLDER": "El nom del vostre compte",
+ "ERROR": ""
+ }
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
new file mode 100644
index 000000000..5059cd491
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
@@ -0,0 +1,138 @@
+{
+ "INBOX_MGMT": {
+ "HEADER": "Safates d'entrada",
+ "SIDEBAR_TXT": "
Safata d'entrada
Quan connecteu un lloc web o una pàgina de facebook a Chatwoot, es diu Safata d'entrada. Teniu bústies d'entrada il·limitades al vostre compte de Chatwoot.
Feu click a Afegir safata d'entrada per connectar-vos a un lloc web o a una pàgina de Facebook.
Al Tauler de control, pots veure totes les converses de totes les teves safates d'entrada en un sol lloc i respondre-les a la pestanya `Converses`.
També pots veure converses específiques per a una safata d’entrada si feu clic al nom de la safata d'entrada, al panell esquerre de la taula.
",
+ "LIST": {
+ "404": "No hi ha cap safata d'entrada connectat a aquest compte."
+ },
+ "CREATE_FLOW": [
+ { "title": "Triar canal", "route": "settings_inbox_new", "body": "Trieu el proveïdor que vulgueu integrar amb Chatwoot." },
+ { "title": "Crear safata d'entrada", "route": "settings_inboxes_page_channel", "body": "Autentiqueu el vostre compte i creeu una safata d'entrada." },
+ { "title": "Afegir agents", "route": "settings_inboxes_add_agents", "body": "Afegir agents a la safata d'entrada creada." },
+ { "title": "Voila!", "route": "settings_inbox_finish", "body": "Ja estàs preparat!" }
+ ],
+ "ADD": {
+ "FB": {
+ "HELP": "PD: Al iniciar la sessió, només accediu als missatges de la vostra pàgina. Chatwoot mai no podrà accedir als vostres missatges privats."
+ },
+ "TWITTER": {
+ "HELP": "Per afegir el teu perfil de Twitter com a canal, has d'autentificar el vostre perfil de Twitter fent clic a 'Inicieu la sessió amb Twitter' "
+ },
+ "WEBSITE_CHANNEL": {
+ "TITLE": "Canal Web",
+ "DESC": "Crea un canal per al vostre lloc web i comença a donar suport als vostres clients mitjançant el teu widget del lloc web.",
+ "LOADING_MESSAGE": "S'està creant el canal de suport web",
+ "CHANNEL_NAME": {
+ "LABEL": "Nom del lloc web",
+ "PLACEHOLDER": "Introduïu el nom del vostre lloc web (per exemple, Acme Inc)"
+ },
+ "CHANNEL_DOMAIN": {
+ "LABEL": "Domini del lloc web",
+ "PLACEHOLDER": "Introduïu el vostre domini de lloc web (pe: acme.com)"
+ },
+ "WIDGET_COLOR": {
+ "LABEL": "Color del Widget",
+ "PLACEHOLDER": "Actualitza el color del widget"
+ },
+ "SUBMIT_BUTTON":"Crea la safata entrada"
+ },
+ "TWILIO": {
+ "TITLE": "Canal Twilio SMS",
+ "DESC": "Integra Twilio i comença a donar suport als teus clients mitjançant SMS.",
+ "ACCOUNT_SID": {
+ "LABEL": "Compte SID",
+ "PLACEHOLDER": "Introduïu el vostre compte Twilio SID",
+ "ERROR": "Aquest camp és obligatori"
+ },
+ "AUTH_TOKEN": {
+ "LABEL": "Auth Token",
+ "PLACEHOLDER": "Introduïu el vostre Twilio Auth Token",
+ "ERROR": "Aquest camp és obligatori"
+ },
+ "CHANNEL_NAME": {
+ "LABEL": "Nom del canal",
+ "PLACEHOLDER": "Introduïu el nom del canal",
+ "ERROR": "Aquest camp és obligatori"
+ },
+ "PHONE_NUMBER": {
+ "LABEL": "Número de telèfon",
+ "PLACEHOLDER": "Introduïu el número de telèfon des del qual serà enviat el missatge.",
+ "ERROR": "Introduïu un valor vàlid. El número de telèfon hauria de començar amb el signe `+`."
+ },
+ "SUBMIT_BUTTON": "Crear un canal Twilio",
+ "API": {
+ "ERROR_MESSAGE": "No hem pogut autenticar les credencials de Twilio, prova de nou"
+ }
+ },
+ "AUTH": {
+ "TITLE": "Canals",
+ "DESC": "Actualment estan suportats widgets de xat en directe per a llocs web, pàgines de Facebook i perfils de Twitter. Estem treballant en més plataformes com Whatsapp, correu electrònic, Telegram i Line, que estaran disponibles en breu"
+ },
+ "AGENTS": {
+ "TITLE": "Agents",
+ "DESC": "Aquí podeu afegir agents per gestionar la vostra safata d'entrada de nova creació. Només aquests agents seleccionats tindran accés a la vostra safata d'entrada. Els agents que no formen part d'aquesta safata d'entrada no podran veure ni respondre als missatges d'aquesta safata d'entrada quan s’inicien. PD: Com a administrador, si necessiteu accés a totes les bústies d’entrada, heu d’afegir-vos com a agent a totes les bústies de sortida que creeu."
+ },
+ "DETAILS": {
+ "TITLE": "Detalls de la safata d'entrada",
+ "DESC": "Des del següent menú desplegable, seleccioneu la pàgina de Facebook que voleu connectar a Chatwoot. També podeu donar un nom personalitzat a la safata d'entrada per a una millor identificació."
+ },
+ "FINISH":{
+ "TITLE": "L'has clavat!",
+ "DESC": "Heu acabat d'integrar la vostra pàgina de Facebook amb Chatwoot. La propera vegada que un client escrigui un missatge a la vostra pàgina, la conversa apareixerà automàticament a la safata d'entrada. També us proporcionem un script del widget que podeu afegir fàcilment al vostre web. Una vegada que estigui operatiu al vostre web, els clients us podran enviar missatges des del web sense l’ajuda de cap eina externa i la conversa apareixerà aquí mateix, a Chatwoot. Genial, eh? Bé, segur que intentem ser-ho :)"
+ }
+ },
+ "DETAILS": {
+ "LOADING_FB": "S'està autenticant amb Facebook...",
+ "ERROR_FB_AUTH": "Alguna cosa ha anat malament, actualitza la pàgina ...",
+ "CREATING_CHANNEL": "S'està creant la safata d'entrada...",
+ "TITLE": "Configura els detalls de la safata d'entrada",
+ "DESC": ""
+ },
+ "AGENTS": {
+ "BUTTON_TEXT": "Afegir agents",
+ "ADD_AGENTS": "S'estan afegint agents a la vostre safata d'entrada..."
+ },
+ "FINISH": {
+ "TITLE": "La vostra safata d'entrada està a punt!",
+ "MESSAGE": "Ja podeu interactuar amb els vostres clients a través del vostre canal nou. Feliç suport",
+ "BUTTON_TEXT": "Porta'm allà",
+ "WEBSITE_SUCCESS": "Heu finalitzat amb èxit la creació d'un canal web. Copieu el codi que es mostra a continuació i enganxeu-lo al lloc web. La propera vegada que un client utilitzi el xat en directe, la conversa apareixerà automàticament a la safata d'entrada."
+ },
+ "REAUTH": "Reautoritza",
+ "VIEW": "Veure",
+ "EDIT": {
+ "API": {
+ "SUCCESS_MESSAGE": "El color del widget s'ha actualitzat correctament",
+ "AUTO_ASSIGNMENT_SUCCESS_MESSAGE": "Assignació automàtica actualitzada correctament",
+ "ERROR_MESSAGE": "No s'ha pogut actualitzar el color del widget. Torneu-ho a provar més endavant."
+ },
+ "AUTO_ASSIGNMENT": {
+ "ENABLED": "Habilita",
+ "DISABLED": "Inhabilita"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "Suprimeix",
+ "CONFIRM": {
+ "TITLE": "Confirma esborrat",
+ "MESSAGE": "N'estas segur? ",
+ "YES": "Si, esborra ",
+ "NO": "No, manten-la "
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "S'ha suprimit la safata d'entrada correctament",
+ "ERROR_MESSAGE": "No s'ha pogut eliminar la safata d'entrada. Torneu-ho a provar més endavant."
+ }
+ },
+ "SETTINGS": "Configuracions",
+ "SETTINGS_POPUP": {
+ "MESSENGER_HEADING": "Script del missatger",
+ "MESSENGER_SUB_HEAD": "Col·loca aquest botó dins de l'etiqueta body",
+ "INBOX_AGENTS": "Agents",
+ "INBOX_AGENTS_SUB_TEXT": "Afegir o eliminar agents d'aquesta safata d'entrada",
+ "UPDATE": "Actualitza",
+ "AUTO_ASSIGNMENT": "Activa l'assignació automàtica",
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Activa o desactiva l'assignació automàtica d'agents disponibles a les noves converses"
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/index.js b/app/javascript/dashboard/i18n/locale/ca/index.js
new file mode 100644
index 000000000..351906dd9
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/index.js
@@ -0,0 +1,34 @@
+/* eslint-disable */
+import { default as _agentMgmt } from './agentMgmt.json';
+import { default as _billing } from './billing.json';
+import { default as _cannedMgmt } from './cannedMgmt.json';
+import { default as _chatlist } from './chatlist.json';
+import { default as _contact } from './contact.json';
+import { default as _conversation } from './conversation.json';
+import { default as _inboxMgmt } from './inboxMgmt.json';
+import { default as _login } from './login.json';
+import { default as _report } from './report.json';
+import { default as _resetPassword } from './resetPassword.json';
+import { default as _setNewPassword } from './setNewPassword.json';
+import { default as _settings } from './settings.json';
+import { default as _signup } from './signup.json';
+import { default as _integrations } from './integrations.json';
+import { default as _generalSettings } from './generalSettings.json';
+
+export default {
+ ..._agentMgmt,
+ ..._billing,
+ ..._cannedMgmt,
+ ..._chatlist,
+ ..._contact,
+ ..._conversation,
+ ..._inboxMgmt,
+ ..._login,
+ ..._report,
+ ..._resetPassword,
+ ..._setNewPassword,
+ ..._settings,
+ ..._signup,
+ ..._integrations,
+ ..._generalSettings,
+};
diff --git a/app/javascript/dashboard/i18n/locale/ca/integrations.json b/app/javascript/dashboard/i18n/locale/ca/integrations.json
new file mode 100644
index 000000000..8490ca178
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/integrations.json
@@ -0,0 +1,54 @@
+{
+ "INTEGRATION_SETTINGS": {
+ "HEADER": "Integracions",
+ "WEBHOOK": {
+ "TITLE": "Webhook",
+ "CONFIGURE": "Configura",
+ "HEADER": "Configuració Webhook",
+ "HEADER_BTN_TXT": "Afegeix un nou webhook",
+ "INTEGRATION_TXT": "Els esdeveniments de Webhook us proporcionen informació en temps real sobre el que passa al vostre compte de Chatwoot. Podeu utilitzar els webhooks per comunicar els esdeveniments a les vostres aplicacions preferides com Slack o Github. Feu clic a Configura per configurar els enllaços web.",
+ "LOADING": "S'estan recollint els webhooks adjunts",
+ "SEARCH_404": "No hi ha articles que coincideixin amb aquesta consulta",
+ "SIDEBAR_TXT": "
Webhooks
Els webhooks són callbacks HTTP que es poden definir per a cada compte. Es produeixen per esdeveniments com la creació de missatges a Chatwoot. Podeu crear més d'un webhook per a aquest compte.
Per crear un webhook, feu clic al botó Afegir nou webhook . També podeu eliminar qualsevol webhook existent fent clic al botó Elimina.
",
+ "LIST": {
+ "404": "No hi ha cap webhooks configurat per a aquest compte.",
+ "TITLE": "Gestiona els webhooks",
+ "DESC": "Els webhooks són plantilles de resposta predefinides que es poden utilitzar per enviar ràpidament respostes a una conversa.",
+ "TABLE_HEADER": [
+ "Webhook endpoint",
+ "Accions"
+ ]
+ },
+ "ADD": {
+ "CANCEL": "Cancel·la",
+ "TITLE": "Afegir un nou webhook",
+ "DESC": "Els esdeveniments de Webhook us proporcionen informació en temps real sobre el que passa al vostre compte de Chatwoot. Introduïu una URL vàlid per configurar un callback.",
+ "FORM": {
+ "END_POINT": {
+ "LABEL": "Webhook URL",
+ "PLACEHOLDER": "Exemple: https://example/api/webhook",
+ "ERROR": "Introduïu una URL vàlid"
+ },
+ "SUBMIT": "Crear webhook"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "S'ha afegit el Webhook correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ }
+ },
+ "DELETE": {
+ "BUTTON_TEXT": "Suprimeix",
+ "API": {
+ "SUCCESS_MESSAGE": "S'ha esborrat el Webhook correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "CONFIRM": {
+ "TITLE": "Confirma l'esborrat",
+ "MESSAGE": "N'estas segur? ",
+ "YES": "Si, esborra ",
+ "NO": "No, manten-la "
+ }
+ }
+ }
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/login.json b/app/javascript/dashboard/i18n/locale/ca/login.json
new file mode 100644
index 000000000..3c62ee837
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/login.json
@@ -0,0 +1,21 @@
+{
+ "LOGIN": {
+ "TITLE": "Entra a Chatwoot",
+ "EMAIL": {
+ "LABEL": "Correu electrònic",
+ "PLACEHOLDER": "Correu electrònic p.e.: someone@exemple.com"
+ },
+ "PASSWORD": {
+ "LABEL": "Contrasenya",
+ "PLACEHOLDER": "Contrasenya"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Iniciada la sessió amb èxit",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant",
+ "UNAUTH": "Nom d'usuari / contrasenya incorrecte. Torna-ho a provar-ho"
+ },
+ "FORGOT_PASSWORD": "Has oblidat la contrasenya?",
+ "CREATE_NEW_ACCOUNT": "Crear un nou compte",
+ "SUBMIT": "Inicia la sessió"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/report.json b/app/javascript/dashboard/i18n/locale/ca/report.json
new file mode 100644
index 000000000..8740c6abf
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/report.json
@@ -0,0 +1,19 @@
+{
+ "REPORT": {
+ "HEADER": "Informes",
+ "LOADING_CHART": "S'estan carregant dades del gràfic...",
+ "NO_ENOUGH_DATA": "No hem rebut suficients punts de dades per generar l'informe. Torneu-ho a provar més endavant.",
+ "METRICS": [
+ { "NAME": "Converses", "KEY": "conversations_count", "DESC": "( Total )" },
+ { "NAME": "Missatges d'entrada", "KEY": "incoming_messages_count", "DESC": "( Total )" },
+ { "NAME": "Missatges de sortida", "KEY": "outgoing_messages_count", "DESC": "( Total )" },
+ { "NAME": "Primer temps de resposta", "KEY": "avg_first_response_time", "DESC": "( Promig )" },
+ { "NAME": "Temps de resolució", "KEY": "avg_resolution_time", "DESC": "( Promig )" },
+ { "NAME": "Total de resolucions", "KEY": "resolutions_count", "DESC": "( Total )" }
+ ],
+ "DATE_RANGE": [
+ { "id": 0, "name": "Últims 7 dies" },
+ { "id": 1, "name": "Últims 30 dies" }
+ ]
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/resetPassword.json b/app/javascript/dashboard/i18n/locale/ca/resetPassword.json
new file mode 100644
index 000000000..d9f15ba8c
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/resetPassword.json
@@ -0,0 +1,15 @@
+{
+ "RESET_PASSWORD": {
+ "TITLE": "Reinicialitza la contrasenya",
+ "EMAIL": {
+ "LABEL": "Correu electrònic",
+ "PLACEHOLDER": "Introduïu el correu electrònic",
+ "ERROR": "Introduïu un correu electrònic vàlid"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "L’enllaç de reinicialització de la contrasenya s’ha enviat al vostre correu electrònic",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "SUBMIT": "Envia"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/setNewPassword.json b/app/javascript/dashboard/i18n/locale/ca/setNewPassword.json
new file mode 100644
index 000000000..7d1ce9ac8
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/setNewPassword.json
@@ -0,0 +1,20 @@
+{
+ "SET_NEW_PASSWORD": {
+ "TITLE": "Estableix la nova contrasenya",
+ "PASSWORD": {
+ "LABEL": "Contrasenya",
+ "PLACEHOLDER": "Contrasenya",
+ "ERROR": "Contrasenya és massa curta"
+ },
+ "CONFIRM_PASSWORD": {
+ "LABEL": "Confirma la contrasenya",
+ "PLACEHOLDER": "Confirma la contrasenya",
+ "ERROR": "La contrasenya no coindeix"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "S'ha canviat la contrasenya correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb Woot Server. Torneu-ho a provar més endavant"
+ },
+ "SUBMIT": "Envia"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/settings.json b/app/javascript/dashboard/i18n/locale/ca/settings.json
new file mode 100644
index 000000000..8878ad89c
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/settings.json
@@ -0,0 +1,62 @@
+{
+ "PROFILE_SETTINGS": {
+ "LINK": "Configuració del Perfil",
+ "TITLE": "Configuració del Perfil",
+ "BTN_TEXT": "Actualització del Perfil",
+ "AFTER_EMAIL_CHANGED": "El vostre perfil s'ha actualitzat correctament. Torneu a iniciar la sessió ja que les vostres credencials d'inici de sessió han canviat.",
+ "FORM": {
+ "AVATAR": "Imatge del Perfil",
+ "ERROR": "Corregiu els errors del formulari",
+ "REMOVE_IMAGE": "Suprimeix",
+ "UPLOAD_IMAGE": "Puja imatge",
+ "UPDATE_IMAGE": "Puja imatge",
+ "PROFILE_SECTION" : {
+ "TITLE": "Perfil",
+ "NOTE": "La vostra adreça de correu electrònic és la vostra identitat i s'utilitza per iniciar la sessió."
+ },
+ "PASSWORD_SECTION" : {
+ "TITLE": "Contrasenya",
+ "NOTE": "L'actualització de la contrasenya restableix els vostres inicis de sessió en múltiples dispositius."
+ },
+ "ACCESS_TOKEN": {
+ "TITLE": "Token d'accés",
+ "NOTE": "Aquest token es pot utilitzar si creeu una integració basada en l'API"
+ },
+ "EMAIL_NOTIFICATIONS_SECTION" : {
+ "TITLE": "Notificacions per correu electrònic",
+ "NOTE": "Actualitza aqui les preferències de les notificacions per correu electrònic",
+ "CONVERSATION_ASSIGNMENT": "Envieu notificacions per correu electrònic quan se m’assigni una conversa",
+ "CONVERSATION_CREATION": "Envieu notificacions per correu electrònic quan es crea una nova conversa",
+ "UPDATE_SUCCESS": "Les preferències de notificació per correu electrònic s’han actualitzat correctament",
+ "UPDATE_ERROR": "S'ha produït un error en actualitzar les preferències. Torneu-ho a provar"
+ },
+ "PROFILE_IMAGE":{
+ "LABEL": "Imatge del Perfil"
+ },
+ "NAME": {
+ "LABEL": "El teu nom",
+ "ERROR": "Introduïu un nom vàlid",
+ "PLACEHOLDER": "Introdueix el teu nom, serà mostrat a les converses"
+ },
+ "EMAIL": {
+ "LABEL": "La teva adreça de correu electrònic",
+ "ERROR": "Introduïu una adreça de correu electrònic vàlida",
+ "PLACEHOLDER": "Introduïu la vostra adreça de correu electrònic, que es mostrarà a les converses"
+ },
+ "PASSWORD": {
+ "LABEL": "Contrasenya",
+ "ERROR": "Introduïu una contrasenya d'una longitud de 6 o més",
+ "PLACEHOLDER": "Introduïu una nova contrasenya"
+ },
+ "PASSWORD_CONFIRMATION": {
+ "LABEL": "Confirmació de la nova contrasenya",
+ "ERROR": "Confirmeu que les contrasenyes coincideixin",
+ "PLACEHOLDER": "Torneu a introduir la vostra contrasenya"
+ }
+ }
+ },
+ "SIDEBAR_ITEMS": {
+ "PROFILE_SETTINGS": "Configuració del Perfil",
+ "LOGOUT": "Sortir"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/signup.json b/app/javascript/dashboard/i18n/locale/ca/signup.json
new file mode 100644
index 000000000..aa459d999
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/signup.json
@@ -0,0 +1,32 @@
+{
+ "REGISTER": {
+ "TRY_WOOT": "Registra un compte",
+ "TITLE": "Registre",
+ "TERMS_ACCEPT": "En registrar-vos, esteu d’acord amb el nostre T & C i Polítiques de Privadesa",
+ "ACCOUNT_NAME": {
+ "LABEL": "Nom del compte",
+ "PLACEHOLDER": "Wayne Enterprises",
+ "ERROR": "El nom del compte és massa curt"
+ },
+ "EMAIL": {
+ "LABEL": "Correu electrònic",
+ "PLACEHOLDER": "bruce@wayne.enterprises",
+ "ERROR": "El correu electrònic no és correcte"
+ },
+ "PASSWORD": {
+ "LABEL": "Contrasenya",
+ "PLACEHOLDER": "Contrasenya",
+ "ERROR": "La contrasenya és massa curta"
+ },
+ "CONFIRM_PASSWORD": {
+ "LABEL": "Confirma la contrasenya",
+ "PLACEHOLDER": "Confirma la contrasenya",
+ "ERROR": "Les contrasenyes no coincideixen"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "Registrat correctament",
+ "ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
+ },
+ "SUBMIT": "Envia"
+ }
+}
diff --git a/app/javascript/dashboard/i18n/locale/ca/webhooks.json b/app/javascript/dashboard/i18n/locale/ca/webhooks.json
new file mode 100644
index 000000000..a3ebed6c3
--- /dev/null
+++ b/app/javascript/dashboard/i18n/locale/ca/webhooks.json
@@ -0,0 +1,5 @@
+{
+ "WEBHOOKS_SETTINGS": {
+ "HEADER": "Paràmetres Webhook"
+ }
+}
diff --git a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
index f4a983294..819d821de 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue
@@ -24,8 +24,9 @@