diff --git a/.env.example b/.env.example
index 4fe8ec3c8..7c5299bad 100644
--- a/.env.example
+++ b/.env.example
@@ -18,7 +18,7 @@ FORCE_SSL=false
# true : default option, allows sign ups
# false : disables all the end points related to sign ups
# api_only: disables the UI for signup, but you can create sign ups via the account apis
-ENABLE_ACCOUNT_SIGNUP=true
+ENABLE_ACCOUNT_SIGNUP=false
# Redis config
REDIS_URL=redis://redis:6379
@@ -110,6 +110,12 @@ SLACK_CLIENT_SECRET=
## Mobile app env variables
IOS_APP_ID=6C953F3RX2.com.chatwoot.app
+
+### Smart App Banner
+# https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
+# You can find your app-id in https://itunesconnect.apple.com
+#IOS_APP_IDENTIFIER=1495796682
+
## Push Notification
## generate a new key value here : https://d3v.one/vapid-key-generator/
# VAPID_PUBLIC_KEY=
diff --git a/.gitignore b/.gitignore
index 0c71b2055..e4b14d2f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,3 +60,6 @@ package-lock.json
# cypress
test/cypress/videos/*
+
+/config/master.key
+/config/*.enc
\ No newline at end of file
diff --git a/.rubocop.yml b/.rubocop.yml
index 9cd50a44f..01951faea 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -11,6 +11,8 @@ Metrics/ClassLength:
Max: 125
Exclude:
- 'app/models/conversation.rb'
+ - 'app/mailers/conversation_reply_mailer.rb'
+ - 'app/models/message.rb'
RSpec/ExampleLength:
Max: 25
Style/Documentation:
@@ -48,6 +50,7 @@ Rails/ApplicationController:
- 'app/controllers/dashboard_controller.rb'
- 'app/controllers/widget_tests_controller.rb'
- 'app/controllers/widgets_controller.rb'
+ - 'app/controllers/platform_controller.rb'
Style/ClassAndModuleChildren:
EnforcedStyle: compact
Exclude:
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 2d3abda7f..4d66828c3 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -6,13 +6,6 @@
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 1
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: native, lf, crlf
-Layout/EndOfLine:
- Exclude:
- - 'deploy/after_restart.rb'
-
# Offense count: 1
Lint/DuplicateMethods:
Exclude:
diff --git a/Gemfile b/Gemfile
index 88f2fc75c..7e7e6ea97 100644
--- a/Gemfile
+++ b/Gemfile
@@ -29,6 +29,8 @@ gem 'flag_shih_tzu'
gem 'haikunator'
# Template parsing safetly
gem 'liquid'
+# Parse Markdown to HTML
+gem 'redcarpet'
##-- for active storage --##
gem 'aws-sdk-s3', require: false
@@ -85,6 +87,8 @@ gem 'sentry-raven'
##-- background job processing --##
gem 'sidekiq'
+# We want cron jobs
+gem 'sidekiq-cron'
##-- Push notification service --##
gem 'fcm'
@@ -96,6 +100,9 @@ gem 'geocoder'
# to parse maxmind db
gem 'maxminddb'
+# to create db triggers
+gem 'hairtrigger'
+
group :development do
gem 'annotate'
gem 'bullet'
diff --git a/Gemfile.lock b/Gemfile.lock
index d6692e402..d9da65980 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -115,13 +115,14 @@ GEM
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
- azure-storage-blob (2.0.0)
+ azure-storage-blob (2.0.1)
azure-storage-common (~> 2.0)
- nokogiri (~> 1.10.4)
- azure-storage-common (2.0.1)
+ nokogiri (~> 1.11.0.rc2)
+ azure-storage-common (2.0.2)
faraday (~> 1.0)
faraday_middleware (~> 1.0.0.rc1)
- nokogiri (~> 1.10.4)
+ net-http-persistent (~> 4.0)
+ nokogiri (~> 1.11.0.rc2)
barnes (0.0.8)
multi_json (~> 1)
statsd-ruby (~> 1.1)
@@ -181,6 +182,8 @@ GEM
railties (>= 3.2)
equalizer (0.0.11)
erubi (1.9.0)
+ et-orbi (1.2.4)
+ tzinfo
execjs (2.7.0)
facebook-messenger (1.5.0)
httparty (~> 0.13, >= 0.13.7)
@@ -198,9 +201,12 @@ GEM
faraday (~> 1.0)
fcm (1.0.2)
faraday (~> 1.0.0)
- ffi (1.13.1)
+ ffi (1.14.2)
flag_shih_tzu (0.3.23)
foreman (0.87.2)
+ fugit (1.4.1)
+ et-orbi (~> 1.1, >= 1.1.8)
+ raabro (~> 1.4)
geocoder (1.6.3)
gli (2.19.2)
globalid (0.4.2)
@@ -236,6 +242,10 @@ GEM
groupdate (5.1.0)
activesupport (>= 5)
haikunator (1.1.0)
+ hairtrigger (0.2.23)
+ activerecord (>= 5.0, < 7)
+ ruby2ruby (~> 2.4)
+ ruby_parser (~> 3.10)
hana (1.3.6)
hashdiff (1.0.1)
hashie (4.1.0)
@@ -281,7 +291,7 @@ GEM
letter_opener (1.7.0)
launchy (~> 2.2)
liquid (4.0.3)
- listen (3.2.1)
+ listen (3.3.3)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.7.0)
@@ -300,7 +310,7 @@ GEM
mimemagic (0.3.5)
mini_magick (4.10.1)
mini_mime (1.0.2)
- mini_portile2 (2.4.0)
+ mini_portile2 (2.5.0)
minitest (5.14.2)
momentjs-rails (2.20.1)
railties (>= 3.1)
@@ -308,10 +318,13 @@ GEM
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
+ net-http-persistent (4.0.0)
+ connection_pool (~> 2.2)
netrc (0.11.0)
nio4r (2.5.4)
- nokogiri (1.10.10)
- mini_portile2 (~> 2.4.0)
+ nokogiri (1.11.0)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
oauth (0.5.4)
orm_adapter (0.5.0)
os (1.1.1)
@@ -329,6 +342,8 @@ GEM
nio4r (~> 2.0)
pundit (2.1.0)
activesupport (>= 3.0.0)
+ raabro (1.4.0)
+ racc (1.5.2)
rack (2.2.3)
rack-cache (1.12.0)
rack (>= 0.4)
@@ -369,6 +384,7 @@ GEM
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
+ redcarpet (3.5.1)
redis (4.2.1)
redis-namespace (1.8.0)
redis (>= 3.0.4)
@@ -422,13 +438,19 @@ GEM
parser (>= 2.7.1.4)
rubocop-performance (1.7.1)
rubocop (>= 0.82.0)
- rubocop-rails (2.7.1)
+ rubocop-rails (2.8.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.87.0)
rubocop-rspec (1.43.2)
rubocop (~> 0.87)
ruby-progressbar (1.10.1)
+ ruby2ruby (2.4.4)
+ ruby_parser (~> 3.1)
+ sexp_processor (~> 4.6)
+ ruby_parser (3.15.0)
+ rubocop (>= 0.87.0)
+ sexp_processor (~> 4.9)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -454,12 +476,16 @@ GEM
semantic_range (2.3.0)
sentry-raven (3.0.3)
faraday (>= 1.0)
+ sexp_processor (4.15.1)
shoulda-matchers (4.4.1)
activesupport (>= 4.2.0)
sidekiq (6.1.1)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
+ sidekiq-cron (1.2.0)
+ fugit (~> 1.1)
+ sidekiq (>= 4.2.1)
signet (0.14.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
@@ -506,7 +532,7 @@ GEM
nokogiri (>= 1.6, < 2.0)
twitty (0.1.1)
oauth
- tzinfo (1.2.7)
+ tzinfo (1.2.8)
thread_safe (~> 0.1)
tzinfo-data (1.2020.1)
tzinfo (>= 1.0.0)
@@ -549,7 +575,7 @@ GEM
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
wisper (2.0.0)
- zeitwerk (2.4.0)
+ zeitwerk (2.4.1)
PLATFORMS
ruby
@@ -584,6 +610,7 @@ DEPENDENCIES
google-cloud-storage
groupdate
haikunator
+ hairtrigger
hashie
jbuilder
json_refs!
@@ -602,6 +629,7 @@ DEPENDENCIES
pundit
rack-cors
rails
+ redcarpet
redis
redis-namespace
redis-rack-cache
@@ -618,6 +646,7 @@ DEPENDENCIES
sentry-raven
shoulda-matchers
sidekiq
+ sidekiq-cron
simplecov (= 0.17.1)
slack-ruby-client
spring
diff --git a/LICENSE b/LICENSE
index a33852dca..037ad7885 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2017-2020 ThoughtWoot Inc.
+Copyright (c) 2017-2021 Chatwoot Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index a27754a70..bf868799f 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ Detailed documentation is available at [www.chatwoot.com/help-center](https://ww
### Translation process
-The translation process for Chatwoot web and mobile app is managed at [https://translate.chatwoot.com](https://translate.chatwoot.com) using Crowdin. Please read the [translation guide](https://www.chatwoot/docs/contributing/translating-chatwoot-to-your-language) for contributing to Chatwoot.
+The translation process for Chatwoot web and mobile app is managed at [https://translate.chatwoot.com](https://translate.chatwoot.com) using Crowdin. Please read the [translation guide](https://www.chatwoot.com/docs/contributing/translating-chatwoot-to-your-language) for contributing to Chatwoot.
---
@@ -98,4 +98,4 @@ Thanks goes to all these [wonderful people](https://www.chatwoot.com/docs/contri
-*Chatwoot* © 2017-2020, ThoughtWoot Inc - Released under the MIT License.
+*Chatwoot* © 2017-2021, Chatwoot Inc - Released under the MIT License.
diff --git a/app.json b/app.json
index b321e9b89..af1a496a4 100644
--- a/app.json
+++ b/app.json
@@ -11,7 +11,10 @@
"rails",
"vue"
],
- "success_url": "/app/login",
+ "success_url": "/",
+ "scripts": {
+ "postdeploy": "bundle exec rake db:seed"
+ },
"env": {
"SECRET_TOKEN": {
"description": "A secret key for verifying the integrity of signed cookies.",
diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb
index 3d81a8e68..f7f94fada 100644
--- a/app/builders/account_builder.rb
+++ b/app/builders/account_builder.rb
@@ -2,7 +2,7 @@
class AccountBuilder
include CustomExceptions::Account
- pattr_initialize [:account_name!, :email!, :confirmed!, :user]
+ pattr_initialize [:account_name!, :email!, :confirmed!, :user, :user_full_name, :user_password]
def perform
if @user.nil?
@@ -15,7 +15,6 @@ class AccountBuilder
end
[@user, @account]
rescue StandardError => e
- @account&.destroy
puts e.inspect
raise e
end
@@ -27,7 +26,7 @@ class AccountBuilder
if address.valid? # && !address.disposable?
true
else
- raise InvalidEmail.new(valid: address.valid?) # , disposable: address.disposable?})
+ raise InvalidEmail.new(valid: address.valid?)
end
end
@@ -61,18 +60,13 @@ class AccountBuilder
)
end
- def email_to_name(email)
- name = email[/[^@]+/]
- name.split('.').map(&:capitalize).join(' ')
- end
-
def create_user
- password = SecureRandom.alphanumeric(12)
+ password = user_password || SecureRandom.alphanumeric(12)
@user = User.new(email: @email,
password: password,
password_confirmation: password,
- name: email_to_name(@email))
+ name: @user_full_name)
@user.confirm if @confirmed
@user.save!
end
diff --git a/app/builders/contact_builder.rb b/app/builders/contact_builder.rb
index 3e362c9b5..dc15a299a 100644
--- a/app/builders/contact_builder.rb
+++ b/app/builders/contact_builder.rb
@@ -5,7 +5,7 @@ class ContactBuilder
contact_inbox = inbox.contact_inboxes.find_by(source_id: source_id)
return contact_inbox if contact_inbox
- build_contact
+ build_contact_inbox
end
private
@@ -26,16 +26,29 @@ class ContactBuilder
::ContactAvatarJob.perform_later(contact, contact_attributes[:avatar_url]) if contact_attributes[:avatar_url]
end
- def build_contact
- ActiveRecord::Base.transaction do
- contact = account.contacts.create!(
- name: contact_attributes[:name],
- phone_number: contact_attributes[:phone_number],
- email: contact_attributes[:email],
- identifier: contact_attributes[:identifier],
- additional_attributes: contact_attributes[:additional_attributes]
- )
+ def create_contact
+ account.contacts.create!(
+ name: contact_attributes[:name],
+ phone_number: contact_attributes[:phone_number],
+ email: contact_attributes[:email],
+ identifier: contact_attributes[:identifier],
+ additional_attributes: contact_attributes[:additional_attributes]
+ )
+ end
+ def find_contact
+ contact = nil
+
+ contact = account.contacts.find_by(identifier: contact_attributes[:identifier]) if contact_attributes[:identifier].present?
+
+ contact ||= account.contacts.find_by(email: contact_attributes[:email]) if contact_attributes[:email].present?
+
+ contact
+ end
+
+ def build_contact_inbox
+ ActiveRecord::Base.transaction do
+ contact = find_contact || create_contact
contact_inbox = create_contact_inbox(contact)
update_contact_avatar(contact)
contact_inbox
diff --git a/app/controllers/api/v1/accounts/contacts/labels_controller.rb b/app/controllers/api/v1/accounts/contacts/labels_controller.rb
new file mode 100644
index 000000000..440c378f7
--- /dev/null
+++ b/app/controllers/api/v1/accounts/contacts/labels_controller.rb
@@ -0,0 +1,13 @@
+class Api::V1::Accounts::Contacts::LabelsController < Api::V1::Accounts::BaseController
+ include LabelConcern
+
+ private
+
+ def model
+ @model ||= Current.account.contacts.find(permitted_params[:contact_id])
+ end
+
+ def permitted_params
+ params.permit(:contact_id, labels: [])
+ end
+end
diff --git a/app/controllers/api/v1/accounts/conversations/labels_controller.rb b/app/controllers/api/v1/accounts/conversations/labels_controller.rb
index 306544200..56b8029e3 100644
--- a/app/controllers/api/v1/accounts/conversations/labels_controller.rb
+++ b/app/controllers/api/v1/accounts/conversations/labels_controller.rb
@@ -1,11 +1,13 @@
class Api::V1::Accounts::Conversations::LabelsController < Api::V1::Accounts::Conversations::BaseController
- def create
- @conversation.update_labels(params[:labels])
- @labels = @conversation.label_list
+ include LabelConcern
+
+ private
+
+ def model
+ @model ||= @conversation
end
- # all labels of the current conversation
- def index
- @labels = @conversation.label_list
+ def permitted_params
+ params.permit(:conversation_id, labels: [])
end
end
diff --git a/app/controllers/api/v1/accounts/conversations/messages_controller.rb b/app/controllers/api/v1/accounts/conversations/messages_controller.rb
index 54cf7c595..8cfea20ba 100644
--- a/app/controllers/api/v1/accounts/conversations/messages_controller.rb
+++ b/app/controllers/api/v1/accounts/conversations/messages_controller.rb
@@ -11,9 +11,24 @@ class Api::V1::Accounts::Conversations::MessagesController < Api::V1::Accounts::
render_could_not_create_error(e.message)
end
+ def destroy
+ ActiveRecord::Base.transaction do
+ message.update!(content: I18n.t('conversations.messages.deleted'), deleted: true)
+ message.attachments.destroy_all
+ end
+ end
+
private
+ def message
+ @message ||= @conversation.messages.find(permitted_params[:id])
+ end
+
def message_finder
@message_finder ||= MessageFinder.new(@conversation, params)
end
+
+ def permitted_params
+ params.permit(:id)
+ end
end
diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb
index 7642e94e3..5dddf8036 100644
--- a/app/controllers/api/v1/accounts/conversations_controller.rb
+++ b/app/controllers/api/v1/accounts/conversations_controller.rb
@@ -86,7 +86,8 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
account_id: Current.account.id,
inbox_id: @contact_inbox.inbox_id,
contact_id: @contact_inbox.contact_id,
- contact_inbox_id: @contact_inbox.id
+ contact_inbox_id: @contact_inbox.id,
+ additional_attributes: params[:additional_attributes]
}
end
diff --git a/app/controllers/api/v1/accounts/notifications_controller.rb b/app/controllers/api/v1/accounts/notifications_controller.rb
index 8ae1629ca..49191caad 100644
--- a/app/controllers/api/v1/accounts/notifications_controller.rb
+++ b/app/controllers/api/v1/accounts/notifications_controller.rb
@@ -3,10 +3,12 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
before_action :fetch_notification, only: [:update]
before_action :set_primary_actor, only: [:read_all]
+ before_action :set_current_page, only: [:index]
def index
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
- @notifications = current_user.notifications.where(account_id: current_account.id).page params[:page]
+ @count = notifications.count
+ @notifications = notifications.page @current_page
end
def read_all
@@ -25,6 +27,11 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
render json: @notification
end
+ def unread_count
+ @unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
+ render json: @unread_count
+ end
+
private
def set_primary_actor
@@ -37,4 +44,12 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
def fetch_notification
@notification = current_user.notifications.find(params[:id])
end
+
+ def set_current_page
+ @current_page = params[:page] || 1
+ end
+
+ def notifications
+ @notifications ||= current_user.notifications.where(account_id: current_account.id)
+ end
end
diff --git a/app/controllers/api/v1/accounts/team_members_controller.rb b/app/controllers/api/v1/accounts/team_members_controller.rb
new file mode 100644
index 000000000..32a792509
--- /dev/null
+++ b/app/controllers/api/v1/accounts/team_members_controller.rb
@@ -0,0 +1,24 @@
+class Api::V1::Accounts::TeamMembersController < Api::V1::Accounts::BaseController
+ before_action :fetch_team
+ before_action :check_authorization
+
+ def index
+ @team_members = @team.team_members.map(&:user)
+ end
+
+ def create
+ record = @team.team_members.find_or_create_by(user_id: params[:user_id])
+ @team_member = record.user
+ end
+
+ def destroy
+ @team.team_members.find_by(user_id: params[:user_id])&.destroy
+ head :ok
+ end
+
+ private
+
+ def fetch_team
+ @team = Current.account.teams.find(params[:team_id])
+ end
+end
diff --git a/app/controllers/api/v1/accounts/teams_controller.rb b/app/controllers/api/v1/accounts/teams_controller.rb
new file mode 100644
index 000000000..adfeed62e
--- /dev/null
+++ b/app/controllers/api/v1/accounts/teams_controller.rb
@@ -0,0 +1,34 @@
+class Api::V1::Accounts::TeamsController < Api::V1::Accounts::BaseController
+ before_action :fetch_team, only: [:show, :update, :destroy]
+ before_action :check_authorization
+
+ def index
+ @teams = Current.account.teams
+ end
+
+ def show; end
+
+ def create
+ @team = Current.account.teams.new(team_params)
+ @team.save!
+ end
+
+ def update
+ @team.update!(team_params)
+ end
+
+ def destroy
+ @team.destroy
+ head :ok
+ end
+
+ private
+
+ def fetch_team
+ @team = Current.account.teams.find(params[:id])
+ end
+
+ def team_params
+ params.require(:team).permit(:name, :description, :allow_auto_assign)
+ end
+end
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index 51dcb1a57..8fbb56c19 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -16,6 +16,7 @@ class Api::V1::AccountsController < Api::BaseController
def create
@user, @account = AccountBuilder.new(
account_name: account_params[:account_name],
+ user_full_name: account_params[:user_full_name],
email: account_params[:email],
confirmed: confirmed?,
user: current_user
@@ -29,6 +30,7 @@ class Api::V1::AccountsController < Api::BaseController
end
def show
+ @latest_chatwoot_version = ::Redis::Alfred.get(::Redis::Alfred::LATEST_CHATWOOT_VERSION)
render 'api/v1/accounts/show.json'
end
@@ -54,7 +56,7 @@ class Api::V1::AccountsController < Api::BaseController
end
def account_params
- params.permit(:account_name, :email, :name, :locale, :domain, :support_email, :auto_resolve_duration)
+ params.permit(:account_name, :email, :name, :locale, :domain, :support_email, :auto_resolve_duration, :user_full_name)
end
def check_signup_enabled
diff --git a/app/controllers/api/v1/profiles_controller.rb b/app/controllers/api/v1/profiles_controller.rb
index bda3e8c90..c59edfce0 100644
--- a/app/controllers/api/v1/profiles_controller.rb
+++ b/app/controllers/api/v1/profiles_controller.rb
@@ -23,7 +23,8 @@ class Api::V1::ProfilesController < Api::BaseController
:password,
:password_confirmation,
:avatar,
- :availability
+ :availability,
+ ui_settings: {}
)
end
end
diff --git a/app/controllers/api/v1/widget/base_controller.rb b/app/controllers/api/v1/widget/base_controller.rb
index 0227bd0ba..1d377d69d 100644
--- a/app/controllers/api/v1/widget/base_controller.rb
+++ b/app/controllers/api/v1/widget/base_controller.rb
@@ -7,7 +7,12 @@ class Api::V1::Widget::BaseController < ApplicationController
private
def conversations
- @conversations = @contact_inbox.conversations.where(inbox_id: auth_token_params[:inbox_id])
+ if @contact_inbox.hmac_verified?
+ verified_contact_inbox_ids = @contact.contact_inboxes.where(inbox_id: auth_token_params[:inbox_id], hmac_verified: true).map(&:id)
+ @conversations = @contact.conversations.where(contact_inbox_id: verified_contact_inbox_ids)
+ else
+ @conversations = @contact_inbox.conversations.where(inbox_id: auth_token_params[:inbox_id])
+ end
end
def conversation
diff --git a/app/controllers/api/v1/widget/contacts_controller.rb b/app/controllers/api/v1/widget/contacts_controller.rb
index b58d26373..1fca2ee81 100644
--- a/app/controllers/api/v1/widget/contacts_controller.rb
+++ b/app/controllers/api/v1/widget/contacts_controller.rb
@@ -1,5 +1,6 @@
class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
def update
+ process_hmac
contact_identify_action = ContactIdentifyAction.new(
contact: @contact,
params: permitted_params.to_h.deep_symbolize_keys
@@ -9,7 +10,22 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
private
+ def process_hmac
+ return if params[:identifier_hash].blank?
+ raise StandardError, 'HMAC failed: Invalid Identifer Hash Provided' unless valid_hmac?
+
+ @contact_inbox.update(hmac_verified: true)
+ end
+
+ def valid_hmac?
+ params[:identifier_hash] == OpenSSL::HMAC.hexdigest(
+ 'sha256',
+ @web_widget.hmac_token,
+ params[:identifier].to_s
+ )
+ end
+
def permitted_params
- params.permit(:website_token, :identifier, :email, :name, :avatar_url, custom_attributes: {})
+ params.permit(:website_token, :identifier, :identifier_hash, :email, :name, :avatar_url, custom_attributes: {})
end
end
diff --git a/app/controllers/api/v1/widget/messages_controller.rb b/app/controllers/api/v1/widget/messages_controller.rb
index a4f33b563..c98138366 100644
--- a/app/controllers/api/v1/widget/messages_controller.rb
+++ b/app/controllers/api/v1/widget/messages_controller.rb
@@ -54,6 +54,8 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
end
def conversation_params
+ # FIXME: typo referrer in additional attributes
+ # will probably require a migration.
{
account_id: inbox.account_id,
inbox_id: inbox.id,
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 8fbc8ff45..4fe48998d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -23,7 +23,7 @@ class ApplicationController < ActionController::Base
render_unauthorized('You are not authorized to do this action')
ensure
# to address the thread variable leak issues in Puma/Thin webserver
- Current.user = nil
+ Current.reset
end
def set_current_user
diff --git a/app/controllers/concerns/label_concern.rb b/app/controllers/concerns/label_concern.rb
new file mode 100644
index 000000000..194f063be
--- /dev/null
+++ b/app/controllers/concerns/label_concern.rb
@@ -0,0 +1,10 @@
+module LabelConcern
+ def create
+ model.update_labels(permitted_params[:labels])
+ @labels = model.label_list
+ end
+
+ def index
+ @labels = model.label_list
+ end
+end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 52f392add..9ed9f7f47 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,5 +1,10 @@
class DashboardController < ActionController::Base
+ include SwitchLocale
+
before_action :set_global_config
+ around_action :switch_locale
+ before_action :ensure_installation_onboarding, only: [:index]
+
layout 'vueapp'
def index; end
@@ -20,4 +25,8 @@ class DashboardController < ActionController::Base
APP_VERSION: Chatwoot.config[:version]
)
end
+
+ def ensure_installation_onboarding
+ redirect_to '/installation/onboarding' if ::Redis::Alfred.get(::Redis::Alfred::CHATWOOT_INSTALLATION_ONBOARDING)
+ end
end
diff --git a/app/controllers/installation/onboarding_controller.rb b/app/controllers/installation/onboarding_controller.rb
new file mode 100644
index 000000000..a6f04238b
--- /dev/null
+++ b/app/controllers/installation/onboarding_controller.rb
@@ -0,0 +1,36 @@
+class Installation::OnboardingController < ApplicationController
+ before_action :ensure_installation_onboarding
+
+ def index; end
+
+ def create
+ begin
+ AccountBuilder.new(
+ account_name: onboarding_params.dig(:user, :company),
+ user_full_name: onboarding_params.dig(:user, :name),
+ email: onboarding_params.dig(:user, :email),
+ user_password: params.dig(:user, :password),
+ confirmed: true
+ ).perform
+ rescue StandardError => e
+ redirect_to '/', flash: { error: e.message } and return
+ end
+ finish_onboarding
+ redirect_to '/'
+ end
+
+ private
+
+ def onboarding_params
+ params.permit(:subscribe_to_updates, user: [:name, :company, :email])
+ end
+
+ def finish_onboarding
+ ::Redis::Alfred.delete(::Redis::Alfred::CHATWOOT_INSTALLATION_ONBOARDING)
+ ChatwootHub.register_instance(onboarding_params) if onboarding_params[:subscribe_to_updates]
+ end
+
+ def ensure_installation_onboarding
+ redirect_to '/' unless ::Redis::Alfred.get(::Redis::Alfred::CHATWOOT_INSTALLATION_ONBOARDING)
+ end
+end
diff --git a/app/controllers/platform/api/v1/account_users_controller.rb b/app/controllers/platform/api/v1/account_users_controller.rb
new file mode 100644
index 000000000..8f651cfd9
--- /dev/null
+++ b/app/controllers/platform/api/v1/account_users_controller.rb
@@ -0,0 +1,29 @@
+class Platform::Api::V1::AccountUsersController < PlatformController
+ before_action :set_resource
+ before_action :validate_platform_app_permissible
+
+ def index
+ render json: @resource.account_users
+ end
+
+ def create
+ @account_user = @resource.account_users.find_or_initialize_by(user_id: account_user_params[:user_id])
+ @account_user.update!(account_user_params)
+ render json: @account_user
+ end
+
+ def destroy
+ @resource.account_users.find_by(user_id: account_user_params[:user_id])&.destroy
+ head :ok
+ end
+
+ private
+
+ def set_resource
+ @resource = Account.find(params[:account_id])
+ end
+
+ def account_user_params
+ params.permit(:user_id, :role)
+ end
+end
diff --git a/app/controllers/platform/api/v1/accounts_controller.rb b/app/controllers/platform/api/v1/accounts_controller.rb
new file mode 100644
index 000000000..24b39aa3e
--- /dev/null
+++ b/app/controllers/platform/api/v1/accounts_controller.rb
@@ -0,0 +1,32 @@
+class Platform::Api::V1::AccountsController < PlatformController
+ def create
+ @resource = Account.new(account_params)
+ @resource.save!
+ @platform_app.platform_app_permissibles.find_or_create_by(permissible: @resource)
+ render json: @resource
+ end
+
+ def show
+ render json: @resource
+ end
+
+ def update
+ @resource.update!(account_params)
+ render json: @resource
+ end
+
+ def destroy
+ # TODO: obfusicate account
+ head :ok
+ end
+
+ private
+
+ def set_resource
+ @resource = Account.find(params[:id])
+ end
+
+ def account_params
+ params.permit(:name)
+ end
+end
diff --git a/app/controllers/platform/api/v1/users_controller.rb b/app/controllers/platform/api/v1/users_controller.rb
new file mode 100644
index 000000000..81b526c8e
--- /dev/null
+++ b/app/controllers/platform/api/v1/users_controller.rb
@@ -0,0 +1,43 @@
+class Platform::Api::V1::UsersController < PlatformController
+ # ref: https://stackoverflow.com/a/45190318/939299
+ # set resource is called for other actions already in platform controller
+ # we want to add login to that chain as well
+ before_action(only: [:login]) { set_resource }
+ before_action(only: [:login]) { validate_platform_app_permissible }
+
+ def create
+ @resource = (User.find_by(email: user_params[:email]) || User.new(user_params))
+ @resource.confirm
+ @resource.save!
+ @platform_app.platform_app_permissibles.find_or_create_by(permissible: @resource)
+ render json: @resource
+ end
+
+ def login
+ render json: { url: "#{ENV['FRONTEND_URL']}/app/login?email=#{@resource.email}&sso_auth_token=#{@resource.generate_sso_auth_token}" }
+ end
+
+ def show
+ render json: @resource
+ end
+
+ def update
+ @resource.update!(user_params)
+ render json: @resource
+ end
+
+ def destroy
+ # TODO: obfusicate user
+ head :ok
+ end
+
+ private
+
+ def set_resource
+ @resource = User.find(params[:id])
+ end
+
+ def user_params
+ params.permit(:name, :email, :password)
+ end
+end
diff --git a/app/controllers/platform_controller.rb b/app/controllers/platform_controller.rb
new file mode 100644
index 000000000..612f86d27
--- /dev/null
+++ b/app/controllers/platform_controller.rb
@@ -0,0 +1,37 @@
+class PlatformController < ActionController::Base
+ protect_from_forgery with: :null_session
+
+ before_action :ensure_access_token
+ before_action :set_platform_app
+ before_action :set_resource, only: [:update, :show, :destroy]
+ before_action :validate_platform_app_permissible, only: [:update, :show, :destroy]
+
+ def show; end
+
+ def update; end
+
+ def destroy; end
+
+ private
+
+ def ensure_access_token
+ token = request.headers[:api_access_token] || request.headers[:HTTP_API_ACCESS_TOKEN]
+ @access_token = AccessToken.find_by(token: token) if token.present?
+ end
+
+ def set_platform_app
+ @platform_app = @access_token.owner if @access_token && @access_token.owner.is_a?(PlatformApp)
+ render json: { error: 'Invalid access_token' }, status: :unauthorized if @platform_app.blank?
+ end
+
+ def set_resource
+ # set @resource in your controller
+ raise 'Overwrite this method your controller'
+ end
+
+ def validate_platform_app_permissible
+ return if @platform_app.platform_app_permissibles.find_by(permissible: @resource)
+
+ render json: { error: 'Non permissible resource' }, status: :unauthorized
+ end
+end
diff --git a/app/controllers/super_admin/installation_configs_controller.rb b/app/controllers/super_admin/installation_configs_controller.rb
new file mode 100644
index 000000000..36a45f707
--- /dev/null
+++ b/app/controllers/super_admin/installation_configs_controller.rb
@@ -0,0 +1,46 @@
+class SuperAdmin::InstallationConfigsController < SuperAdmin::ApplicationController
+ # Overwrite any of the RESTful controller actions to implement custom behavior
+ # For example, you may want to send an email after a foo is updated.
+ #
+ # def update
+ # super
+ # send_foo_updated_email(requested_resource)
+ # end
+
+ # Override this method to specify custom lookup behavior.
+ # This will be used to set the resource for the `show`, `edit`, and `update`
+ # actions.
+ #
+ # def find_resource(param)
+ # Foo.find_by!(slug: param)
+ # end
+
+ # The result of this lookup will be available as `requested_resource`
+
+ # Override this if you have certain roles that require a subset
+ # this will be used to set the records shown on the `index` action.
+ #
+ def scoped_resource
+ resource_class.editable
+ end
+
+ # Override `resource_params` if you want to transform the submitted
+ # data before it's persisted. For example, the following would turn all
+ # empty values into nil values. It uses other APIs such as `resource_class`
+ # and `dashboard`:
+ #
+ # def resource_params
+ # params.require(resource_class.model_name.param_key).
+ # permit(dashboard.permitted_attributes).
+ # transform_values { |value| value == "" ? nil : value }
+ # end
+
+ def resource_params
+ params.require(:installation_config)
+ .permit(:name, :value)
+ .transform_values { |value| value == '' ? nil : value }.merge(locked: false)
+ end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+end
diff --git a/app/dashboards/installation_config_dashboard.rb b/app/dashboards/installation_config_dashboard.rb
new file mode 100644
index 000000000..8a60c0dba
--- /dev/null
+++ b/app/dashboards/installation_config_dashboard.rb
@@ -0,0 +1,66 @@
+require 'administrate/base_dashboard'
+
+class InstallationConfigDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ id: Field::Number,
+ name: Field::String,
+ value: SerializedField,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = %i[
+ id
+ name
+ value
+ created_at
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = %i[
+ id
+ name
+ value
+ created_at
+ updated_at
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = %i[
+ name
+ value
+ ].freeze
+
+ # COLLECTION_FILTERS
+ # a hash that defines filters that can be used while searching via the search
+ # field of the dashboard.
+ #
+ # For example to add an option to search for open resources by typing "open:"
+ # in the search field:
+ #
+ # COLLECTION_FILTERS = {
+ # open: ->(resources) { resources.where(open: true) }
+ # }.freeze
+ COLLECTION_FILTERS = {}.freeze
+
+ # Overwrite this method to customize how installation configs are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(installation_config)
+ # "InstallationConfig ##{installation_config.id}"
+ # end
+end
diff --git a/app/fields/serialized_field.rb b/app/fields/serialized_field.rb
new file mode 100644
index 000000000..5c1069c42
--- /dev/null
+++ b/app/fields/serialized_field.rb
@@ -0,0 +1,15 @@
+require 'administrate/field/base'
+
+class SerializedField < Administrate::Field::Base
+ def to_s
+ hash? ? data.as_json : data.to_s
+ end
+
+ def hash?
+ data.is_a? Hash
+ end
+
+ def array?
+ data.is_a? Array
+ end
+end
diff --git a/app/javascript/dashboard/api/auth.js b/app/javascript/dashboard/api/auth.js
index 1a16108ca..5de3e8d9b 100644
--- a/app/javascript/dashboard/api/auth.js
+++ b/app/javascript/dashboard/api/auth.js
@@ -26,7 +26,8 @@ export default {
const fetchPromise = new Promise((resolve, reject) => {
axios
.post(urlData.url, {
- account_name: creds.name,
+ account_name: creds.accountName.trim(),
+ user_full_name: creds.fullName.trim(),
email: creds.email,
})
.then(response => {
@@ -139,6 +140,12 @@ export default {
return axios.put(endPoints('profileUpdate').url, formData);
},
+ updateUISettings({ uiSettings }) {
+ return axios.put(endPoints('profileUpdate').url, {
+ profile: { ui_settings: uiSettings },
+ });
+ },
+
updateAvailability({ availability }) {
return axios.put(endPoints('profileUpdate').url, {
profile: { availability },
diff --git a/app/javascript/dashboard/api/inbox/message.js b/app/javascript/dashboard/api/inbox/message.js
index 07754fd10..0020a4138 100644
--- a/app/javascript/dashboard/api/inbox/message.js
+++ b/app/javascript/dashboard/api/inbox/message.js
@@ -7,11 +7,26 @@ class MessageApi extends ApiClient {
super('conversations', { accountScoped: true });
}
- create({ conversationId, message, private: isPrivate, contentAttributes }) {
- return axios.post(`${this.url}/${conversationId}/messages`, {
- content: message,
- private: isPrivate,
- content_attributes: contentAttributes,
+ create({
+ conversationId,
+ message,
+ private: isPrivate,
+ contentAttributes,
+ echo_id: echoId,
+ file,
+ }) {
+ const formData = new FormData();
+ if (file) formData.append('attachments[]', file, file.name);
+ if (message) formData.append('content', message);
+ if (contentAttributes)
+ formData.append('content_attributes', JSON.stringify(contentAttributes));
+
+ formData.append('private', isPrivate);
+ formData.append('echo_id', echoId);
+ return axios({
+ method: 'post',
+ url: `${this.url}/${conversationId}/messages`,
+ data: formData,
});
}
@@ -20,17 +35,6 @@ class MessageApi extends ApiClient {
params: { before },
});
}
-
- sendAttachment([conversationId, { file, isPrivate = false }]) {
- const formData = new FormData();
- formData.append('attachments[]', file, file.name);
- formData.append('private', isPrivate);
- return axios({
- method: 'post',
- url: `${this.url}/${conversationId}/messages`,
- data: formData,
- });
- }
}
export default new MessageApi();
diff --git a/app/javascript/dashboard/assets/scss/_foundation-custom.scss b/app/javascript/dashboard/assets/scss/_foundation-custom.scss
index 175a65604..d76fef07d 100644
--- a/app/javascript/dashboard/assets/scss/_foundation-custom.scss
+++ b/app/javascript/dashboard/assets/scss/_foundation-custom.scss
@@ -1,4 +1,3 @@
-
.button {
font-family: $body-font-family;
font-weight: $font-weight-medium;
@@ -35,6 +34,7 @@ code {
&.hljs {
background: $color-background;
+ border-radius: var(--border-radius-large);
padding: $space-two;
}
}
diff --git a/app/javascript/dashboard/assets/scss/_foundation-settings.scss b/app/javascript/dashboard/assets/scss/_foundation-settings.scss
index b96a1b5bd..79bc1ae29 100644
--- a/app/javascript/dashboard/assets/scss/_foundation-settings.scss
+++ b/app/javascript/dashboard/assets/scss/_foundation-settings.scss
@@ -236,18 +236,18 @@ $breadcrumbs-item-slash: true;
// 11. Button
// ----------
-$button-padding: $space-one $space-normal;
+$button-padding: var(--space-one) var(--space-slab);
$button-margin: 0 0 $global-margin 0;
$button-fill: solid;
$button-background: $primary-color;
$button-background-hover: scale-color($button-background, $lightness: -15%);
$button-color: $white;
$button-color-alt: $white;
-$button-radius: $global-radius;
-$button-sizes: (tiny: $font-size-micro,
- small: $font-size-mini,
- default: $font-size-default,
- large: $font-size-large);
+$button-radius: var(--border-radius-normal);
+$button-sizes: (tiny: var(--font-size-nano),
+ small: var(--font-size-mini),
+ default: var(--font-size-small),
+ large: var(--font-size-medium));
$button-palette: $foundation-palette;
$button-opacity-disabled: 0.25;
$button-background-hover-lightness: -20%;
diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss
index 7f9041b93..e53ceef73 100644
--- a/app/javascript/dashboard/assets/scss/_woot.scss
+++ b/app/javascript/dashboard/assets/scss/_woot.scss
@@ -23,7 +23,7 @@
@import 'views/settings/inbox';
@import 'views/settings/channel';
@import 'views/settings/integrations';
-@import 'views/signup';
@import 'plugins/multiselect';
@import 'plugins/dropdown';
+@import '@chatwoot/prosemirror-schema/src/woot-editor.css';
diff --git a/app/javascript/dashboard/assets/scss/app.scss b/app/javascript/dashboard/assets/scss/app.scss
index 3220f0326..dbf3a6e78 100644
--- a/app/javascript/dashboard/assets/scss/app.scss
+++ b/app/javascript/dashboard/assets/scss/app.scss
@@ -3,10 +3,12 @@
@import 'shared/assets/stylesheets/spacing';
@import 'shared/assets/stylesheets/font-size';
@import 'shared/assets/stylesheets/font-weights';
+@import 'shared/assets/stylesheets/shadows';
+@import 'shared/assets/stylesheets/border-radius';
@import 'variables';
@import '~spinkit/scss/spinners/7-three-bounce';
-@import '~ionicons/scss/ionicons';
+@import '~shared/assets/stylesheets/ionicons';
@import 'mixins';
@import 'foundation-settings';
diff --git a/app/javascript/dashboard/assets/scss/super_admin/index.scss b/app/javascript/dashboard/assets/scss/super_admin/index.scss
index a646bf5f9..205a10f70 100644
--- a/app/javascript/dashboard/assets/scss/super_admin/index.scss
+++ b/app/javascript/dashboard/assets/scss/super_admin/index.scss
@@ -1,15 +1,36 @@
@import '../variables';
.superadmin-body {
- background: $color-background;
+ background: var(--color-background);
+
+ .hero--title {
+ font-size: var(--font-size-mega);
+ font-weight: var(--font-weight-light);
+ margin-top: var(--space-large);
+ }
}
.alert-box {
- background-color: $alert-color;
+ background-color: var(--r-500);
border-radius: 5px;
- color: $color-white;
+ color: var(--color-white);
font-size: 14px;
margin-bottom: 14px;
padding: 10px;
text-align: center;
}
+
+.update-subscription--checkbox {
+ display: flex;
+
+ input {
+ line-height: 1.5;
+ margin-right: var(--space-one);
+ }
+
+ div {
+ font-size: var(--font-size-small);
+ line-height: 1.5;
+ margin-bottom: var(--space-normal);
+ }
+}
diff --git a/app/javascript/dashboard/assets/scss/super_admin/pages.scss b/app/javascript/dashboard/assets/scss/super_admin/pages.scss
index 2bc31db1c..8e5b86989 100644
--- a/app/javascript/dashboard/assets/scss/super_admin/pages.scss
+++ b/app/javascript/dashboard/assets/scss/super_admin/pages.scss
@@ -1,3 +1,3 @@
@import 'shared/assets/fonts/inter';
@import '../variables';
-@import '~ionicons/scss/ionicons';
+@import '~shared/assets/stylesheets/ionicons';
diff --git a/app/javascript/dashboard/assets/scss/views/_signup.scss b/app/javascript/dashboard/assets/scss/views/_signup.scss
deleted file mode 100644
index 5233e3de0..000000000
--- a/app/javascript/dashboard/assets/scss/views/_signup.scss
+++ /dev/null
@@ -1,94 +0,0 @@
-.signup {
- // margin-top: $space-larger*1.2;
-
- .signup--hero {
- margin-bottom: $space-larger * 1.5;
-
- .hero--logo {
- width: 180px;
- }
-
- .hero--title {
- margin-top: $space-large;
- font-weight: $font-weight-light;
- }
-
- .hero--sub {
- font-size: $font-size-medium;
- color: $medium-gray;
- }
- }
-
- .signup--features {
- list-style-type: none;
- font-size: $font-size-medium;
-
- > li {
- padding: $space-slab;
-
- > i {
- margin-right: $space-two;
- font-size: $font-size-large;
-
- &.beer {
- color: #dfb63b;
- }
-
- &.report {
- color: #2196f3;
- }
-
- &.canned {
- color: #1cad22;
- }
-
- &.uptime {
- color: #a753b5;
- }
-
- &.secure {
- color: #607d8b;
- }
- }
- }
- }
-
- .signup--box {
- @include elegant-card;
- padding: $space-large;
-
- label {
- font-size: $font-size-default;
- color: $color-gray;
-
- input {
- padding: $space-slab;
- height: $space-larger;
- font-size: $font-size-default;
- }
-
- .error {
- font-size: $font-size-small
- }
- }
- }
-
- .sigin--footer {
- padding: $space-medium;
- font-size: $font-size-default;
-
- > a {
- font-weight: $font-weight-bold;
- }
- }
-
- .accept--terms {
- font-size: $font-size-mini;
- text-align: center;
- @include margin($zero);
-
- a {
- font-size: $font-size-mini;
- }
- }
-}
diff --git a/app/javascript/dashboard/assets/scss/widgets/_buttons.scss b/app/javascript/dashboard/assets/scss/widgets/_buttons.scss
index 280997559..07089b399 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_buttons.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_buttons.scss
@@ -1,6 +1,21 @@
.button {
margin-bottom: 0;
+ &.button--emoji {
+ background: var(--b-50);
+ border: 1px solid var(--color-border-light);
+ border-radius: var(--border-radius-large);
+ font-size: var(--font-size-small);
+ margin-right: var(--space-small);
+ padding: var(--space-small);
+
+ &:hover {
+ background: var(--b-200);
+ }
+ }
+
+
+
&.icon {
padding-left: $space-normal;
padding-right: $space-normal;
diff --git a/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss b/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
index 9b8c71500..c6cc66c96 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_conv-header.scss
@@ -72,7 +72,7 @@ $resolve-button-width: 13.2rem;
.button.resolve--button {
@include flex-align($x: center, $y: middle);
-
+ font-size: var(--font-size-default);
width: $resolve-button-width;
>.icon {
diff --git a/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss b/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
index c35abab4f..d518812f1 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_conversation-view.scss
@@ -3,7 +3,7 @@
@include margin($zero);
background: $color-woot;
border-radius: $space-one;
- color: $color-white;
+ color: var(--white);
font-size: $font-size-small;
font-weight: $font-weight-normal;
position: relative;
@@ -11,20 +11,12 @@
.message-text__wrap {
position: relative;
-
.link {
- color: $color-white;
+ color: var(--white);
text-decoration: underline;
}
}
- .message-text {
- &::after {
- content: ' \00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0';
- display: inline;
- }
- }
-
.image {
cursor: pointer;
position: relative;
@@ -95,17 +87,15 @@
}
}
-
-
.content-box {
text-align: center;
}
}
.conversation-wrap {
- @include background-gray;
@include margin(0);
@include border-normal-left;
+ background: var(--color-background-light);
.current-chat {
@include flex;
@@ -145,10 +135,9 @@
@include flex-weight(1);
@include margin($zero);
flex-direction: column;
- // Firefox flexbox fix
height: 100%;
- margin-bottom: $space-small;
overflow-y: auto;
+ padding-bottom: var(--space-normal);
position: relative;
}
@@ -171,7 +160,7 @@
@include elegant-card;
@include round-corner;
background: $color-woot;
- color: $color-white;
+ color: var(--white);
font-size: $font-size-mini;
font-weight: $font-weight-medium;
margin: $space-one auto;
@@ -201,6 +190,10 @@
color: $color-body;
margin-right: auto;
+ &.is-image {
+ border-radius: var(--border-radius-large);
+ }
+
.link {
color: $color-primary-dark;
}
@@ -218,6 +211,7 @@
color: $color-primary-dark;
}
}
+
}
+.right {
@@ -247,7 +241,6 @@
background: lighten($warning-color, 32%);
border: 1px solid lighten($warning-color, 15%);
color: $color-heading;
- padding-right: $space-large;
position: relative;
&::before {
@@ -258,6 +251,10 @@
top: $space-smaller + $space-micro;
}
}
+
+ &.is-image {
+ border-radius: var(--border-radius-large);
+ }
}
+.left {
@@ -297,30 +294,15 @@
border-radius: $space-smaller;
font-size: $font-size-small;
- p {
- color: $color-heading;
- margin-bottom: $zero;
-
- .ion-person {
- color: $color-body;
- font-size: $font-size-default;
- margin-right: $space-small;
- position: relative;
- top: $space-micro;
- }
-
- .message-text__wrap {
- position: relative;
- }
-
- .message-text {
- &::after {
- content: ' \00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0';
- display: inline;
- }
- }
+ .message-text__wrap {
+ display: inline-block;
}
+ }
+}
+.activity-wrap .message-text__wrap {
+ .text-content p {
+ margin-bottom: 0;
}
}
@@ -341,7 +323,7 @@
.typing-indicator {
@include elegant-card;
@include round-corner;
- background: $color-white;
+ background: var(--white);
color: $color-light-gray;
font-size: $font-size-mini;
font-weight: $font-weight-bold;
@@ -354,3 +336,65 @@
}
}
}
+
+.left .bubble .text-content {
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ color: var(--color-body);
+ }
+
+ a {
+ color: var(--color-woot);
+ text-decoration: underline;
+ }
+
+ blockquote {
+ border-left-color: var(--s-300);
+
+ p {
+ color: var(--s-300);
+ }
+ }
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.right .bubble .text-content {
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ color: var(--white);
+ }
+
+ a {
+ color: var(--white);
+ text-decoration: underline;
+ }
+
+ blockquote {
+ border-left-color: var(--w-100);
+
+ p {
+ color: var(--w-100);
+ }
+ }
+
+ pre code {
+ background: var(--color-background);
+ }
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+}
diff --git a/app/javascript/dashboard/assets/scss/widgets/_forms.scss b/app/javascript/dashboard/assets/scss/widgets/_forms.scss
index d824f9d48..231f4c535 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_forms.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_forms.scss
@@ -2,12 +2,13 @@
#{$all-text-inputs},
select,
.multiselect > .multiselect__tags {
- @include thin-border(darken(get-color(alert), 25%));
+ @include thin-border(var(--r-400));
}
.message {
- color: darken(get-color(alert), 25%);
+ color: var(--r-400);
display: block;
+ font-size: var(--font-size-small);
font-weight: $font-weight-normal;
margin-bottom: $space-one;
margin-top: -$space-normal;
diff --git a/app/javascript/dashboard/assets/scss/widgets/_reply-box.scss b/app/javascript/dashboard/assets/scss/widgets/_reply-box.scss
index a234a110d..870a60c1b 100644
--- a/app/javascript/dashboard/assets/scss/widgets/_reply-box.scss
+++ b/app/javascript/dashboard/assets/scss/widgets/_reply-box.scss
@@ -1,28 +1,13 @@
.reply-box {
- @include light-shadow;
- border-bottom: 0;
- border-radius: $space-small;
- margin: $space-normal;
- margin-top: 0;
- max-height: $space-mega * 3;
transition: box-shadow .35s $swift-ease-out-function,
height 2s $swift-ease-out-function;
&.is-focused {
- @include shadow;
+ box-shadow: var(--shadow);
}
.reply-box__top {
- @include flex;
- @include flex-align($x: left, $y: middle);
- @include padding($space-one $space-normal);
- @include background-white;
- @include margin(0);
- border-top-left-radius: $space-small;
- border-top-right-radius: $space-small;
- position: relative;
-
.canned {
@include elegant-card;
background: $color-white;
@@ -41,19 +26,6 @@
}
}
- &.is-active {
- border-bottom-left-radius: $space-small;
- border-bottom-right-radius: $space-small;
- }
-
- &.is-private {
- background: lighten($warning-color, 38%);
-
- >input {
- background: lighten($warning-color, 38%);
- }
- }
-
.icon {
color: $medium-gray;
cursor: pointer;
@@ -65,9 +37,6 @@
}
}
- .file-uploads>label {
- cursor: pointer;
- }
.attachment {
cursor: pointer;
@@ -82,87 +51,45 @@
// Override min-height : 50px in foundation
//
max-height: $space-mega * 2.4;
- min-height: 4rem;
+ min-height: 4.8rem;
+ padding: var(--space-normal) 0 0;
resize: none;
}
}
- .reply-box__bottom {
- @include background-light;
- @include flex;
- @include flex-align($x: justify, $y: middle);
- @include border-light-top;
- border-bottom-left-radius: $space-small;
- border-bottom-right-radius: $space-small;
+ &.is-private {
+ background: var(--y-50);
- .tabs {
- border: 0;
- flex: 1;
- padding: 0;
+ .reply-box__top {
+ background: var(--y-50);
- .tabs-title {
- margin: 0;
- transition: all .2s $swift-ease-out-function;
- transition-property: color, background;
-
- a {
- font-weight: $font-weight-medium;
- padding: $space-one $space-two;
- }
-
- &.is-private.is-active {
- background: lighten($warning-color, 38%);
-
- a {
- border-bottom-color: darken($warning-color, 15%);
- color: darken($warning-color, 15%);
- }
- }
- }
-
- .tabs-title:first-child {
- border-bottom-left-radius: $space-small;
-
- &.is-active {
- @include border-light-right;
- border-left: 0;
- }
-
- a {
- border-bottom-left-radius: $space-small;
- }
- }
-
- .is-active {
- @include background-white;
- @include border-light-left;
- @include border-light-right;
- margin-top: -1px;
- }
-
- .message-length {
- float: right;
-
- a {
- font-size: $font-size-mini;
- }
- }
-
- .message-error {
- color: $input-error-color;
- }
- }
-
- .send-button {
- border-bottom-right-radius: $space-small;
- height: 3.6rem;
- padding-left: $space-two;
- padding-right: $space-two;
- padding-top: $space-small;
-
- .icon {
- margin-left: $space-small;
+ >input {
+ background: var(--y-50);
}
}
}
+
+ .file-uploads>label {
+ cursor: pointer;
+
+ &:hover .button--emoji {
+ background: var(--b-200);
+ }
+ }
+
+ .bottom-box .button--emoji.button--upload {
+ height: var(--space-large);
+ padding: 0;
+ width: var(--space-large);
+
+ .file-uploads {
+ height: 100%;
+ line-height: var(--space-large);
+ width: 100%;
+ }
+
+ label {
+ padding: var(--space-small);
+ }
+ }
}
diff --git a/app/javascript/dashboard/components/SettingsSection.vue b/app/javascript/dashboard/components/SettingsSection.vue
index fd930914b..26caff02c 100644
--- a/app/javascript/dashboard/components/SettingsSection.vue
+++ b/app/javascript/dashboard/components/SettingsSection.vue
@@ -42,5 +42,9 @@ export default {
font-weight: $font-weight-medium;
margin-bottom: 0;
}
+
+ .title--section {
+ padding-right: var(--space-large);
+ }
}
diff --git a/app/javascript/dashboard/components/buttons/ResolveAction.vue b/app/javascript/dashboard/components/buttons/ResolveAction.vue
index 8d99d3ce3..6127eec43 100644
--- a/app/javascript/dashboard/components/buttons/ResolveAction.vue
+++ b/app/javascript/dashboard/components/buttons/ResolveAction.vue
@@ -1,7 +1,7 @@
diff --git a/app/javascript/dashboard/helper/commons.js b/app/javascript/dashboard/helper/commons.js
index c32d2717a..d7d34283a 100644
--- a/app/javascript/dashboard/helper/commons.js
+++ b/app/javascript/dashboard/helper/commons.js
@@ -1,5 +1,8 @@
-/* eslint no-console: 0 */
/* eslint no-param-reassign: 0 */
+
+import getUuid from 'widget/helpers/uuid';
+import { MESSAGE_STATUS, MESSAGE_TYPE } from 'shared/constants/messages';
+
export default () => {
if (!Array.prototype.last) {
Object.assign(Array.prototype, {
@@ -26,3 +29,23 @@ export const getTypingUsersText = (users = []) => {
const rest = users.length - 1;
return `${user.name} and ${rest} others are typing`;
};
+
+export const createPendingMessage = data => {
+ const timestamp = Math.floor(new Date().getTime() / 1000);
+ const tempMessageId = getUuid();
+ const { message, file } = data;
+ const tempAttachments = [{ id: tempMessageId }];
+ const pendingMessage = {
+ ...data,
+ content: message || null,
+ id: tempMessageId,
+ echo_id: tempMessageId,
+ status: MESSAGE_STATUS.PROGRESS,
+ created_at: timestamp,
+ message_type: MESSAGE_TYPE.OUTGOING,
+ conversation_id: data.conversationId,
+ attachments: file ? tempAttachments : null,
+ };
+
+ return pendingMessage;
+};
diff --git a/app/javascript/dashboard/helper/files.js b/app/javascript/dashboard/helper/files.js
new file mode 100644
index 000000000..4f7559304
--- /dev/null
+++ b/app/javascript/dashboard/helper/files.js
@@ -0,0 +1,11 @@
+export const formatBytes = (bytes, decimals = 2) => {
+ if (bytes === 0) return '0 Bytes';
+
+ const k = 1024;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
+};
diff --git a/app/javascript/dashboard/helper/specs/commons.spec.js b/app/javascript/dashboard/helper/specs/commons.spec.js
index 180846496..2df5e36b5 100644
--- a/app/javascript/dashboard/helper/specs/commons.spec.js
+++ b/app/javascript/dashboard/helper/specs/commons.spec.js
@@ -1,4 +1,4 @@
-import { getTypingUsersText } from '../commons';
+import { getTypingUsersText, createPendingMessage } from '../commons';
describe('#getTypingUsersText', () => {
it('returns the correct text is there is only one typing user', () => {
@@ -24,3 +24,62 @@ describe('#getTypingUsersText', () => {
).toEqual('Pranav and 3 others are typing');
});
});
+
+describe('#createPendingMessage', () => {
+ const message = {
+ message: 'hi',
+ };
+ it('returns the pending message with expected new keys', () => {
+ expect(createPendingMessage(message)).toHaveProperty(
+ 'content',
+ 'id',
+ 'status',
+ 'echo_id',
+ 'status',
+ 'created_at',
+ 'message_type',
+ 'conversation_id'
+ );
+ });
+
+ it('returns the pending message with status progress', () => {
+ expect(createPendingMessage(message)).toMatchObject({
+ status: 'progress',
+ });
+ });
+
+ it('returns the pending message with same id and echo_id', () => {
+ const pending = createPendingMessage(message);
+ expect(pending).toMatchObject({
+ echo_id: pending.id,
+ });
+ });
+
+ it('returns the pending message with attachmnet key if file is passed', () => {
+ const messageWithFile = {
+ message: 'hi',
+ file: {},
+ };
+ expect(createPendingMessage(messageWithFile)).toHaveProperty(
+ 'content',
+ 'id',
+ 'status',
+ 'echo_id',
+ 'status',
+ 'created_at',
+ 'message_type',
+ 'conversation_id',
+ 'attachments',
+ 'private'
+ );
+ });
+
+ it('returns the pending message to have one attachment', () => {
+ const messageWithFile = {
+ message: 'hi',
+ file: {},
+ };
+ const pending = createPendingMessage(messageWithFile);
+ expect(pending.attachments.length).toBe(1);
+ });
+});
diff --git a/app/javascript/dashboard/helper/specs/files.spec.js b/app/javascript/dashboard/helper/specs/files.spec.js
new file mode 100644
index 000000000..3b2c86bcd
--- /dev/null
+++ b/app/javascript/dashboard/helper/specs/files.spec.js
@@ -0,0 +1,18 @@
+import { formatBytes } from '../files';
+
+describe('#File Helpers', () => {
+ describe('formatBytes', () => {
+ it('should return zero bytes if 0 is passed', () => {
+ expect(formatBytes(0)).toBe('0 Bytes');
+ });
+ it('should return in bytes if 1000 is passed', () => {
+ expect(formatBytes(1000)).toBe('1000 Bytes');
+ });
+ it('should return in KB if 100000 is passed', () => {
+ expect(formatBytes(10000)).toBe('9.77 KB');
+ });
+ it('should return in MB if 10000000 is passed', () => {
+ expect(formatBytes(10000000)).toBe('9.54 MB');
+ });
+ });
+});
diff --git a/app/javascript/dashboard/i18n/default-sidebar.js b/app/javascript/dashboard/i18n/default-sidebar.js
index 657a60eef..f39f5b4f8 100644
--- a/app/javascript/dashboard/i18n/default-sidebar.js
+++ b/app/javascript/dashboard/i18n/default-sidebar.js
@@ -25,7 +25,7 @@ export const getSidebarItems = accountId => ({
toStateName: 'home',
},
contacts: {
- icon: 'ion-person-stalker',
+ icon: 'ion-person',
label: 'CONTACTS',
hasSubMenu: false,
toState: frontendURL(`accounts/${accountId}/contacts`),
diff --git a/app/javascript/dashboard/i18n/locale/ar/contact.json b/app/javascript/dashboard/i18n/locale/ar/contact.json
index 9414816ce..2a22cbb3c 100644
--- a/app/javascript/dashboard/i18n/locale/ar/contact.json
+++ b/app/javascript/dashboard/i18n/locale/ar/contact.json
@@ -11,6 +11,7 @@
"OS": "نظام التشغيل",
"INITIATED_FROM": "تم البدء من",
"INITIATED_AT": "تم البدء في",
+ "IP_ADDRESS": "IP Address",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "لا توجد محادثات سابقة مرتبطة بجهة الاتصال هذه.",
"TITLE": "المحادثات السابقة"
diff --git a/app/javascript/dashboard/i18n/locale/ar/conversation.json b/app/javascript/dashboard/i18n/locale/ar/conversation.json
index 204e4f497..cc05895cb 100644
--- a/app/javascript/dashboard/i18n/locale/ar/conversation.json
+++ b/app/javascript/dashboard/i18n/locale/ar/conversation.json
@@ -24,6 +24,7 @@
"REPLYING_TO": "أنت ترد على:",
"REMOVE_SELECTION": "إزالة التحديد",
"DOWNLOAD": "تنزيل",
+ "UPLOADING_ATTACHMENTS": "Uploading attachments...",
"HEADER": {
"RESOLVE_ACTION": "إغلاق المحادثة",
"REOPEN_ACTION": "إعادة فتح",
@@ -40,7 +41,10 @@
"PRIVATE_NOTE": "إضافة ملاحظة خاصة",
"SEND": "إرسال",
"CREATE": "إضافة ملاحظة",
- "TWEET": "تغريد"
+ "TWEET": "تغريد",
+ "TIP_FORMAT_ICON": "Show rich text editor",
+ "TIP_EMOJI_ICON": "Show emoji selector",
+ "TIP_ATTACH_ICON": "Attach files"
},
"VISIBLE_TO_AGENTS": "ملاحظة خاصة: مرئية فقط لأعضاء فريق العمل والموظفين",
"CHANGE_STATUS": "تم تغيير حالة المحادثة",
diff --git a/app/javascript/dashboard/i18n/locale/ar/generalSettings.json b/app/javascript/dashboard/i18n/locale/ar/generalSettings.json
index 682094f3f..351367867 100644
--- a/app/javascript/dashboard/i18n/locale/ar/generalSettings.json
+++ b/app/javascript/dashboard/i18n/locale/ar/generalSettings.json
@@ -42,7 +42,8 @@
"INBOUND_EMAIL_ENABLED": "الاستمرار في المحادثة عبر رسائل البريد الإلكتروني مفعّل لحسابك.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "يمكنك تلقي رسائل البريد الإلكتروني في النطاق المخصص الخاص بك الآن."
}
- }
+ },
+ "UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance."
},
"FORMS": {
"MULTISELECT": {
diff --git a/app/javascript/dashboard/i18n/locale/ar/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/ar/inboxMgmt.json
index 2375f6f3e..36c75a3a9 100644
--- a/app/javascript/dashboard/i18n/locale/ar/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/ar/inboxMgmt.json
@@ -241,7 +241,9 @@
"AUTO_ASSIGNMENT": "تفعيل الإسناد التلقائي",
"INBOX_UPDATE_TITLE": "إعدادات قناة التواصل",
"INBOX_UPDATE_SUB_TEXT": "تحديث إعدادات قناة التواصل",
- "AUTO_ASSIGNMENT_SUB_TEXT": "تمكين أو تعطيل الإسناد التلقائي للمحادثات الجديدة إلى الموظفين المضافين إلى قناة التواصل هذه."
+ "AUTO_ASSIGNMENT_SUB_TEXT": "تمكين أو تعطيل الإسناد التلقائي للمحادثات الجديدة إلى الموظفين المضافين إلى قناة التواصل هذه.",
+ "HMAC_VERIFICATION": "User Identity Validation",
+ "HMAC_DESCRIPTION": "Inorder validate the users identity, the SDK allows you to pass an `identity_hash` for each user. You can generate HMAC using 'sha256' with the key shown here."
},
"FACEBOOK_REAUTHORIZE": {
"TITLE": "إعادة التصريح",
diff --git a/app/javascript/dashboard/i18n/locale/ar/settings.json b/app/javascript/dashboard/i18n/locale/ar/settings.json
index be4724989..5b80c6bb9 100644
--- a/app/javascript/dashboard/i18n/locale/ar/settings.json
+++ b/app/javascript/dashboard/i18n/locale/ar/settings.json
@@ -113,7 +113,7 @@
"SIDEBAR": {
"CONVERSATIONS": "المحادثات",
"REPORTS": "التقارير",
- "CONTACTS": "Contacts (Beta)",
+ "CONTACTS": "Contacts",
"SETTINGS": "الإعدادات",
"HOME": "الرئيسية",
"AGENTS": "موظف الدعم",
diff --git a/app/javascript/dashboard/i18n/locale/ar/signup.json b/app/javascript/dashboard/i18n/locale/ar/signup.json
index f9999f877..3582ad041 100644
--- a/app/javascript/dashboard/i18n/locale/ar/signup.json
+++ b/app/javascript/dashboard/i18n/locale/ar/signup.json
@@ -5,13 +5,18 @@
"TERMS_ACCEPT": "من خلال التسجيل، فإنك توافق على شروط الخدمة و سياسة الخصوصية",
"ACCOUNT_NAME": {
"LABEL": "اسم الحساب",
- "PLACEHOLDER": "مؤسسة Wayne",
- "ERROR": "اسم الحساب قصير جداً"
+ "PLACEHOLDER": "Enter an account name. eg: Wayne Enterprises",
+ "ERROR": "Account name is too short"
+ },
+ "FULL_NAME": {
+ "LABEL": "Full name",
+ "PLACEHOLDER": "Enter your full name. eg: Bruce Wayne",
+ "ERROR": "Full name is too short"
},
"EMAIL": {
- "LABEL": "البريد الإلكتروني",
- "PLACEHOLDER": "bruce@wayne.enterprises",
- "ERROR": "البريد الإلكتروني غير صالح"
+ "LABEL": "Work email",
+ "PLACEHOLDER": "Enter your work email address. eg: bruce@wayne.enterprises",
+ "ERROR": "Email address is invalid"
},
"PASSWORD": {
"LABEL": "كلمة المرور",
@@ -28,12 +33,6 @@
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
},
"SUBMIT": "إرسال",
- "FEATURES": {
- "UNLIMITED_INBOXES": "Unlimited inboxes",
- "ROBUST_REPORTING": "Robust Reporting",
- "CANNED_RESPONSES": "الردود السريعة",
- "AUTO_ASSIGNMENT": "Auto Assignment",
- "SECURITY": "Enterprise level security"
- }
+ "HAVE_AN_ACCOUNT": "Already have an account?"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/ca/contact.json b/app/javascript/dashboard/i18n/locale/ca/contact.json
index aa707bacc..045aa0f20 100644
--- a/app/javascript/dashboard/i18n/locale/ca/contact.json
+++ b/app/javascript/dashboard/i18n/locale/ca/contact.json
@@ -11,6 +11,7 @@
"OS": "Sistema operatiu",
"INITIATED_FROM": "Iniciada des de",
"INITIATED_AT": "Iniciada a les",
+ "IP_ADDRESS": "Adreça IP",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "No hi han converses prèvies associades a aquest contacte.",
"TITLE": "Converses prèvies"
diff --git a/app/javascript/dashboard/i18n/locale/ca/conversation.json b/app/javascript/dashboard/i18n/locale/ca/conversation.json
index 65882712f..b58a644c1 100644
--- a/app/javascript/dashboard/i18n/locale/ca/conversation.json
+++ b/app/javascript/dashboard/i18n/locale/ca/conversation.json
@@ -13,8 +13,8 @@
"PLACEHOLDER": "Escriu qualsevol text per cercar missatges",
"NO_MATCHING_RESULTS": "No hi ha missatges que coincideixin amb els paràmetres de cerca."
},
- "UNREAD_MESSAGES": "Unread Messages",
- "UNREAD_MESSAGE": "Unread Message",
+ "UNREAD_MESSAGES": "Missatges no Llegits",
+ "UNREAD_MESSAGE": "Missatge no Llegit",
"CLICK_HERE": "Clica aquí",
"LOADING_INBOXES": "S'estan carregant les safates d'entrada",
"LOADING_CONVERSATIONS": "S'estan carregant les converses",
@@ -24,6 +24,7 @@
"REPLYING_TO": "Estas responent a:",
"REMOVE_SELECTION": "Elimina la selecció",
"DOWNLOAD": "Descarrega",
+ "UPLOADING_ATTACHMENTS": "Pujant fitxers adjunts...",
"HEADER": {
"RESOLVE_ACTION": "Resoldre",
"REOPEN_ACTION": "Tornar a obrir",
@@ -40,7 +41,10 @@
"PRIVATE_NOTE": "Nota privada",
"SEND": "Envia",
"CREATE": "Afegeix una nota",
- "TWEET": "Tuit"
+ "TWEET": "Tuit",
+ "TIP_FORMAT_ICON": "Show rich text editor",
+ "TIP_EMOJI_ICON": "Show emoji selector",
+ "TIP_ATTACH_ICON": "Attach files"
},
"VISIBLE_TO_AGENTS": "Nota privada: Només és visible per tu i el vostre equip",
"CHANGE_STATUS": "Estat de la conversa canviat",
diff --git a/app/javascript/dashboard/i18n/locale/ca/generalSettings.json b/app/javascript/dashboard/i18n/locale/ca/generalSettings.json
index 949267b11..20ca7465c 100644
--- a/app/javascript/dashboard/i18n/locale/ca/generalSettings.json
+++ b/app/javascript/dashboard/i18n/locale/ca/generalSettings.json
@@ -42,7 +42,8 @@
"INBOUND_EMAIL_ENABLED": "La continuïtat de converses amb correus electrònics està habilitada per al vostre compte.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "Ara podeu rebre correus electrònics al vostre domini personalitzat."
}
- }
+ },
+ "UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance."
},
"FORMS": {
"MULTISELECT": {
diff --git a/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
index cc827e9e7..1f4f8430a 100644
--- a/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/ca/inboxMgmt.json
@@ -241,7 +241,9 @@
"AUTO_ASSIGNMENT": "Activa l'assignació automàtica",
"INBOX_UPDATE_TITLE": "Configuració de la safata d'entrada",
"INBOX_UPDATE_SUB_TEXT": "Actualitza la configuració de la safata d'entrada",
- "AUTO_ASSIGNMENT_SUB_TEXT": "Activa o desactiva l'assignació automàtica d'agents disponibles a les noves converses"
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Activa o desactiva l'assignació automàtica d'agents disponibles a les noves converses",
+ "HMAC_VERIFICATION": "User Identity Validation",
+ "HMAC_DESCRIPTION": "Inorder validate the users identity, the SDK allows you to pass an `identity_hash` for each user. You can generate HMAC using 'sha256' with the key shown here."
},
"FACEBOOK_REAUTHORIZE": {
"TITLE": "Reautoritza",
diff --git a/app/javascript/dashboard/i18n/locale/ca/index.js b/app/javascript/dashboard/i18n/locale/ca/index.js
index 558cc9b3a..5dfc44e4b 100644
--- a/app/javascript/dashboard/i18n/locale/ca/index.js
+++ b/app/javascript/dashboard/i18n/locale/ca/index.js
@@ -1,5 +1,5 @@
-/* eslint-disable */
import { default as _agentMgmt } from './agentMgmt.json';
+import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
@@ -23,6 +23,7 @@ export default {
..._inboxMgmt,
..._login,
..._report,
+ ..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
diff --git a/app/javascript/dashboard/i18n/locale/ca/report.json b/app/javascript/dashboard/i18n/locale/ca/report.json
index 93813aa44..7dabbcb7e 100644
--- a/app/javascript/dashboard/i18n/locale/ca/report.json
+++ b/app/javascript/dashboard/i18n/locale/ca/report.json
@@ -3,7 +3,7 @@
"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.",
- "DOWNLOAD_AGENT_REPORTS": "Download agent reports",
+ "DOWNLOAD_AGENT_REPORTS": "Descarregar Informes d'Agent",
"METRICS": {
"CONVERSATIONS": {
"NAME": "Converses",
diff --git a/app/javascript/dashboard/i18n/locale/ca/settings.json b/app/javascript/dashboard/i18n/locale/ca/settings.json
index c0431495b..06d239685 100644
--- a/app/javascript/dashboard/i18n/locale/ca/settings.json
+++ b/app/javascript/dashboard/i18n/locale/ca/settings.json
@@ -113,7 +113,7 @@
"SIDEBAR": {
"CONVERSATIONS": "Converses",
"REPORTS": "Informes",
- "CONTACTS": "Contactes (Beta)",
+ "CONTACTS": "Contactes",
"SETTINGS": "Configuracions",
"HOME": "Inici",
"AGENTS": "Agents",
diff --git a/app/javascript/dashboard/i18n/locale/ca/signup.json b/app/javascript/dashboard/i18n/locale/ca/signup.json
index aa87cf84c..578dfde7a 100644
--- a/app/javascript/dashboard/i18n/locale/ca/signup.json
+++ b/app/javascript/dashboard/i18n/locale/ca/signup.json
@@ -5,13 +5,18 @@
"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",
+ "PLACEHOLDER": "Introdueix el nom del compte. ex: Wayne Enterprises",
+ "ERROR": "El nom del compte és massa curt"
+ },
+ "FULL_NAME": {
+ "LABEL": "Nom complet",
+ "PLACEHOLDER": "Introdueix el teu nom complet. ex: Bruce Wayne",
"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"
+ "LABEL": "Email de treball",
+ "PLACEHOLDER": "Introdueix la teva adreça email de treball. ex: bruce@wayne.enterprises",
+ "ERROR": "Adreça email invàlida"
},
"PASSWORD": {
"LABEL": "Contrasenya",
@@ -28,12 +33,6 @@
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
},
"SUBMIT": "Envia",
- "FEATURES": {
- "UNLIMITED_INBOXES": "Safates ilimitades",
- "ROBUST_REPORTING": "Informa robust",
- "CANNED_RESPONSES": "Respostes predeterminades",
- "AUTO_ASSIGNMENT": "Tasca Automàtica",
- "SECURITY": "Seguretat a nivell empreserial"
- }
+ "HAVE_AN_ACCOUNT": "Ja tens un compte?"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/cs/contact.json b/app/javascript/dashboard/i18n/locale/cs/contact.json
index 19f01f6ef..c7af0ddad 100644
--- a/app/javascript/dashboard/i18n/locale/cs/contact.json
+++ b/app/javascript/dashboard/i18n/locale/cs/contact.json
@@ -11,6 +11,7 @@
"OS": "Operační systém",
"INITIATED_FROM": "Zahájeno od",
"INITIATED_AT": "Zahájeno v",
+ "IP_ADDRESS": "IP adresa",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "K tomuto kontaktu nejsou přiřazeny žádné předchozí konverzace.",
"TITLE": "Předchozí konverzace"
diff --git a/app/javascript/dashboard/i18n/locale/cs/conversation.json b/app/javascript/dashboard/i18n/locale/cs/conversation.json
index 80fb50df8..d43167102 100644
--- a/app/javascript/dashboard/i18n/locale/cs/conversation.json
+++ b/app/javascript/dashboard/i18n/locale/cs/conversation.json
@@ -13,8 +13,8 @@
"PLACEHOLDER": "Zadejte jakýkoli text k hledání",
"NO_MATCHING_RESULTS": "Vašemu vyhledávání neodpovídají žádné zprávy."
},
- "UNREAD_MESSAGES": "Unread Messages",
- "UNREAD_MESSAGE": "Unread Message",
+ "UNREAD_MESSAGES": "Nepřečtené zprávy",
+ "UNREAD_MESSAGE": "Nepřečtená zpráva",
"CLICK_HERE": "Klikněte zde",
"LOADING_INBOXES": "Načítání krabic",
"LOADING_CONVERSATIONS": "Načítání konverzací",
@@ -24,6 +24,7 @@
"REPLYING_TO": "Odpovídáte uživateli:",
"REMOVE_SELECTION": "Odstranit výběr",
"DOWNLOAD": "Stáhnout",
+ "UPLOADING_ATTACHMENTS": "Nahrávání příloh...",
"HEADER": {
"RESOLVE_ACTION": "Vyřešit",
"REOPEN_ACTION": "Znovu otevřít",
@@ -40,16 +41,19 @@
"PRIVATE_NOTE": "Soukromá poznámka",
"SEND": "Poslat",
"CREATE": "Přidat poznámku",
- "TWEET": "Tweet"
+ "TWEET": "Tweet",
+ "TIP_FORMAT_ICON": "Show rich text editor",
+ "TIP_EMOJI_ICON": "Show emoji selector",
+ "TIP_ATTACH_ICON": "Attach files"
},
"VISIBLE_TO_AGENTS": "Soukromá poznámka: Viditelné pouze pro vás a váš tým",
"CHANGE_STATUS": "Stav konverzace byl změněn",
"CHANGE_AGENT": "Konverzace pověřená osoba změněna",
- "SENT_BY": "Sent by:",
+ "SENT_BY": "Odeslal:",
"ASSIGNMENT": {
- "SELECT_AGENT": "Select Agent",
+ "SELECT_AGENT": "Vybrat agenta",
"REMOVE": "Odebrat",
- "ASSIGN": "Assign"
+ "ASSIGN": "Přiřadit"
}
},
"EMAIL_TRANSCRIPT": {
diff --git a/app/javascript/dashboard/i18n/locale/cs/generalSettings.json b/app/javascript/dashboard/i18n/locale/cs/generalSettings.json
index 969d0c5b2..c2d583554 100644
--- a/app/javascript/dashboard/i18n/locale/cs/generalSettings.json
+++ b/app/javascript/dashboard/i18n/locale/cs/generalSettings.json
@@ -42,13 +42,14 @@
"INBOUND_EMAIL_ENABLED": "E-mailová konverzace je u vašeho účtu povolena.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "Nyní můžete přijímat e-maily na vaši vlastní doménu."
}
- }
+ },
+ "UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance."
},
"FORMS": {
"MULTISELECT": {
- "ENTER_TO_SELECT": "Press enter to select",
- "ENTER_TO_REMOVE": "Press enter to remove",
- "SELECT_ONE": "Select one"
+ "ENTER_TO_SELECT": "Stiskněte Enter pro vybrání",
+ "ENTER_TO_REMOVE": "Stiskněte Enter pro odebrání",
+ "SELECT_ONE": "Vyberte jeden"
}
}
}
diff --git a/app/javascript/dashboard/i18n/locale/cs/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/cs/inboxMgmt.json
index b1964a136..146b737c4 100644
--- a/app/javascript/dashboard/i18n/locale/cs/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/cs/inboxMgmt.json
@@ -75,10 +75,10 @@
},
"REPLY_TIME": {
"TITLE": "Nastavit čas odpovědi",
- "IN_A_FEW_MINUTES": "In a few minutes",
- "IN_A_FEW_HOURS": "In a few hours",
- "IN_A_DAY": "In a day",
- "HELP_TEXT": "This reply time will be displayed on the live chat widget"
+ "IN_A_FEW_MINUTES": "Do několika minut",
+ "IN_A_FEW_HOURS": "Do několika hodin",
+ "IN_A_DAY": "Do dne",
+ "HELP_TEXT": "Tento čas odpovědi bude zobrazen na widgetu"
},
"WIDGET_COLOR": {
"LABEL": "Barva widgetu",
@@ -241,7 +241,9 @@
"AUTO_ASSIGNMENT": "Povolit automatické přiřazení",
"INBOX_UPDATE_TITLE": "Nastavení doručené pošty",
"INBOX_UPDATE_SUB_TEXT": "Aktualizujte nastavení doručené pošty",
- "AUTO_ASSIGNMENT_SUB_TEXT": "Povolit nebo zakázat automatické přiřazování nových konverzací agentům přidaným do této schránky."
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Povolit nebo zakázat automatické přiřazování nových konverzací agentům přidaným do této schránky.",
+ "HMAC_VERIFICATION": "User Identity Validation",
+ "HMAC_DESCRIPTION": "Inorder validate the users identity, the SDK allows you to pass an `identity_hash` for each user. You can generate HMAC using 'sha256' with the key shown here."
},
"FACEBOOK_REAUTHORIZE": {
"TITLE": "Znovu autorizovat",
diff --git a/app/javascript/dashboard/i18n/locale/cs/settings.json b/app/javascript/dashboard/i18n/locale/cs/settings.json
index 3fc24e742..7b477e382 100644
--- a/app/javascript/dashboard/i18n/locale/cs/settings.json
+++ b/app/javascript/dashboard/i18n/locale/cs/settings.json
@@ -113,7 +113,7 @@
"SIDEBAR": {
"CONVERSATIONS": "Konverzace",
"REPORTS": "Zprávy",
- "CONTACTS": "Contacts (Beta)",
+ "CONTACTS": "Kontakty",
"SETTINGS": "Nastavení",
"HOME": "Home",
"AGENTS": "Agenti",
diff --git a/app/javascript/dashboard/i18n/locale/cs/signup.json b/app/javascript/dashboard/i18n/locale/cs/signup.json
index d5aa3956e..49f82b700 100644
--- a/app/javascript/dashboard/i18n/locale/cs/signup.json
+++ b/app/javascript/dashboard/i18n/locale/cs/signup.json
@@ -5,13 +5,18 @@
"TERMS_ACCEPT": "Registrací souhlasíte s našimi T & C a Zásadami ochrany osobních údajů",
"ACCOUNT_NAME": {
"LABEL": "Název účtu",
- "PLACEHOLDER": "Wayne podniky",
- "ERROR": "Název účtu je příliš krátký"
+ "PLACEHOLDER": "Enter an account name. eg: Wayne Enterprises",
+ "ERROR": "Account name is too short"
+ },
+ "FULL_NAME": {
+ "LABEL": "Full name",
+ "PLACEHOLDER": "Enter your full name. eg: Bruce Wayne",
+ "ERROR": "Full name is too short"
},
"EMAIL": {
- "LABEL": "E-mailová adresa",
- "PLACEHOLDER": "bruce@wayne.enterprises",
- "ERROR": "E-mail je neplatný"
+ "LABEL": "Work email",
+ "PLACEHOLDER": "Enter your work email address. eg: bruce@wayne.enterprises",
+ "ERROR": "Email address is invalid"
},
"PASSWORD": {
"LABEL": "Heslo",
@@ -28,12 +33,6 @@
"ERROR_MESSAGE": "Nelze se připojit k Woot serveru, opakujte akci později"
},
"SUBMIT": "Odeslat",
- "FEATURES": {
- "UNLIMITED_INBOXES": "Unlimited inboxes",
- "ROBUST_REPORTING": "Robust Reporting",
- "CANNED_RESPONSES": "Konzervované odpovědi",
- "AUTO_ASSIGNMENT": "Auto Assignment",
- "SECURITY": "Enterprise level security"
- }
+ "HAVE_AN_ACCOUNT": "Already have an account?"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/da/contact.json b/app/javascript/dashboard/i18n/locale/da/contact.json
index 4a2eb0bbf..bf22980e5 100644
--- a/app/javascript/dashboard/i18n/locale/da/contact.json
+++ b/app/javascript/dashboard/i18n/locale/da/contact.json
@@ -11,6 +11,7 @@
"OS": "Operativsystem",
"INITIATED_FROM": "Startet fra",
"INITIATED_AT": "Startet fra",
+ "IP_ADDRESS": "IP Address",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "Der er ingen tidligere samtaler tilknyttet denne kontakt.",
"TITLE": "Tidligere Samtaler"
diff --git a/app/javascript/dashboard/i18n/locale/da/conversation.json b/app/javascript/dashboard/i18n/locale/da/conversation.json
index 260238d29..db40a2e32 100644
--- a/app/javascript/dashboard/i18n/locale/da/conversation.json
+++ b/app/javascript/dashboard/i18n/locale/da/conversation.json
@@ -24,6 +24,7 @@
"REPLYING_TO": "Du svarer til:",
"REMOVE_SELECTION": "Fjern Markering",
"DOWNLOAD": "Download",
+ "UPLOADING_ATTACHMENTS": "Uploading attachments...",
"HEADER": {
"RESOLVE_ACTION": "Løs",
"REOPEN_ACTION": "Genåben",
@@ -40,7 +41,10 @@
"PRIVATE_NOTE": "Privat Note",
"SEND": "Send",
"CREATE": "Tilføj Note",
- "TWEET": "Tweet"
+ "TWEET": "Tweet",
+ "TIP_FORMAT_ICON": "Show rich text editor",
+ "TIP_EMOJI_ICON": "Show emoji selector",
+ "TIP_ATTACH_ICON": "Attach files"
},
"VISIBLE_TO_AGENTS": "Privat Note: Kun synlig for dig og dit team",
"CHANGE_STATUS": "Samtalestatus ændret",
diff --git a/app/javascript/dashboard/i18n/locale/da/generalSettings.json b/app/javascript/dashboard/i18n/locale/da/generalSettings.json
index 6fdc73177..6da2cc759 100644
--- a/app/javascript/dashboard/i18n/locale/da/generalSettings.json
+++ b/app/javascript/dashboard/i18n/locale/da/generalSettings.json
@@ -42,7 +42,8 @@
"INBOUND_EMAIL_ENABLED": "Samtale kontinuitet med e-mails er aktiveret for din konto.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "Du kan modtage e-mails på dit brugerdefinerede domæne nu."
}
- }
+ },
+ "UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance."
},
"FORMS": {
"MULTISELECT": {
diff --git a/app/javascript/dashboard/i18n/locale/da/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/da/inboxMgmt.json
index d1bcd2a37..6f49a8b26 100644
--- a/app/javascript/dashboard/i18n/locale/da/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/da/inboxMgmt.json
@@ -241,7 +241,9 @@
"AUTO_ASSIGNMENT": "Aktiver automatisk tildeling",
"INBOX_UPDATE_TITLE": "Indbakke Indstillinger",
"INBOX_UPDATE_SUB_TEXT": "Opdater dine indbakkeindstillinger",
- "AUTO_ASSIGNMENT_SUB_TEXT": "Aktiver eller deaktiver automatisk tildeling af nye samtaler til agenter tilføjet til denne indbakke."
+ "AUTO_ASSIGNMENT_SUB_TEXT": "Aktiver eller deaktiver automatisk tildeling af nye samtaler til agenter tilføjet til denne indbakke.",
+ "HMAC_VERIFICATION": "User Identity Validation",
+ "HMAC_DESCRIPTION": "Inorder validate the users identity, the SDK allows you to pass an `identity_hash` for each user. You can generate HMAC using 'sha256' with the key shown here."
},
"FACEBOOK_REAUTHORIZE": {
"TITLE": "Genautorisér",
diff --git a/app/javascript/dashboard/i18n/locale/da/settings.json b/app/javascript/dashboard/i18n/locale/da/settings.json
index acf2dad20..a5bd70c1f 100644
--- a/app/javascript/dashboard/i18n/locale/da/settings.json
+++ b/app/javascript/dashboard/i18n/locale/da/settings.json
@@ -113,7 +113,7 @@
"SIDEBAR": {
"CONVERSATIONS": "Samtaler",
"REPORTS": "Rapporter",
- "CONTACTS": "Kontakter (Beta)",
+ "CONTACTS": "Kontakter",
"SETTINGS": "Indstillinger",
"HOME": "Hjem",
"AGENTS": "Agenter",
diff --git a/app/javascript/dashboard/i18n/locale/da/signup.json b/app/javascript/dashboard/i18n/locale/da/signup.json
index d877ecfdc..3998d458b 100644
--- a/app/javascript/dashboard/i18n/locale/da/signup.json
+++ b/app/javascript/dashboard/i18n/locale/da/signup.json
@@ -5,13 +5,18 @@
"TERMS_ACCEPT": "Ved at tilmelde dig, accepterer du vores T & C og Privatlivspolitik",
"ACCOUNT_NAME": {
"LABEL": "Kontonavn",
- "PLACEHOLDER": "Wayne Enterprises",
- "ERROR": "Kontonavn er for kort"
+ "PLACEHOLDER": "Enter an account name. eg: Wayne Enterprises",
+ "ERROR": "Account name is too short"
+ },
+ "FULL_NAME": {
+ "LABEL": "Full name",
+ "PLACEHOLDER": "Enter your full name. eg: Bruce Wayne",
+ "ERROR": "Full name is too short"
},
"EMAIL": {
- "LABEL": "E-mail",
- "PLACEHOLDER": "bruce@wayne.enterprises",
- "ERROR": "E-mail er ugyldig"
+ "LABEL": "Work email",
+ "PLACEHOLDER": "Enter your work email address. eg: bruce@wayne.enterprises",
+ "ERROR": "Email address is invalid"
},
"PASSWORD": {
"LABEL": "Adgangskode",
@@ -28,12 +33,6 @@
"ERROR_MESSAGE": "Kunne ikke oprette forbindelse til Woot Server, Prøv igen senere"
},
"SUBMIT": "Send",
- "FEATURES": {
- "UNLIMITED_INBOXES": "Unlimited inboxes",
- "ROBUST_REPORTING": "Robust Reporting",
- "CANNED_RESPONSES": "Standardsvar Svar",
- "AUTO_ASSIGNMENT": "Auto Assignment",
- "SECURITY": "Enterprise level security"
- }
+ "HAVE_AN_ACCOUNT": "Already have an account?"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/de/chatlist.json b/app/javascript/dashboard/i18n/locale/de/chatlist.json
index 0deec4756..086ce1130 100644
--- a/app/javascript/dashboard/i18n/locale/de/chatlist.json
+++ b/app/javascript/dashboard/i18n/locale/de/chatlist.json
@@ -77,8 +77,8 @@
"CONTENT": "hat eine URL geteilt"
}
},
- "RECEIVED_VIA_EMAIL": "Received via email",
- "VIEW_TWEET_IN_TWITTER": "View tweet in Twitter",
- "REPLY_TO_TWEET": "Reply to this tweet"
+ "RECEIVED_VIA_EMAIL": "Per E-Mail empfangen",
+ "VIEW_TWEET_IN_TWITTER": "Tweet auf Twitter anzeigen",
+ "REPLY_TO_TWEET": "Auf diesen Tweet antworten"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/de/contact.json b/app/javascript/dashboard/i18n/locale/de/contact.json
index d8cb5632a..0333afa03 100644
--- a/app/javascript/dashboard/i18n/locale/de/contact.json
+++ b/app/javascript/dashboard/i18n/locale/de/contact.json
@@ -1,113 +1,114 @@
{
"CONTACT_PANEL": {
- "NOT_AVAILABLE": "Not Available",
+ "NOT_AVAILABLE": "Nicht verfügbar",
"EMAIL_ADDRESS": "E-Mail-Addresse",
"PHONE_NUMBER": "Telefonnummer",
- "COPY_SUCCESSFUL": "Copied to clipboard successfully",
- "COMPANY": "Company",
+ "COPY_SUCCESSFUL": "Der Code wurde erfolgreich in die Zwischenablage kopiert",
+ "COMPANY": "Firma",
"LOCATION": "Ort",
"CONVERSATION_TITLE": "Unterhaltungsdetails",
"BROWSER": "Browser",
"OS": "Betriebssystem",
"INITIATED_FROM": "Initiiert von",
"INITIATED_AT": "Initiiert bei",
+ "IP_ADDRESS": "IP-Adresse",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "Es sind keine vorherigen Gespräche mit diesem Kontakt verbunden.",
"TITLE": "Vorherige Gespräche"
},
"CUSTOM_ATTRIBUTES": {
- "TITLE": "Custom Attributes"
+ "TITLE": "Benutzerdefinierte Attribute"
},
"LABELS": {
"TITLE": "Konversationsetiketten",
"MODAL": {
- "TITLE": "Labels for",
- "ACTIVE_LABELS": "Labels added to the conversation",
- "INACTIVE_LABELS": "Labels available in the account",
- "REMOVE": "Click on X icon to remove the label",
- "ADD": "Click on + icon to add the label",
- "UPDATE_BUTTON": "Update labels",
+ "TITLE": "Labels für",
+ "ACTIVE_LABELS": "Labels zur Unterhaltung hinzugefügt",
+ "INACTIVE_LABELS": "Verfügbare Labels im Konto",
+ "REMOVE": "Klicken Sie auf das X-Symbol, um das Label zu entfernen",
+ "ADD": "Klicken Sie auf das + Symbol, um ein Label hinzuzufügen",
+ "UPDATE_BUTTON": "Labels aktualisieren",
"UPDATE_ERROR": "Etiketten konnten nicht aktualisiert werden. Versuchen Sie es erneut."
},
- "NO_LABELS_TO_ADD": "There are no more labels defined in the account.",
- "NO_AVAILABLE_LABELS": "There are no labels added to this conversation."
+ "NO_LABELS_TO_ADD": "Es sind keine weiteren Labels im Konto definiert.",
+ "NO_AVAILABLE_LABELS": "Zu dieser Unterhaltung wurden noch keine Labels hinzugefügt."
},
- "MUTE_CONTACT": "Mute Conversation",
- "UNMUTE_CONTACT": "Unmute Conversation",
- "MUTED_SUCCESS": "This conversation is muted for 6 hours",
- "UNMUTED_SUCCESS": "This conversation is unmuted",
- "SEND_TRANSCRIPT": "Send Transcript",
+ "MUTE_CONTACT": "Unterhaltung stummschalten",
+ "UNMUTE_CONTACT": "Unterhaltung entmuten",
+ "MUTED_SUCCESS": "Diese Unterhaltung ist für 6 Stunden auf stumm schalten",
+ "UNMUTED_SUCCESS": "Diese Unterhaltung ist nicht mehr stumm geschaltet",
+ "SEND_TRANSCRIPT": "Transkript senden",
"EDIT_LABEL": "Bearbeiten"
},
"EDIT_CONTACT": {
- "BUTTON_LABEL": "Edit Contact",
- "TITLE": "Edit contact",
- "DESC": "Edit contact details",
+ "BUTTON_LABEL": "Kontakt bearbeiten",
+ "TITLE": "Kontakt bearbeiten",
+ "DESC": "Kontaktdetails bearbeiten",
"FORM": {
"SUBMIT": "Einreichen",
"CANCEL": "Stornieren",
"AVATAR": {
- "LABEL": "Contact Avatar"
+ "LABEL": "Kontaktbild"
},
"NAME": {
- "PLACEHOLDER": "Enter the full name of the contact",
- "LABEL": "Full Name"
+ "PLACEHOLDER": "Vollständigen Namen des Kontakts eingeben",
+ "LABEL": "Vollständiger Name"
},
"BIO": {
- "PLACEHOLDER": "Enter the bio of the contact",
- "LABEL": "Bio"
+ "PLACEHOLDER": "Beschreibung dieses Kontakts",
+ "LABEL": "Beschreibung"
},
"EMAIL_ADDRESS": {
- "PLACEHOLDER": "Enter the email address of the contact",
+ "PLACEHOLDER": "Geben Sie die E-Mail-Adresse des Kontakts ein",
"LABEL": "E-Mail-Addresse"
},
"PHONE_NUMBER": {
- "PLACEHOLDER": "Enter the phone number of the contact",
- "LABEL": "Phone Number"
+ "PLACEHOLDER": "Geben Sie die Telefonnummer des Kontakts ein",
+ "LABEL": "Telefonnummer"
},
"LOCATION": {
- "PLACEHOLDER": "Enter the location of the contact",
+ "PLACEHOLDER": "Geben Sie den Standort des Kontakts ein",
"LABEL": "Ort"
},
"COMPANY_NAME": {
- "PLACEHOLDER": "Enter the company name",
- "LABEL": "Company Name"
+ "PLACEHOLDER": "Firmenname eingeben",
+ "LABEL": "Firmenname"
},
"SOCIAL_PROFILES": {
"FACEBOOK": {
- "PLACEHOLDER": "Enter the Facebook username",
+ "PLACEHOLDER": "Facebook-Benutzername eingeben",
"LABEL": "Facebook"
},
"TWITTER": {
- "PLACEHOLDER": "Enter the Twitter username",
+ "PLACEHOLDER": "Twitter-Benutzername eingeben",
"LABEL": "Twitter"
},
"LINKEDIN": {
- "PLACEHOLDER": "Enter the LinkedIn username",
+ "PLACEHOLDER": "Geben Sie den LinkedIn-Benutzernamen ein",
"LABEL": "LinkedIn"
},
"GITHUB": {
- "PLACEHOLDER": "Enter the Github username",
+ "PLACEHOLDER": "Gitub-Benutzernamen eingeben",
"LABEL": "Github"
}
}
},
- "SUCCESS_MESSAGE": "Updated contact successfully",
- "CONTACT_ALREADY_EXIST": "This email address is in use for another contact.",
- "ERROR_MESSAGE": "There was an error updating the contact, please try again"
+ "SUCCESS_MESSAGE": "Kontakt erfolgreich aktualisiert",
+ "CONTACT_ALREADY_EXIST": "Diese E-Mail-Adresse wird bereits für einen anderen Kontakt verwendet.",
+ "ERROR_MESSAGE": "Beim Aktualisieren des Kontakts ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut"
},
"CONTACTS_PAGE": {
- "HEADER": "Contacts",
- "SEARCH_BUTTON": "Search",
- "SEARCH_INPUT_PLACEHOLDER": "Search for contacts",
+ "HEADER": "Kontakte",
+ "SEARCH_BUTTON": "Suchen",
+ "SEARCH_INPUT_PLACEHOLDER": "Suche nach Kontakten",
"LIST": {
- "LOADING_MESSAGE": "Loading contacts...",
- "404": "No contacts matches your search 🔍",
+ "LOADING_MESSAGE": "Kontakte werden geladen...",
+ "404": "Keine Kontakte entsprechend Deiner Suche gefunden 🔍",
"TABLE_HEADER": [
"Name",
- "Phone Number",
+ "Telefonnummer",
"Gespräche",
- "Last Contacted"
+ "Letzter Kontakt"
]
}
}
diff --git a/app/javascript/dashboard/i18n/locale/de/conversation.json b/app/javascript/dashboard/i18n/locale/de/conversation.json
index 4e57ce402..7ecd5013f 100644
--- a/app/javascript/dashboard/i18n/locale/de/conversation.json
+++ b/app/javascript/dashboard/i18n/locale/de/conversation.json
@@ -6,24 +6,25 @@
"NO_INBOX_1": "Hallo! Sieht so aus, als hätten Sie noch keine Posteingänge hinzugefügt.",
"NO_INBOX_2": " um loszulegen",
"NO_INBOX_AGENT": "Oh oh! Sieht so aus, als wären Sie nicht Teil eines Posteingangs. Bitte wenden Sie sich an Ihren Administrator",
- "SEARCH_MESSAGES": "Search for messages in conversations",
+ "SEARCH_MESSAGES": "Nachrichten durchsuchen",
"SEARCH": {
- "TITLE": "Search messages",
- "LOADING_MESSAGE": "Crunching data...",
- "PLACEHOLDER": "Type any text to search messages",
- "NO_MATCHING_RESULTS": "There are no messages matching the search parameters."
+ "TITLE": "Nachrichten durchsuchen",
+ "LOADING_MESSAGE": "Daten werden geladen...",
+ "PLACEHOLDER": "Geben Sie einen Text ein, um danach zu suchen",
+ "NO_MATCHING_RESULTS": "Keine passenden Nachrichten gefunden."
},
- "UNREAD_MESSAGES": "Unread Messages",
- "UNREAD_MESSAGE": "Unread Message",
+ "UNREAD_MESSAGES": "Ungelesene Nachrichten",
+ "UNREAD_MESSAGE": "Ungelesene Nachricht",
"CLICK_HERE": "Hier klicken",
"LOADING_INBOXES": "Posteingänge laden",
"LOADING_CONVERSATIONS": "Gespräche laden",
- "CANNOT_REPLY": "You cannot reply due to",
- "24_HOURS_WINDOW": "24 hour message window restriction",
- "LAST_INCOMING_TWEET": "You are replying to the last incoming tweet",
- "REPLYING_TO": "You are replying to:",
- "REMOVE_SELECTION": "Remove Selection",
+ "CANNOT_REPLY": "Du kannst nicht Antworten aufgrund von",
+ "24_HOURS_WINDOW": "24-Stunden-Nachrichtenfenster-Beschränkung",
+ "LAST_INCOMING_TWEET": "Du antwortest auf den letzten eingehenden Tweet",
+ "REPLYING_TO": "Du antwortest auf:",
+ "REMOVE_SELECTION": "Auswahl entfernen",
"DOWNLOAD": "Herunterladen",
+ "UPLOADING_ATTACHMENTS": "Uploading attachments...",
"HEADER": {
"RESOLVE_ACTION": "Fall schließen",
"REOPEN_ACTION": "Wieder öffnen",
@@ -40,31 +41,34 @@
"PRIVATE_NOTE": "Private Notiz",
"SEND": "Senden",
"CREATE": "Notiz hinzufügen",
- "TWEET": "Tweet"
+ "TWEET": "Tweet",
+ "TIP_FORMAT_ICON": "Show rich text editor",
+ "TIP_EMOJI_ICON": "Show emoji selector",
+ "TIP_ATTACH_ICON": "Attach files"
},
"VISIBLE_TO_AGENTS": "Privater Hinweis: Nur für Sie und Ihr Team sichtbar",
"CHANGE_STATUS": "Gesprächsstatus geändert",
"CHANGE_AGENT": "Konversationsempfänger geändert",
- "SENT_BY": "Sent by:",
+ "SENT_BY": "Gesendet von:",
"ASSIGNMENT": {
- "SELECT_AGENT": "Select Agent",
+ "SELECT_AGENT": "Agent auswählen",
"REMOVE": "Entfernen",
- "ASSIGN": "Assign"
+ "ASSIGN": "Zuordnen"
}
},
"EMAIL_TRANSCRIPT": {
- "TITLE": "Send conversation transcript",
- "DESC": "Send a copy of the conversation transcript to the specified email address",
+ "TITLE": "Konversations-Transkript senden",
+ "DESC": "Kopie des Konversationsprotokolls an die angegebene E-Mail-Adresse senden",
"SUBMIT": "Einreichen",
"CANCEL": "Stornieren",
- "SEND_EMAIL_SUCCESS": "The chat transcript was sent successfully",
- "SEND_EMAIL_ERROR": "There was an error, please try again",
+ "SEND_EMAIL_SUCCESS": "Das Chat-Protokoll wurde erfolgreich gesendet",
+ "SEND_EMAIL_ERROR": "Es ist ein Fehler aufgetreten, bitte versuche es erneut",
"FORM": {
- "SEND_TO_CONTACT": "Send the transcript to the customer",
- "SEND_TO_AGENT": "Send the transcript to the assigned agent",
- "SEND_TO_OTHER_EMAIL_ADDRESS": "Send the transcript to another email address",
+ "SEND_TO_CONTACT": "Das Transkript an den Kunden senden",
+ "SEND_TO_AGENT": "Transkript an den zugewiesenen Agent senden",
+ "SEND_TO_OTHER_EMAIL_ADDRESS": "Transkript an eine andere E-Mail-Adresse senden",
"EMAIL": {
- "PLACEHOLDER": "Enter an email address",
+ "PLACEHOLDER": "E-Mail-Adresse eingeben",
"ERROR": "Bitte geben Sie eine gültige E-Mail-Adresse ein"
}
}
diff --git a/app/javascript/dashboard/i18n/locale/de/generalSettings.json b/app/javascript/dashboard/i18n/locale/de/generalSettings.json
index c681da0e6..edd13312b 100644
--- a/app/javascript/dashboard/i18n/locale/de/generalSettings.json
+++ b/app/javascript/dashboard/i18n/locale/de/generalSettings.json
@@ -2,7 +2,7 @@
"GENERAL_SETTINGS": {
"TITLE": "Kontoeinstellungen",
"SUBMIT": "Update Einstellungen",
- "BACK": "Back",
+ "BACK": "Zurück",
"UPDATE": {
"ERROR": "Einstellungen konnten nicht aktualisiert werden, versuchen Sie es erneut!",
"SUCCESS": "Kontoeinstellungen erfolgreich aktualisiert"
@@ -24,31 +24,32 @@
"ERROR": ""
},
"DOMAIN": {
- "LABEL": "Incoming Email Domain",
- "PLACEHOLDER": "The domain where you will receive the emails",
+ "LABEL": "Eingehende E-Mail-Domain",
+ "PLACEHOLDER": "Die Domain, von der E-Mails empfangen werden",
"ERROR": ""
},
"SUPPORT_EMAIL": {
- "LABEL": "Support Email",
- "PLACEHOLDER": "Your company's support email",
+ "LABEL": "Support-E-Mail",
+ "PLACEHOLDER": "Support E-Mail deines Unternehmens",
"ERROR": ""
},
"AUTO_RESOLVE_DURATION": {
- "LABEL": "Number of days after a ticket should auto resolve if there is no activity",
+ "LABEL": "Anzahl der Tage, nach denen ein Ticket automatisch geschlossen wird, wenn keine Aktivität erfolgt",
"PLACEHOLDER": "30",
- "ERROR": "Please enter a valid auto resolve duration (minimum 1 day)"
+ "ERROR": "Bitte gebe eine gültige automatische Auflösungsdauer ein (mindestens 1 Tag)"
},
"FEATURES": {
"INBOUND_EMAIL_ENABLED": "Conversation continuity with emails is enabled for your account.",
- "CUSTOM_EMAIL_DOMAIN_ENABLED": "You can receive emails in your custom domain now."
+ "CUSTOM_EMAIL_DOMAIN_ENABLED": "Du kannst E-Mails jetzt von der festgelegten Domain erhalten."
}
- }
+ },
+ "UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance."
},
"FORMS": {
"MULTISELECT": {
- "ENTER_TO_SELECT": "Press enter to select",
- "ENTER_TO_REMOVE": "Press enter to remove",
- "SELECT_ONE": "Select one"
+ "ENTER_TO_SELECT": "Drücke Enter zum Auswählen",
+ "ENTER_TO_REMOVE": "Drücke Enter zum Entfernen",
+ "SELECT_ONE": "Eine Option wählen"
}
}
}
diff --git a/app/javascript/dashboard/i18n/locale/de/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/de/inboxMgmt.json
index 42924f951..64b8135cc 100644
--- a/app/javascript/dashboard/i18n/locale/de/inboxMgmt.json
+++ b/app/javascript/dashboard/i18n/locale/de/inboxMgmt.json
@@ -1,7 +1,7 @@
{
"INBOX_MGMT": {
"HEADER": "Posteingänge",
- "SIDEBAR_TXT": "
Inbox
When you connect a website or a facebook Page to Chatwoot, it is called an Inbox. You can have unlimited inboxes in your Chatwoot account.
Click on Add Inbox to connect a website or a Facebook Page.
In the Dashboard, you can see all the conversations from all your inboxes in a single place and respond to them under the `Conversations` tab.
You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard.
", + "SIDEBAR_TXT": "Posteingang
Wenn du eine Webseite oder eine Facebook-Seite mit Chatwood verbindest, wird dieser Kanal als Posteingang bezeichnet. Dabei können unbegrenzte viele Posteingänge angelegt werden.
Klicke auf Posteingang hinzufügen, um eine Webseite oder eine Facebook-Seite zu verbinden.
Im Dashboard du kannst alle Unterhaltungen aus allen deinen Posteingängen an einem Ort sehen und unter der Registerkarte \"Unterhaltungen\" beantworten.
Du kannst dir auch nur Konversationen anzeigen lassen, die in einen bestimmten Posteingang enthalten sind, indem du auf den Posteingangsnamen auf der linken Seite des Dashboards klicken.
", "LIST": { "404": "Diesem Konto sind keine Posteingänge zugeordnet." }, @@ -30,12 +30,12 @@ "ADD": { "FB": { "HELP": "PS: Durch die Anmeldung erhalten wir nur Zugriff auf die Nachrichten Ihrer Seite. Auf Ihre privaten Nachrichten kann Chatwoot niemals zugreifen.", - "CHOOSE_PAGE": "Choose Page", - "CHOOSE_PLACEHOLDER": "Select a page from the list", - "INBOX_NAME": "Inbox Name", - "ADD_NAME": "Add a name for your inbox", - "PICK_NAME": "Pick A Name Your Inbox", - "PICK_A_VALUE": "Pick a value" + "CHOOSE_PAGE": "Seite auswählen", + "CHOOSE_PLACEHOLDER": "Wähle eine Seite aus der Liste", + "INBOX_NAME": "Name des Posteingang", + "ADD_NAME": "Namen für diesen Posteingang eingeben", + "PICK_NAME": "Wähle einen Namen für deinen Posteingang", + "PICK_A_VALUE": "Wähle einen Wert" }, "TWITTER": { "HELP": "Um Ihr Twitter-Profil als Kanal hinzuzufügen, müssen Sie Ihr Twitter-Profil authentifizieren, indem Sie auf 'Mit Twitter anmelden' klicken." @@ -43,7 +43,7 @@ "WEBSITE_CHANNEL": { "TITLE": "Website-Kanal", "DESC": "Erstellen Sie einen Kanal für Ihre Website und unterstützen Sie Ihre Kunden über unser Website-Widget.", - "LOADING_MESSAGE": "Creating Website Support Channel", + "LOADING_MESSAGE": "Website-Support-Channel erstellen", "CHANNEL_AVATAR": { "LABEL": "Channel Avatar" }, @@ -52,33 +52,33 @@ "PLACEHOLDER": "Geben Sie den Namen Ihrer Website ein (eg: Acme Inc)" }, "CHANNEL_DOMAIN": { - "LABEL": "Website Domain", + "LABEL": "Website-Domain", "PLACEHOLDER": "Geben Sie Ihre Website-Domain ein (eg: acme.com)" }, "CHANNEL_WELCOME_TITLE": { - "LABEL": "Welcome Heading", - "PLACEHOLDER": "Hi there !" + "LABEL": "Willkommens-Überschrift", + "PLACEHOLDER": "Hallo!" }, "CHANNEL_WELCOME_TAGLINE": { - "LABEL": "Welcome Tagline", - "PLACEHOLDER": "We make it simple to connect with us. Ask us anything, or share your feedback." + "LABEL": "Willkommens-Schlagzeile", + "PLACEHOLDER": "Wir machen es einfach, mit uns in Verbindung zu treten. Fragen Sie uns etwas oder teilen Sie Ihr Feedback." }, "CHANNEL_GREETING_MESSAGE": { - "LABEL": "Channel greeting message", - "PLACEHOLDER": "Acme Inc typically replies in a few hours." + "LABEL": "Grußnachricht des Kanals", + "PLACEHOLDER": "Wir antworten in der Regel in wenigen Stunden." }, "CHANNEL_GREETING_TOGGLE": { - "LABEL": "Enable channel greeting", - "HELP_TEXT": "Send a greeting message to the user when he starts the conversation.", + "LABEL": "Kanal Begrüßung aktivieren", + "HELP_TEXT": "Senden Sie eine Grußnachricht an den Benutzer, wenn er die Unterhaltung beginnt.", "ENABLED": "Aktiviert", "DISABLED": "Behindert" }, "REPLY_TIME": { "TITLE": "Reaktionszeit festlegen", - "IN_A_FEW_MINUTES": "In a few minutes", - "IN_A_FEW_HOURS": "In a few hours", - "IN_A_DAY": "In a day", - "HELP_TEXT": "This reply time will be displayed on the live chat widget" + "IN_A_FEW_MINUTES": "Innerhalb weniger Minuten", + "IN_A_FEW_HOURS": "Innerhalb weniger Stunden", + "IN_A_DAY": "Innerhalb eines Tages", + "HELP_TEXT": "Diese Antwortzeit wird im Live-Chat-Widget angezeigt" }, "WIDGET_COLOR": { "LABEL": "Widget Farbe", @@ -87,7 +87,7 @@ "SUBMIT_BUTTON": "Posteingang erstellen" }, "TWILIO": { - "TITLE": "Twilio SMS/Whatsapp Channel", + "TITLE": "Twilio SMS/Whatsapp Kanal", "DESC": "Integrieren Sie Twilio und unterstützen Sie Ihre Kunden per SMS/Whatsapp.", "ACCOUNT_SID": { "LABEL": "Account SID", @@ -95,11 +95,11 @@ "ERROR": "Dieses Feld wird benötigt" }, "CHANNEL_TYPE": { - "LABEL": "Channel Type", - "ERROR": "Please select your Channel Type" + "LABEL": "Kanal-Typ", + "ERROR": "Bitte wählen Sie den Kanal-Typ aus" }, "AUTH_TOKEN": { - "LABEL": "Auth Token", + "LABEL": "Auth-Token", "PLACEHOLDER": "Bitte geben Sie Ihr Twilio Auth Token ein", "ERROR": "Dieses Feld wird benötigt" }, @@ -115,7 +115,7 @@ }, "API_CALLBACK": { "TITLE": "Callback URL", - "SUBTITLE": "You have to configure the message callback URL in Twilio with the URL mentioned here." + "SUBTITLE": "Sie müssen die Callback-URL in Twilio mit der hier genannten URL konfigurieren." }, "SUBMIT_BUTTON": "Erstellen Sie Twilio Channel", "API": { @@ -123,8 +123,8 @@ } }, "API_CHANNEL": { - "TITLE": "API Channel", - "DESC": "Integrate with API channel and start supporting your customers.", + "TITLE": "API-Kanal", + "DESC": "Integrieren Sie einen API-Kanal und starten Sie mit der Unterstützung Ihrer Kunden.", "CHANNEL_NAME": { "LABEL": "Kanal Name", "PLACEHOLDER": "Bitte geben Sie einen Kanalnamen ein", @@ -132,32 +132,32 @@ }, "WEBHOOK_URL": { "LABEL": "Webhook-URL", - "SUBTITLE": "Configure the URL where you want to recieve callbacks on events.", + "SUBTITLE": "Konfigurieren Sie die URL, auf der Sie Callbacks bei Events erhalten möchten.", "PLACEHOLDER": "Webhook-URL" }, - "SUBMIT_BUTTON": "Create API Channel", + "SUBMIT_BUTTON": "API-Kanal erstellen", "API": { - "ERROR_MESSAGE": "We were not able to save the api channel" + "ERROR_MESSAGE": "Der API-Kanal konnte nicht gespeichert werden" } }, "EMAIL_CHANNEL": { - "TITLE": "Email Channel", - "DESC": "Integrate you email inbox.", + "TITLE": "E-Mail-Kanal", + "DESC": "Integrieren Sie Ihren Posteingang.", "CHANNEL_NAME": { "LABEL": "Kanal Name", "PLACEHOLDER": "Bitte geben Sie einen Kanalnamen ein", "ERROR": "Dieses Feld wird benötigt" }, "EMAIL": { - "LABEL": "Email", - "SUBTITLE": "Email where your customers sends you support tickets", - "PLACEHOLDER": "Email" + "LABEL": "E-Mail", + "SUBTITLE": "E-Mail Adresse, an die Ihre Kunden Ihnen Support-Tickets senden", + "PLACEHOLDER": "E-Mail" }, - "SUBMIT_BUTTON": "Create Email Channel", + "SUBMIT_BUTTON": "E-Mail-Kanal erstellen", "API": { - "ERROR_MESSAGE": "We were not able to save the email channel" + "ERROR_MESSAGE": "Wir konnten den E-Mail-Kanal nicht speichern" }, - "FINISH_MESSAGE": "Start forwarding your emails to the following email address." + "FINISH_MESSAGE": "Starten Sie die Weiterleitung Ihrer E-Mails an die folgende E-Mail-Adresse." }, "AUTH": { "TITLE": "Kanäle", @@ -166,8 +166,8 @@ "AGENTS": { "TITLE": "Agenten", "DESC": "Hier können Sie Agenten hinzufügen, um Ihren neu erstellten Posteingang zu verwalten. Nur diese ausgewählten Agenten haben Zugriff auf Ihren Posteingang. Agenten, die nicht Teil dieses Posteingangs sind, können bei der Anmeldung keine Nachrichten in diesem Posteingang sehen oder darauf antworten.Agents
An Agent is a member of your Customer Support team.
Agents will be able to view and reply to messages from your users. The list shows all agents currently in your account.
Click on Add Agent to add a new agent. Agent you add will receive an email with a confirmation link to activate their account, after which they can access Chatwoot and respond to messages.
Access to Chatwoot's features are based on following roles.
Agent - Agents with this role can only access inboxes, reports and conversations. They can assign conversations to other agents or themselves and resolve conversations.
Administrator - Administrator will have access to all Chatwoot features enabled for your account, including settings, along with all of a normal agents' privileges.
", + "SIDEBAR_TXT": "Agenter
En Agent är medlem i ditt kundsupportteam.
Agenter kommer att kunna se och svara på meddelanden från dina användare. Listan visar alla agenter som finns på ditt konto.
Klicka på Lägg till agent för att lägga till en ny agent. Agenter du lägger till kommer att få ett e-postmeddelande med en bekräftelselänk för att aktivera sitt konto, vartefter de kan komma åt Chatwoot och svara på meddelanden.
Åtkomst till Chatwoots funktioner baseras på följande roller:
Agent - Agenter med denna roll kan endast komma åt inkorgar, rapporter och konversationer. De kan tilldela konversationer till andra agenter eller sig själva och lösa konversationer.
Administratör - Administratörer kommer att ha tillgång till alla Chatwoot-funktioner som är aktiverade för ditt konto, inklusive inställningar, tillsammans med alla normala agenters privilegier.
", "AGENT_TYPES": { "ADMINISTRATOR": "Administratör", - "AGENT": "Agentkommando" + "AGENT": "Agent" }, "LIST": { "404": "Det finns inga agenter kopplade till detta konto", @@ -29,33 +29,33 @@ "PLACEHOLDER": "Ange ett namn på agenten" }, "AGENT_TYPE": { - "LABEL": "Agentkommando typ", + "LABEL": "Roll", "PLACEHOLDER": "Välj en typ", - "ERROR": "Agentkommando krävs" + "ERROR": "Roll krävs" }, "EMAIL": { "LABEL": "E-postadress", "PLACEHOLDER": "Ange en e-postadress till agenten" }, - "SUBMIT": "Lägg till agentur" + "SUBMIT": "Lägg till agent" }, "API": { - "SUCCESS_MESSAGE": "Agentkommando har lagts till", - "EXIST_MESSAGE": "Agentkommando redan använt, försök med en annan e-postadress", + "SUCCESS_MESSAGE": "Agenten har lagts till", + "EXIST_MESSAGE": "E-postadressen används redan, försök med en annan e-postadress", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" } }, "DELETE": { "BUTTON_TEXT": "Radera", "API": { - "SUCCESS_MESSAGE": "Agentkommando har tagits bort", + "SUCCESS_MESSAGE": "Agenten har tagits bort", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" }, "CONFIRM": { "TITLE": "Bekräfta borttagning", "MESSAGE": "Är du säker på att ta bort ", "YES": "Ja, ta bort ", - "NO": "No, Keep " + "NO": "Nej, behåll " } }, "EDIT": { @@ -66,9 +66,9 @@ "PLACEHOLDER": "Ange ett namn på agenten" }, "AGENT_TYPE": { - "LABEL": "Agentkommando typ", + "LABEL": "Roll", "PLACEHOLDER": "Välj en typ", - "ERROR": "Agentkommando krävs" + "ERROR": "Roll krävs" }, "EMAIL": { "LABEL": "E-postadress", @@ -79,13 +79,13 @@ "BUTTON_TEXT": "Redigera", "CANCEL_BUTTON_TEXT": "Avbryt", "API": { - "SUCCESS_MESSAGE": "Agentkommando uppdaterades", + "SUCCESS_MESSAGE": "Agenten uppdaterad", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" }, "PASSWORD_RESET": { "ADMIN_RESET_BUTTON": "Återställ lösenord", "ADMIN_SUCCESS_MESSAGE": "Ett e-postmeddelande med instruktioner för att återställa lösenordet har skickats till agenten", - "SUCCESS_MESSAGE": "Agentkommando återställs framgångsrikt", + "SUCCESS_MESSAGE": "Agentlösenordet återställt", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" } }, diff --git a/app/javascript/dashboard/i18n/locale/sv/cannedMgmt.json b/app/javascript/dashboard/i18n/locale/sv/cannedMgmt.json index bf4805924..5746b86e0 100644 --- a/app/javascript/dashboard/i18n/locale/sv/cannedMgmt.json +++ b/app/javascript/dashboard/i18n/locale/sv/cannedMgmt.json @@ -1,29 +1,29 @@ { "CANNED_MGMT": { - "HEADER": "Konserverade svar", - "HEADER_BTN_TXT": "Lägg till konserverat svar", - "LOADING": "Hämtar konserverade svar", + "HEADER": "Svarsmallar", + "HEADER_BTN_TXT": "Lägg till svarsmall", + "LOADING": "Hämtar svarsmallar", "SEARCH_404": "Det finns inga objekt som matchar denna fråga", - "SIDEBAR_TXT": "Konserverade svar
Konserverade svar sparas svarsmallar som kan användas för att snabbt skicka ett svar till en konversation.
För att skapa ett konserverat svar, klicka bara på Add Canned Response. Du kan också redigera eller ta bort ett befintligt konserverat svar genom att klicka på knappen Redigera eller Ta bort
Konserverade svar används med hjälp av Korta koder. Agenter kan komma åt konserverade svar medan de är på en chatt genom att skriva '/' följt av kortkoden.
", + "SIDEBAR_TXT": "Svarsmallar
Svarsmallar är sparade mallar som kan användas för att snabbt skicka ett svar till en konversation.
För att skapa en svarsmall, klicka bara på Lägg till svarsmall. Du kan också redigera eller ta bort en befintlig svarsmall genom att klicka på knapparna Redigera eller Ta bort
Svarsmallar används med hjälp av korta koder. Agenter kan komma åt svarsmallar medan de är på en chatt genom att skriva '/' följt av kortkoden.
", "LIST": { - "404": "Det finns inga konserverade svar tillgängliga på detta konto.", - "TITLE": "Hantera konserverade svar", - "DESC": "Konserverade svar är fördefinierade svarsmallar som kan användas för att snabbt skicka ut svar till ärenden.", + "404": "Det finns inga svarsmallar tillgängliga på detta konto.", + "TITLE": "Hantera svarsmallar", + "DESC": "Svarsmallar är fördefinierade mallar som kan användas för att snabbt skicka ut svar till ärenden.", "TABLE_HEADER": [ - "Kort kod", + "Kortkod", "Innehåll", "Åtgärder" ] }, "ADD": { - "TITLE": "Lägg till konserverat svar", - "DESC": "Konserverade svar sparas svarsmallar som kan användas för att snabbt skicka svar till konversation.", + "TITLE": "Lägg till svarsmall", + "DESC": "Svarsmallar är fördefinierade mallar som kan användas för att snabbt skicka ut svar till konversationer.", "CANCEL_BUTTON_TEXT": "Avbryt", "FORM": { "SHORT_CODE": { - "LABEL": "Kort kod", + "LABEL": "Kortkod", "PLACEHOLDER": "Ange en kortkod", - "ERROR": "Kort kod krävs" + "ERROR": "Kortkod krävs" }, "CONTENT": { "LABEL": "Innehåll", @@ -33,18 +33,18 @@ "SUBMIT": "Skicka" }, "API": { - "SUCCESS_MESSAGE": "Konserverat svar har lagts till", + "SUCCESS_MESSAGE": "Svarsmallen har lagts till", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" } }, "EDIT": { - "TITLE": "Redigera konserverat svar", + "TITLE": "Redigera svarsmall", "CANCEL_BUTTON_TEXT": "Avbryt", "FORM": { "SHORT_CODE": { - "LABEL": "Kort kod", + "LABEL": "Kortkod", "PLACEHOLDER": "Ange en kortkod", - "ERROR": "Kort kod krävs" + "ERROR": "Kortkod krävs" }, "CONTENT": { "LABEL": "Innehåll", @@ -55,21 +55,21 @@ }, "BUTTON_TEXT": "Redigera", "API": { - "SUCCESS_MESSAGE": "Konserverat svar har uppdaterats", + "SUCCESS_MESSAGE": "Svarsmallen har uppdaterats", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" } }, "DELETE": { "BUTTON_TEXT": "Radera", "API": { - "SUCCESS_MESSAGE": "Konserverat svar har tagits bort", + "SUCCESS_MESSAGE": "Svarsmallen har tagits bort", "ERROR_MESSAGE": "Kunde inte ansluta till Woot Server, försök igen senare" }, "CONFIRM": { "TITLE": "Bekräfta borttagning", "MESSAGE": "Är du säker på att ta bort ", "YES": "Ja, ta bort ", - "NO": "No, Keep " + "NO": "Nej, behåll " } } } diff --git a/app/javascript/dashboard/i18n/locale/sv/chatlist.json b/app/javascript/dashboard/i18n/locale/sv/chatlist.json index 52328cf60..fb1981fa7 100644 --- a/app/javascript/dashboard/i18n/locale/sv/chatlist.json +++ b/app/javascript/dashboard/i18n/locale/sv/chatlist.json @@ -4,7 +4,7 @@ "LOAD_MORE_CONVERSATIONS": "Ladda fler konversationer", "EOF": "Alla konversationer laddade 🎉", "LIST": { - "404": "Det finns inga aktiva samtal i denna grupp." + "404": "Det finns inga aktiva konversationer i denna grupp." }, "TAB_HEADING": "Konversationer", "SEARCH": { @@ -22,12 +22,12 @@ ], "ASSIGNEE_TYPE_TABS": [ { - "NAME": "Gruva", + "NAME": "Mina", "KEY": "me", "COUNT_KEY": "mineCount" }, { - "NAME": "Otilldelad", + "NAME": "Otilldelade", "KEY": "unassigned", "COUNT_KEY": "unAssignedCount" }, @@ -43,7 +43,7 @@ "VALUE": "open" }, { - "TEXT": "Löst", + "TEXT": "Lösta", "VALUE": "resolved" }, { @@ -54,11 +54,11 @@ "ATTACHMENTS": { "image": { "ICON": "ion-image", - "CONTENT": "Meddelande om bild" + "CONTENT": "Bildmeddelande" }, "audio": { "ICON": "ion-volume-high", - "CONTENT": "Ljud meddelande" + "CONTENT": "Ljudmeddelande" }, "video": { "ICON": "ion-ios-videocam", @@ -77,8 +77,8 @@ "CONTENT": "har delat en webbadress" } }, - "RECEIVED_VIA_EMAIL": "Received via email", - "VIEW_TWEET_IN_TWITTER": "View tweet in Twitter", - "REPLY_TO_TWEET": "Reply to this tweet" + "RECEIVED_VIA_EMAIL": "Mottaget via e-post", + "VIEW_TWEET_IN_TWITTER": "Visa tweet i Twitter", + "REPLY_TO_TWEET": "Svara på detta tweet" } } diff --git a/app/javascript/dashboard/i18n/locale/sv/contact.json b/app/javascript/dashboard/i18n/locale/sv/contact.json index 3c7eae9c2..2898e0f50 100644 --- a/app/javascript/dashboard/i18n/locale/sv/contact.json +++ b/app/javascript/dashboard/i18n/locale/sv/contact.json @@ -1,113 +1,114 @@ { "CONTACT_PANEL": { - "NOT_AVAILABLE": "Not Available", + "NOT_AVAILABLE": "Ej tillgänglig", "EMAIL_ADDRESS": "E-postadress", "PHONE_NUMBER": "Telefonnummer", - "COPY_SUCCESSFUL": "Copied to clipboard successfully", - "COMPANY": "Company", + "COPY_SUCCESSFUL": "Kopierat till urklipp", + "COMPANY": "Företag", "LOCATION": "Plats", "CONVERSATION_TITLE": "Konversation Detaljer", "BROWSER": "Webbläsare", "OS": "Operativsystem", "INITIATED_FROM": "Initierad från", "INITIATED_AT": "Initierad den", + "IP_ADDRESS": "IP-adress", "CONVERSATIONS": { "NO_RECORDS_FOUND": "Det finns inga tidigare konversationer kopplade till denna kontakt.", "TITLE": "Tidigare konversationer" }, "CUSTOM_ATTRIBUTES": { - "TITLE": "Custom Attributes" + "TITLE": "Egna egenskaper" }, "LABELS": { "TITLE": "Etiketter för konversation", "MODAL": { - "TITLE": "Labels for", - "ACTIVE_LABELS": "Labels added to the conversation", - "INACTIVE_LABELS": "Labels available in the account", - "REMOVE": "Click on X icon to remove the label", - "ADD": "Click on + icon to add the label", - "UPDATE_BUTTON": "Update labels", - "UPDATE_ERROR": "Couldn't update labels, try again." + "TITLE": "Etiketter för", + "ACTIVE_LABELS": "Etiketter tillagda till konversationen", + "INACTIVE_LABELS": "Etiketter tillgängliga på kontot", + "REMOVE": "Klicka på X-ikonen för att ta bort etiketten", + "ADD": "Klicka på + ikonen för att lägga till etiketten", + "UPDATE_BUTTON": "Uppdatera etiketter", + "UPDATE_ERROR": "Kunde inte uppdatera etiketter, försök igen." }, - "NO_LABELS_TO_ADD": "There are no more labels defined in the account.", - "NO_AVAILABLE_LABELS": "There are no labels added to this conversation." + "NO_LABELS_TO_ADD": "Det finns inga fler etiketter definierade på kontot.", + "NO_AVAILABLE_LABELS": "Det finns inga etiketter tillagda till denna konversation." }, - "MUTE_CONTACT": "Mute Conversation", - "UNMUTE_CONTACT": "Unmute Conversation", - "MUTED_SUCCESS": "This conversation is muted for 6 hours", - "UNMUTED_SUCCESS": "This conversation is unmuted", - "SEND_TRANSCRIPT": "Send Transcript", + "MUTE_CONTACT": "Tysta konversation", + "UNMUTE_CONTACT": "Avtysta konversation", + "MUTED_SUCCESS": "Denna konversation är tystad i 6 timmar", + "UNMUTED_SUCCESS": "Denna konversation är avtystad", + "SEND_TRANSCRIPT": "Skicka transkribering", "EDIT_LABEL": "Redigera" }, "EDIT_CONTACT": { - "BUTTON_LABEL": "Edit Contact", - "TITLE": "Edit contact", - "DESC": "Edit contact details", + "BUTTON_LABEL": "Redigera kontakt", + "TITLE": "Redigera kontakt", + "DESC": "Redigera kontaktuppgifter", "FORM": { "SUBMIT": "Skicka", "CANCEL": "Avbryt", "AVATAR": { - "LABEL": "Contact Avatar" + "LABEL": "Kontaktavatar" }, "NAME": { - "PLACEHOLDER": "Enter the full name of the contact", - "LABEL": "Full Name" + "PLACEHOLDER": "Ange det fullständiga namnet för kontakten", + "LABEL": "Fullständigt namn" }, "BIO": { - "PLACEHOLDER": "Enter the bio of the contact", - "LABEL": "Bio" + "PLACEHOLDER": "Ange biografi för kontakten", + "LABEL": "Biografi" }, "EMAIL_ADDRESS": { - "PLACEHOLDER": "Enter the email address of the contact", + "PLACEHOLDER": "Ange e-postadressen till kontakten", "LABEL": "E-postadress" }, "PHONE_NUMBER": { - "PLACEHOLDER": "Enter the phone number of the contact", - "LABEL": "Phone Number" + "PLACEHOLDER": "Ange telefonnummer till kontakten", + "LABEL": "Telefonnummer" }, "LOCATION": { - "PLACEHOLDER": "Enter the location of the contact", + "PLACEHOLDER": "Ange platsen för kontakten", "LABEL": "Plats" }, "COMPANY_NAME": { - "PLACEHOLDER": "Enter the company name", - "LABEL": "Company Name" + "PLACEHOLDER": "Ange företagets namn", + "LABEL": "Företagsnamn" }, "SOCIAL_PROFILES": { "FACEBOOK": { - "PLACEHOLDER": "Enter the Facebook username", + "PLACEHOLDER": "Ange Facebook-användarnamn", "LABEL": "Facebook" }, "TWITTER": { - "PLACEHOLDER": "Enter the Twitter username", + "PLACEHOLDER": "Ange Twitter-användarnamn", "LABEL": "Twitter" }, "LINKEDIN": { - "PLACEHOLDER": "Enter the LinkedIn username", + "PLACEHOLDER": "Ange LinkedIn-användarnamn", "LABEL": "LinkedIn" }, "GITHUB": { - "PLACEHOLDER": "Enter the Github username", + "PLACEHOLDER": "Ange Github-användarnamn", "LABEL": "Github" } } }, - "SUCCESS_MESSAGE": "Updated contact successfully", - "CONTACT_ALREADY_EXIST": "This email address is in use for another contact.", - "ERROR_MESSAGE": "There was an error updating the contact, please try again" + "SUCCESS_MESSAGE": "Kontakten har uppdaterats", + "CONTACT_ALREADY_EXIST": "Den här e-postadressen används för en annan kontakt.", + "ERROR_MESSAGE": "Ett fel uppstod vid uppdateringen av kontakten, vänligen försök igen" }, "CONTACTS_PAGE": { - "HEADER": "Contacts", - "SEARCH_BUTTON": "Search", - "SEARCH_INPUT_PLACEHOLDER": "Search for contacts", + "HEADER": "Kontakter", + "SEARCH_BUTTON": "Sök", + "SEARCH_INPUT_PLACEHOLDER": "Sök kontakter", "LIST": { - "LOADING_MESSAGE": "Loading contacts...", - "404": "No contacts matches your search 🔍", + "LOADING_MESSAGE": "Laddar kontakter...", + "404": "Inga kontakter matchar din sökning 🔍", "TABLE_HEADER": [ "Namn", - "Phone Number", + "Telefonnummer", "Konversationer", - "Last Contacted" + "Senast kontaktad" ] } } diff --git a/app/javascript/dashboard/i18n/locale/sv/conversation.json b/app/javascript/dashboard/i18n/locale/sv/conversation.json index aaf3cf8c8..3914f4a3e 100644 --- a/app/javascript/dashboard/i18n/locale/sv/conversation.json +++ b/app/javascript/dashboard/i18n/locale/sv/conversation.json @@ -4,26 +4,27 @@ "NO_MESSAGE_1": "Oj då! Det ser ut som att det inte finns några meddelanden från kunder i din inkorg.", "NO_MESSAGE_2": " för att skicka ett meddelande till din sida!", "NO_INBOX_1": "Hola! Ser ut som om du inte har lagt till några inkorgar än.", - "NO_INBOX_2": " att komma igång", + "NO_INBOX_2": " för att komma igång", "NO_INBOX_AGENT": "Oh Oh! Ser ut som om du inte är en del av någon inkorg. Kontakta administratören", - "SEARCH_MESSAGES": "Search for messages in conversations", + "SEARCH_MESSAGES": "Sök meddelanden i konversationer", "SEARCH": { - "TITLE": "Search messages", - "LOADING_MESSAGE": "Crunching data...", - "PLACEHOLDER": "Type any text to search messages", - "NO_MATCHING_RESULTS": "There are no messages matching the search parameters." + "TITLE": "Sök meddelanden", + "LOADING_MESSAGE": "Tuggar data...", + "PLACEHOLDER": "Skriv valfri text för att söka efter meddelanden", + "NO_MATCHING_RESULTS": "Det finns inga meddelanden som motsvarar sökparametrarna." }, - "UNREAD_MESSAGES": "Unread Messages", - "UNREAD_MESSAGE": "Unread Message", + "UNREAD_MESSAGES": "Olästa meddelanden", + "UNREAD_MESSAGE": "Oläst meddelande", "CLICK_HERE": "Klicka här", "LOADING_INBOXES": "Laddar inkorgar", "LOADING_CONVERSATIONS": "Laddar konversationer", - "CANNOT_REPLY": "You cannot reply due to", - "24_HOURS_WINDOW": "24 hour message window restriction", - "LAST_INCOMING_TWEET": "You are replying to the last incoming tweet", - "REPLYING_TO": "You are replying to:", - "REMOVE_SELECTION": "Remove Selection", + "CANNOT_REPLY": "Du kan inte svara på grund av", + "24_HOURS_WINDOW": "24 timmars meddelandebegränsning", + "LAST_INCOMING_TWEET": "Du svarar på den senast inkomna tweeten", + "REPLYING_TO": "Du svarar:", + "REMOVE_SELECTION": "Ta bort urval", "DOWNLOAD": "Hämta", + "UPLOADING_ATTACHMENTS": "Laddar upp bilagor...", "HEADER": { "RESOLVE_ACTION": "Lös", "REOPEN_ACTION": "Återöppna", @@ -32,39 +33,42 @@ "DETAILS": "detaljer" }, "FOOTER": { - "MSG_INPUT": "Skift + ange för ny rad. Börja med '/' för att välja ett konserverat svar.", - "PRIVATE_MSG_INPUT": "Skift + ange för ny rad. Detta kommer endast att vara synligt för agenter" + "MSG_INPUT": "Skift + Enter för ny rad. Börja med '/' för att välja en svarsmall.", + "PRIVATE_MSG_INPUT": "Skift + Enter för ny rad. Detta kommer endast att vara synligt för agenter" }, "REPLYBOX": { "REPLY": "Svara", "PRIVATE_NOTE": "Privat anteckning", "SEND": "Skicka", "CREATE": "Lägg till anteckning", - "TWEET": "Twittra" + "TWEET": "Twittra", + "TIP_FORMAT_ICON": "Show rich text editor", + "TIP_EMOJI_ICON": "Show emoji selector", + "TIP_ATTACH_ICON": "Attach files" }, - "VISIBLE_TO_AGENTS": "Privat Obs: Endast synlig för dig och ditt team", - "CHANGE_STATUS": "Konversation status ändrad", - "CHANGE_AGENT": "Konversation förvärvaren ändrad", - "SENT_BY": "Sent by:", + "VISIBLE_TO_AGENTS": "Privat anteckning: Endast synlig för dig och ditt team", + "CHANGE_STATUS": "Konversationsstatus ändrad", + "CHANGE_AGENT": "Konversationstilldelning ändrad", + "SENT_BY": "Skickat av:", "ASSIGNMENT": { - "SELECT_AGENT": "Select Agent", + "SELECT_AGENT": "Välj agent", "REMOVE": "Radera", - "ASSIGN": "Assign" + "ASSIGN": "Tilldela" } }, "EMAIL_TRANSCRIPT": { - "TITLE": "Send conversation transcript", - "DESC": "Send a copy of the conversation transcript to the specified email address", + "TITLE": "Skicka konversationstranskribering", + "DESC": "Skicka en kopia av konversationstranskriberingen till den angivna e-postadressen", "SUBMIT": "Skicka", "CANCEL": "Avbryt", - "SEND_EMAIL_SUCCESS": "The chat transcript was sent successfully", - "SEND_EMAIL_ERROR": "There was an error, please try again", + "SEND_EMAIL_SUCCESS": "Chattranskriberingen har skickats", + "SEND_EMAIL_ERROR": "Ett fel uppstod, vänligen försök igen", "FORM": { - "SEND_TO_CONTACT": "Send the transcript to the customer", - "SEND_TO_AGENT": "Send the transcript to the assigned agent", - "SEND_TO_OTHER_EMAIL_ADDRESS": "Send the transcript to another email address", + "SEND_TO_CONTACT": "Skicka transkriberingen till kunden", + "SEND_TO_AGENT": "Skicka transkriberingen till den tilldelade agenten", + "SEND_TO_OTHER_EMAIL_ADDRESS": "Skicka transkriberingen till annan epost-adress", "EMAIL": { - "PLACEHOLDER": "Enter an email address", + "PLACEHOLDER": "Ange en e-postadress", "ERROR": "Ange en giltig e-postadress" } } diff --git a/app/javascript/dashboard/i18n/locale/sv/generalSettings.json b/app/javascript/dashboard/i18n/locale/sv/generalSettings.json index 5843d1a28..9412ab970 100644 --- a/app/javascript/dashboard/i18n/locale/sv/generalSettings.json +++ b/app/javascript/dashboard/i18n/locale/sv/generalSettings.json @@ -2,7 +2,7 @@ "GENERAL_SETTINGS": { "TITLE": "Kontoinställningar", "SUBMIT": "Uppdatera inställningar", - "BACK": "Back", + "BACK": "Tillbaka", "UPDATE": { "ERROR": "Kunde inte uppdatera inställningar, försök igen!", "SUCCESS": "Uppdaterade kontoinställningar" @@ -14,7 +14,7 @@ "NOTE": "" }, "NAME": { - "LABEL": "Konto namn", + "LABEL": "Kontonamn", "PLACEHOLDER": "Ditt kontonamn", "ERROR": "Ange ett giltigt kontonamn" }, @@ -24,31 +24,32 @@ "ERROR": "" }, "DOMAIN": { - "LABEL": "Incoming Email Domain", - "PLACEHOLDER": "The domain where you will receive the emails", + "LABEL": "Inkommande e-postdomän", + "PLACEHOLDER": "Domänen du tar emot e-post på", "ERROR": "" }, "SUPPORT_EMAIL": { - "LABEL": "Support Email", - "PLACEHOLDER": "Your company's support email", + "LABEL": "Supportmejl", + "PLACEHOLDER": "Ditt företags supportmejl", "ERROR": "" }, "AUTO_RESOLVE_DURATION": { - "LABEL": "Number of days after a ticket should auto resolve if there is no activity", + "LABEL": "Antal dagar till ett ärende ska automatlösas på grund av inaktivitet", "PLACEHOLDER": "30", - "ERROR": "Please enter a valid auto resolve duration (minimum 1 day)" + "ERROR": "Ange en giltig tid för automatlösning (minst 1 dag)" }, "FEATURES": { - "INBOUND_EMAIL_ENABLED": "Conversation continuity with emails is enabled for your account.", - "CUSTOM_EMAIL_DOMAIN_ENABLED": "You can receive emails in your custom domain now." + "INBOUND_EMAIL_ENABLED": "Konversationskontinuitet med e-post är aktiverat för ditt konto.", + "CUSTOM_EMAIL_DOMAIN_ENABLED": "Du kan nu ta emot e-postmeddelanden i din egna domän." } - } + }, + "UPDATE_CHATWOOT": "En uppdatering %{latestChatwootVersion} för Chatwoot är tillgänglig. Vänligen uppdatera din instans." }, "FORMS": { "MULTISELECT": { - "ENTER_TO_SELECT": "Press enter to select", - "ENTER_TO_REMOVE": "Press enter to remove", - "SELECT_ONE": "Select one" + "ENTER_TO_SELECT": "Tryck Enter för att välja", + "ENTER_TO_REMOVE": "Tryck Enter för att ta bort", + "SELECT_ONE": "Markera en/ett" } } } diff --git a/app/javascript/dashboard/i18n/locale/sv/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/sv/inboxMgmt.json index ad7b1dab6..586c7f71c 100644 --- a/app/javascript/dashboard/i18n/locale/sv/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/sv/inboxMgmt.json @@ -1,7 +1,7 @@ { "INBOX_MGMT": { "HEADER": "Inkorgar", - "SIDEBAR_TXT": "Inbox
When you connect a website or a facebook Page to Chatwoot, it is called an Inbox. You can have unlimited inboxes in your Chatwoot account.
Click on Add Inbox to connect a website or a Facebook Page.
In the Dashboard, you can see all the conversations from all your inboxes in a single place and respond to them under the `Conversations` tab.
You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard.
", + "SIDEBAR_TXT": "Inkorg
När du ansluter en webbplats eller en Facebook-sida till Chatwoot, så kallas det för en Inkorg. Du kan ha obegränsad mängd inkorgar i ditt Chatwoot-konto.
Klicka på Lägg till inkorg för att ansluta en webbplats eller en Facebook-sida.
I instrumentpanelen kan du se alla konversationer från alla dina inkorgar på en enda plats och svara på dem under fliken \"Konversationer\".
Du kan också se konversationer specifika för en inkorg genom att klicka på inkorgnamnet i den vänstra rutan på instrumentbrädan.
", "LIST": { "404": "Det finns inga inkorgar kopplade till detta konto." }, @@ -24,18 +24,18 @@ { "title": "Voila!", "route": "settings_inbox_finish", - "body": "Ni är alla redo att gå!" + "body": "Ni är redo att köra!" } ], "ADD": { "FB": { - "HELP": "PS: Genom att logga in får vi bara tillgång till din Sidas meddelanden. Dina privata meddelanden kan aldrig nås av Chatwoot.", - "CHOOSE_PAGE": "Choose Page", - "CHOOSE_PLACEHOLDER": "Select a page from the list", - "INBOX_NAME": "Inbox Name", - "ADD_NAME": "Add a name for your inbox", - "PICK_NAME": "Pick A Name Your Inbox", - "PICK_A_VALUE": "Pick a value" + "HELP": "PS: Genom att logga in får vi bara tillgång till din sidas meddelanden. Dina privata meddelanden kan aldrig nås av Chatwoot.", + "CHOOSE_PAGE": "Välj sida", + "CHOOSE_PLACEHOLDER": "Välj en sida från listan", + "INBOX_NAME": "Inkorgsnamn", + "ADD_NAME": "Lägg till ett namn för din inkorg", + "PICK_NAME": "Välj ett namn på din inkorg", + "PICK_A_VALUE": "Välj ett värde" }, "TWITTER": { "HELP": "För att lägga till din Twitter-profil som en kanal måste du autentisera din Twitter-profil genom att klicka på \"Logga in med Twitter\" " @@ -45,7 +45,7 @@ "DESC": "Skapa en kanal för din webbplats och börja stödja dina kunder via vår hemsida widget.", "LOADING_MESSAGE": "Skapar supportkanal för webbplats", "CHANNEL_AVATAR": { - "LABEL": "Channel Avatar" + "LABEL": "Kanalavatar" }, "CHANNEL_NAME": { "LABEL": "Webbplatsens namn", @@ -60,25 +60,25 @@ "PLACEHOLDER": "Hej där!" }, "CHANNEL_WELCOME_TAGLINE": { - "LABEL": "Välkommen Tagline", + "LABEL": "Välkomsttagline", "PLACEHOLDER": "Vi gör det enkelt att få kontakt med oss. Fråga oss något, eller dela din feedback." }, "CHANNEL_GREETING_MESSAGE": { - "LABEL": "Channel greeting message", - "PLACEHOLDER": "Acme Inc typically replies in a few hours." + "LABEL": "Kanalhälsningsmeddelande", + "PLACEHOLDER": "Acme Inc svarar vanligtvis inom några timmar." }, "CHANNEL_GREETING_TOGGLE": { - "LABEL": "Enable channel greeting", - "HELP_TEXT": "Send a greeting message to the user when he starts the conversation.", + "LABEL": "Aktivera kanalhälsning", + "HELP_TEXT": "Skicka ett hälsningsmeddelande till användaren när hen startar konversationen.", "ENABLED": "Aktiverad", "DISABLED": "Inaktiverad" }, "REPLY_TIME": { - "TITLE": "Set Reply time", - "IN_A_FEW_MINUTES": "In a few minutes", - "IN_A_FEW_HOURS": "In a few hours", - "IN_A_DAY": "In a day", - "HELP_TEXT": "This reply time will be displayed on the live chat widget" + "TITLE": "Ställ in svarstid", + "IN_A_FEW_MINUTES": "Inom några minuter", + "IN_A_FEW_HOURS": "Inom några timmar", + "IN_A_DAY": "Inom en dag", + "HELP_TEXT": "Den här svarstiden kommer att visas på livechattswidgeten" }, "WIDGET_COLOR": { "LABEL": "Widget färg", @@ -87,16 +87,16 @@ "SUBMIT_BUTTON": "Skapa inkorg" }, "TWILIO": { - "TITLE": "Twilio SMS/Whatsapp Channel", - "DESC": "Integrate Twilio and start supporting your customers via SMS or Whatsapp.", + "TITLE": "Twilio SMS/Whatsapp-kanal", + "DESC": "Integrera Twilio och börja supporta dina kunder via SMS eller Whatsapp.", "ACCOUNT_SID": { "LABEL": "Konto SID", "PLACEHOLDER": "Ange ditt Twilio-konto SID", "ERROR": "Detta fält är tvingande" }, "CHANNEL_TYPE": { - "LABEL": "Channel Type", - "ERROR": "Please select your Channel Type" + "LABEL": "Kanaltyp", + "ERROR": "Var god välj din kanaltyp" }, "AUTH_TOKEN": { "LABEL": "Auth token", @@ -114,8 +114,8 @@ "ERROR": "Ange ett giltigt värde. Telefonnummer bör börja med `+`-tecken." }, "API_CALLBACK": { - "TITLE": "Callback URL", - "SUBTITLE": "You have to configure the message callback URL in Twilio with the URL mentioned here." + "TITLE": "Callback-URL", + "SUBTITLE": "Du måste konfigurera meddelande-callback-URL i Twilio med den URL som nämns här." }, "SUBMIT_BUTTON": "Skapa Twilio kanal", "API": { @@ -123,8 +123,8 @@ } }, "API_CHANNEL": { - "TITLE": "API Channel", - "DESC": "Integrate with API channel and start supporting your customers.", + "TITLE": "API-kanal", + "DESC": "Integrera med API-kanalen och börja supporta dina kunder.", "CHANNEL_NAME": { "LABEL": "Kanalnamn", "PLACEHOLDER": "Ange ett kanalnamn", @@ -132,17 +132,17 @@ }, "WEBHOOK_URL": { "LABEL": "Webhook URL", - "SUBTITLE": "Configure the URL where you want to recieve callbacks on events.", + "SUBTITLE": "Konfigurera URL:en där du vill få callbacks på händelser.", "PLACEHOLDER": "Webhook URL" }, - "SUBMIT_BUTTON": "Create API Channel", + "SUBMIT_BUTTON": "Skapa API-kanal", "API": { - "ERROR_MESSAGE": "We were not able to save the api channel" + "ERROR_MESSAGE": "Vi kunde inte spara API-kanalen" } }, "EMAIL_CHANNEL": { - "TITLE": "Email Channel", - "DESC": "Integrate you email inbox.", + "TITLE": "E-postkanal", + "DESC": "Integrera din e-postinkorg.", "CHANNEL_NAME": { "LABEL": "Kanalnamn", "PLACEHOLDER": "Ange ett kanalnamn", @@ -150,24 +150,24 @@ }, "EMAIL": { "LABEL": "E-post", - "SUBTITLE": "Email where your customers sends you support tickets", + "SUBTITLE": "E-post dit dina kunder skickar supportärenden", "PLACEHOLDER": "E-post" }, - "SUBMIT_BUTTON": "Create Email Channel", + "SUBMIT_BUTTON": "Skapa e-postkanal", "API": { - "ERROR_MESSAGE": "We were not able to save the email channel" + "ERROR_MESSAGE": "Vi kunde inte spara e-postkanalen" }, - "FINISH_MESSAGE": "Start forwarding your emails to the following email address." + "FINISH_MESSAGE": "Börja vidarebefordra dina e-postmeddelanden till följande e-postadress." }, "AUTH": { "TITLE": "Kanaler", - "DESC": "För närvarande stöder vi Webbplats live chat widgets, Facebook-sidor och Twitter-profiler som plattformar. Vi har fler plattformar som Whatsapp, e-post, Telegram och Linje i verken, som kommer ut snart." + "DESC": "För närvarande stöder vi live chat widgets på en webbplats, Facebook-sidor, Twitter-profiler och Whatsapp som plattformar. Vi har fler plattformar som e-post, Telegram och Line på gång som kommer ut snart." }, "AGENTS": { "TITLE": "Agenter", "DESC": "Här kan du lägga till agenter för att hantera din nyskapade inkorg. Endast dessa utvalda agenter har tillgång till din inkorg. Agenter som inte är en del av denna inkorg kommer inte att kunna se eller svara på meddelanden i denna inkorg när de loggar in.Labels
Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel.
Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.
Etiketter
Etiketter hjälper dig att kategorisera konversationer och prioritera dem. Du kan tilldela etiketter till en konversation från sidopanelen.
Etiketter är knutna till kontot och kan användas för att skapa anpassade arbetsflöden i din organisation. Du kan tilldela en färg till en etikett, det gör det lättare att identifiera etiketten. Du kommer att kunna visa etiketten på sidofältet för att enkelt filtrera konversationerna.