Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b83c7c8c39 | ||
|
|
496e78b5d3 | ||
|
|
6694db093f | ||
|
|
0331815cc5 | ||
|
|
027a540bbd | ||
|
|
239c61095a | ||
|
|
e9d47d31c7 | ||
|
|
8b1d98af52 | ||
|
|
8e2b329202 | ||
|
|
71073a06ff | ||
|
|
39d20b197d | ||
|
|
fb99ba7b40 | ||
|
|
79aa5a5d7f | ||
|
|
10ee773aac | ||
|
|
81d7c51a84 | ||
|
|
79381b08cc | ||
|
|
84c380c8c4 | ||
|
|
cb0642564c | ||
|
|
23e30fcb1a | ||
|
|
ae8619142f | ||
|
|
499408ea6f | ||
|
|
dc245814fe | ||
|
|
6c52a0638d | ||
|
|
64a9a46b28 | ||
|
|
30d4f6c2f5 | ||
|
|
5909c0f8b7 | ||
|
|
554388bff3 | ||
|
|
ebf3b46f0d | ||
|
|
5cfac31f93 | ||
|
|
787ac3134d | ||
|
|
2a06c85f1a |
@@ -257,3 +257,5 @@ AZURE_APP_SECRET=
|
||||
# Set to true if you want to remove stale contact inboxes
|
||||
# contact_inboxes with no conversation older than 90 days will be removed
|
||||
# REMOVE_STALE_CONTACT_INBOX_JOB_STATUS=false
|
||||
|
||||
# CAPTAIN_API_URL=http://localhost:3001/api
|
||||
|
||||
@@ -111,9 +111,9 @@ gem 'elastic-apm', require: false
|
||||
gem 'newrelic_rpm', require: false
|
||||
gem 'newrelic-sidekiq-metrics', '>= 1.6.2', require: false
|
||||
gem 'scout_apm', require: false
|
||||
gem 'sentry-rails', '>= 5.18.1', require: false
|
||||
gem 'sentry-rails', '>= 5.18.2', require: false
|
||||
gem 'sentry-ruby', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.18.1', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.18.2', require: false
|
||||
|
||||
##-- background job processing --##
|
||||
gem 'sidekiq', '>= 7.3.0'
|
||||
|
||||
+17
-16
@@ -103,8 +103,8 @@ GEM
|
||||
tzinfo (~> 2.0)
|
||||
acts-as-taggable-on (9.0.1)
|
||||
activerecord (>= 6.0, < 7.1)
|
||||
addressable (2.8.4)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
administrate (0.20.1)
|
||||
actionpack (>= 6.0, < 8.0)
|
||||
actionview (>= 6.0, < 8.0)
|
||||
@@ -171,7 +171,8 @@ GEM
|
||||
commonmarker (0.23.10)
|
||||
concurrent-ruby (1.3.3)
|
||||
connection_pool (2.4.1)
|
||||
crack (0.4.5)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
csv (3.3.0)
|
||||
@@ -358,7 +359,7 @@ GEM
|
||||
ruby2ruby (~> 2.4)
|
||||
ruby_parser (~> 3.10)
|
||||
hana (1.3.7)
|
||||
hashdiff (1.0.1)
|
||||
hashdiff (1.1.0)
|
||||
hashie (5.0.0)
|
||||
http (5.1.1)
|
||||
addressable (~> 2.8)
|
||||
@@ -550,7 +551,7 @@ GEM
|
||||
method_source (~> 1.0)
|
||||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (5.0.1)
|
||||
public_suffix (6.0.0)
|
||||
puma (6.4.2)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.3.0)
|
||||
@@ -633,8 +634,8 @@ GEM
|
||||
retriable (3.1.2)
|
||||
reverse_markdown (2.1.1)
|
||||
nokogiri
|
||||
rexml (3.2.8)
|
||||
strscan (>= 3.0.9)
|
||||
rexml (3.3.2)
|
||||
strscan
|
||||
rspec-core (3.13.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.1)
|
||||
@@ -709,14 +710,14 @@ GEM
|
||||
activesupport (>= 4)
|
||||
selectize-rails (0.12.6)
|
||||
semantic_range (3.0.0)
|
||||
sentry-rails (5.18.1)
|
||||
sentry-rails (5.18.2)
|
||||
railties (>= 5.0)
|
||||
sentry-ruby (~> 5.18.1)
|
||||
sentry-ruby (5.18.1)
|
||||
sentry-ruby (~> 5.18.2)
|
||||
sentry-ruby (5.18.2)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
sentry-sidekiq (5.18.1)
|
||||
sentry-ruby (~> 5.18.1)
|
||||
sentry-sidekiq (5.18.2)
|
||||
sentry-ruby (~> 5.18.2)
|
||||
sidekiq (>= 3.0)
|
||||
sexp_processor (4.17.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
@@ -809,7 +810,7 @@ GEM
|
||||
web-push (3.0.1)
|
||||
jwt (~> 2.0)
|
||||
openssl (~> 3.0)
|
||||
webmock (3.18.1)
|
||||
webmock (3.23.1)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -938,9 +939,9 @@ DEPENDENCIES
|
||||
scout_apm
|
||||
scss_lint
|
||||
seed_dump
|
||||
sentry-rails (>= 5.18.1)
|
||||
sentry-rails (>= 5.18.2)
|
||||
sentry-ruby
|
||||
sentry-sidekiq (>= 5.18.1)
|
||||
sentry-sidekiq (>= 5.18.2)
|
||||
shoulda-matchers
|
||||
sidekiq (>= 7.3.0)
|
||||
sidekiq-cron (>= 1.12.0)
|
||||
@@ -970,4 +971,4 @@ RUBY VERSION
|
||||
ruby 3.3.3p89
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.14
|
||||
2.5.16
|
||||
|
||||
@@ -27,7 +27,7 @@ class Messages::Messenger::MessageBuilder
|
||||
file_type = attachment['type'].to_sym
|
||||
params = { file_type: file_type, account_id: @message.account_id }
|
||||
|
||||
if [:image, :file, :audio, :video, :share, :story_mention].include? file_type
|
||||
if [:image, :file, :audio, :video, :share, :story_mention, :ig_reel].include? file_type
|
||||
params.merge!(file_type_params(attachment))
|
||||
elsif file_type == :location
|
||||
params.merge!(location_params(attachment))
|
||||
|
||||
@@ -10,7 +10,7 @@ class Api::V1::Accounts::Integrations::AppsController < Api::V1::Accounts::BaseC
|
||||
private
|
||||
|
||||
def fetch_apps
|
||||
@apps = Integrations::App.all.select(&:active?)
|
||||
@apps = Integrations::App.all.select { |app| app.active?(Current.account) }
|
||||
end
|
||||
|
||||
def fetch_app
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
@import 'shared/assets/fonts/plus-jakarta';
|
||||
@import 'shared/assets/fonts/InterDisplay/inter-display';
|
||||
@import 'shared/assets/fonts/inter';
|
||||
|
||||
@import 'shared/assets/stylesheets/animations';
|
||||
@import 'shared/assets/stylesheets/colors';
|
||||
@import 'shared/assets/stylesheets/spacing';
|
||||
@@ -42,6 +45,7 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
// scss-lint:disable PropertySortOrder
|
||||
:root {
|
||||
--color-amber-25: 254 253 251;
|
||||
@@ -213,6 +217,7 @@
|
||||
--color-orange-800: 204 78 0;
|
||||
--color-orange-900: 88 45 29;
|
||||
}
|
||||
|
||||
// scss-lint:disable QualifyingElement
|
||||
body.dark {
|
||||
--color-amber-25: 31 19 0;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
table {
|
||||
@apply border-spacing-0 text-sm w-full;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.woot-table {
|
||||
thead {
|
||||
th {
|
||||
@apply font-semibold tracking-[1px] text-left px-2.5 uppercase text-slate-900 dark:text-slate-200;
|
||||
@@ -16,9 +20,7 @@ table {
|
||||
@apply p-2.5 text-slate-700 dark:text-slate-100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woot-table {
|
||||
tr {
|
||||
.show-if-hover {
|
||||
transition: opacity 0.2s $swift-ease-out-function;
|
||||
|
||||
@@ -116,13 +116,14 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import VirtualList from 'vue-virtual-scroll-list';
|
||||
|
||||
import ChatListHeader from './ChatListHeader.vue';
|
||||
import ConversationAdvancedFilter from './widgets/conversation/ConversationAdvancedFilter.vue';
|
||||
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
|
||||
import ConversationItem from './ConversationItem.vue';
|
||||
import timeMixin from '../mixins/time';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import conversationMixin from '../mixins/conversations';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
@@ -131,9 +132,7 @@ import filterQueryGenerator from '../helper/filterQueryGenerator.js';
|
||||
import AddCustomViews from 'dashboard/routes/dashboard/customviews/AddCustomViews.vue';
|
||||
import DeleteCustomViews from 'dashboard/routes/dashboard/customviews/DeleteCustomViews.vue';
|
||||
import ConversationBulkActions from './widgets/conversation/conversationBulkActions/Index.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import filterMixin from 'shared/mixins/filterMixin';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
||||
import countries from 'shared/constants/countries';
|
||||
import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper';
|
||||
@@ -158,14 +157,7 @@ export default {
|
||||
IntersectionObserver,
|
||||
VirtualList,
|
||||
},
|
||||
mixins: [
|
||||
timeMixin,
|
||||
conversationMixin,
|
||||
keyboardEventListenerMixins,
|
||||
alertMixin,
|
||||
filterMixin,
|
||||
uiSettingsMixin,
|
||||
],
|
||||
mixins: [conversationMixin, keyboardEventListenerMixins, filterMixin],
|
||||
provide() {
|
||||
return {
|
||||
// Actions to be performed on virtual list item and context menu.
|
||||
@@ -210,6 +202,13 @@ export default {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { uiSettings } = useUISettings();
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeAssigneeTab: wootConstants.ASSIGNEE_TYPE.ME,
|
||||
@@ -812,7 +811,7 @@ export default {
|
||||
});
|
||||
this.$store.dispatch('bulkActions/clearSelectedConversationIds');
|
||||
if (conversationId) {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'CONVERSATION.CARD_CONTEXT_MENU.API.AGENT_ASSIGNMENT.SUCCESFUL',
|
||||
{
|
||||
@@ -822,10 +821,10 @@ export default {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.showAlert(this.$t('BULK_ACTION.ASSIGN_SUCCESFUL'));
|
||||
useAlert(this.$t('BULK_ACTION.ASSIGN_SUCCESFUL'));
|
||||
}
|
||||
} catch (err) {
|
||||
this.showAlert(this.$t('BULK_ACTION.ASSIGN_FAILED'));
|
||||
useAlert(this.$t('BULK_ACTION.ASSIGN_FAILED'));
|
||||
}
|
||||
},
|
||||
async assignPriority(priority, conversationId = null) {
|
||||
@@ -840,7 +839,7 @@ export default {
|
||||
newValue: priority,
|
||||
from: 'Context menu',
|
||||
});
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t('CONVERSATION.PRIORITY.CHANGE_PRIORITY.SUCCESSFUL', {
|
||||
priority,
|
||||
conversationId,
|
||||
@@ -883,7 +882,7 @@ export default {
|
||||
conversationId,
|
||||
teamId: team.id,
|
||||
});
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'CONVERSATION.CARD_CONTEXT_MENU.API.TEAM_ASSIGNMENT.SUCCESFUL',
|
||||
{
|
||||
@@ -893,7 +892,7 @@ export default {
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t('CONVERSATION.CARD_CONTEXT_MENU.API.TEAM_ASSIGNMENT.FAILED')
|
||||
);
|
||||
}
|
||||
@@ -910,7 +909,7 @@ export default {
|
||||
});
|
||||
this.$store.dispatch('bulkActions/clearSelectedConversationIds');
|
||||
if (conversationId) {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'CONVERSATION.CARD_CONTEXT_MENU.API.LABEL_ASSIGNMENT.SUCCESFUL',
|
||||
{
|
||||
@@ -920,10 +919,10 @@ export default {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.showAlert(this.$t('BULK_ACTION.LABELS.ASSIGN_SUCCESFUL'));
|
||||
useAlert(this.$t('BULK_ACTION.LABELS.ASSIGN_SUCCESFUL'));
|
||||
}
|
||||
} catch (err) {
|
||||
this.showAlert(this.$t('BULK_ACTION.LABELS.ASSIGN_FAILED'));
|
||||
useAlert(this.$t('BULK_ACTION.LABELS.ASSIGN_FAILED'));
|
||||
}
|
||||
},
|
||||
async onAssignTeamsForBulk(team) {
|
||||
@@ -936,9 +935,9 @@ export default {
|
||||
},
|
||||
});
|
||||
this.$store.dispatch('bulkActions/clearSelectedConversationIds');
|
||||
this.showAlert(this.$t('BULK_ACTION.TEAMS.ASSIGN_SUCCESFUL'));
|
||||
useAlert(this.$t('BULK_ACTION.TEAMS.ASSIGN_SUCCESFUL'));
|
||||
} catch (err) {
|
||||
this.showAlert(this.$t('BULK_ACTION.TEAMS.ASSIGN_FAILED'));
|
||||
useAlert(this.$t('BULK_ACTION.TEAMS.ASSIGN_FAILED'));
|
||||
}
|
||||
},
|
||||
async onUpdateConversations(status, snoozedUntil) {
|
||||
@@ -952,9 +951,9 @@ export default {
|
||||
snoozed_until: snoozedUntil,
|
||||
});
|
||||
this.$store.dispatch('bulkActions/clearSelectedConversationIds');
|
||||
this.showAlert(this.$t('BULK_ACTION.UPDATE.UPDATE_SUCCESFUL'));
|
||||
useAlert(this.$t('BULK_ACTION.UPDATE.UPDATE_SUCCESFUL'));
|
||||
} catch (err) {
|
||||
this.showAlert(this.$t('BULK_ACTION.UPDATE.UPDATE_FAILED'));
|
||||
useAlert(this.$t('BULK_ACTION.UPDATE.UPDATE_FAILED'));
|
||||
}
|
||||
},
|
||||
toggleConversationStatus(conversationId, status, snoozedUntil) {
|
||||
@@ -965,7 +964,7 @@ export default {
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
useAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
<script>
|
||||
import 'highlight.js/styles/default.css';
|
||||
import { copyTextToClipboard } from 'shared/helpers/clipboard';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
script: {
|
||||
type: String,
|
||||
@@ -61,7 +60,7 @@ export default {
|
||||
async onCopy(e) {
|
||||
e.preventDefault();
|
||||
await copyTextToClipboard(this.script);
|
||||
this.showAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
||||
useAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<script setup>
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
import { computed } from 'vue';
|
||||
const props = defineProps({
|
||||
showOnCustomBrandedInstance: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const getters = useStoreGetters();
|
||||
|
||||
const isACustomBrandedInstance =
|
||||
getters['globalConfig/isACustomBrandedInstance'];
|
||||
|
||||
const shouldShowContent = computed(
|
||||
() => props.showOnCustomBrandedInstance || !isACustomBrandedInstance.value
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="shouldShowContent">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,10 +18,9 @@
|
||||
<script>
|
||||
import 'highlight.js/styles/default.css';
|
||||
import { copyTextToClipboard } from 'shared/helpers/clipboard';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
@@ -37,7 +36,7 @@ export default {
|
||||
async onCopy(e) {
|
||||
e.preventDefault();
|
||||
await copyTextToClipboard(this.value);
|
||||
this.showAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
||||
useAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
||||
},
|
||||
toggleMasked() {
|
||||
this.masked = !this.masked;
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
|
||||
<script>
|
||||
import WootSnackbar from './Snackbar.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WootSnackbar,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
duration: {
|
||||
type: Number,
|
||||
@@ -42,7 +40,7 @@ export default {
|
||||
this.$emitter.off('newToastMessage', this.onNewToastMessage);
|
||||
},
|
||||
methods: {
|
||||
onNewToastMessage(message, action) {
|
||||
onNewToastMessage({ message, action }) {
|
||||
this.snackMessages.push({
|
||||
key: new Date().getTime(),
|
||||
message,
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
|
||||
const EMPTY_SUBSCRIPTION_INFO = {
|
||||
@@ -22,7 +22,13 @@ const EMPTY_SUBSCRIPTION_INFO = {
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [adminMixin, accountMixin],
|
||||
mixins: [accountMixin],
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isOnChatwootCloud: 'globalConfig/isOnChatwootCloud',
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [accountMixin, alertMixin],
|
||||
mixins: [accountMixin],
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'getCurrentUser',
|
||||
@@ -36,7 +36,7 @@ export default {
|
||||
methods: {
|
||||
resendVerificationEmail() {
|
||||
this.$store.dispatch('resendConfirmation');
|
||||
this.showAlert(this.$t('APP_GLOBAL.EMAIL_VERIFICATION_SENT'));
|
||||
useAlert(this.$t('APP_GLOBAL.EMAIL_VERIFICATION_SENT'));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,15 +14,20 @@ import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { hasAnUpdateAvailable } from './versionCheckHelper';
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [adminMixin],
|
||||
props: {
|
||||
latestChatwootVersion: { type: String, default: '' },
|
||||
},
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return { userDismissedBanner: false };
|
||||
},
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
<script>
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [adminMixin, accountMixin],
|
||||
mixins: [accountMixin],
|
||||
data() {
|
||||
return { conversationMeta: {} };
|
||||
},
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||
@@ -94,7 +94,7 @@ export default {
|
||||
WootDropdownItem,
|
||||
WootDropdownMenu,
|
||||
},
|
||||
mixins: [alertMixin, keyboardEventListenerMixins],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
props: { conversationId: { type: [String, Number], required: true } },
|
||||
data() {
|
||||
return {
|
||||
@@ -209,7 +209,7 @@ export default {
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
useAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</woot-button>
|
||||
</woot-dropdown-item>
|
||||
<woot-dropdown-divider />
|
||||
<woot-dropdown-item class="m-0 flex items-center justify-between p-2">
|
||||
<woot-dropdown-item class="flex items-center justify-between p-2 m-0">
|
||||
<div class="flex items-center">
|
||||
<fluent-icon
|
||||
v-tooltip.right-start="$t('SIDEBAR.SET_AUTO_OFFLINE.INFO_TEXT')"
|
||||
@@ -28,7 +28,7 @@
|
||||
/>
|
||||
|
||||
<span
|
||||
class="my-0 mx-1 text-xs font-medium text-slate-600 dark:text-slate-100"
|
||||
class="mx-1 my-0 text-xs font-medium text-slate-600 dark:text-slate-100"
|
||||
>
|
||||
{{ $t('SIDEBAR.SET_AUTO_OFFLINE.TEXT') }}
|
||||
</span>
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<woot-switch
|
||||
size="small"
|
||||
class="mt-px mx-1 mb-0"
|
||||
class="mx-1 mt-px mb-0"
|
||||
:value="currentUserAutoOffline"
|
||||
@input="updateAutoOffline"
|
||||
/>
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||
import WootDropdownHeader from 'shared/components/ui/dropdown/DropdownHeader.vue';
|
||||
@@ -65,9 +65,6 @@ export default {
|
||||
WootDropdownItem,
|
||||
AvailabilityStatusBadge,
|
||||
},
|
||||
|
||||
mixins: [alertMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
isStatusMenuOpened: false,
|
||||
@@ -129,7 +126,7 @@ export default {
|
||||
account_id: this.currentAccountId,
|
||||
});
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t('PROFILE_SETTINGS.FORM.AVAILABILITY.SET_AVAILABILITY_ERROR')
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from '../../mixins/isAdmin';
|
||||
import { getSidebarItems } from './config/default-sidebar';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
import PrimarySidebar from './sidebarComponents/Primary.vue';
|
||||
import SecondarySidebar from './sidebarComponents/Secondary.vue';
|
||||
@@ -45,7 +43,7 @@ export default {
|
||||
PrimarySidebar,
|
||||
SecondarySidebar,
|
||||
},
|
||||
mixins: [adminMixin, alertMixin, keyboardEventListenerMixins],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
props: {
|
||||
showSecondarySidebar: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -163,17 +163,6 @@ const settings = accountId => ({
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/integrations`),
|
||||
toStateName: 'settings_integrations',
|
||||
featureFlag: FEATURE_FLAGS.INTEGRATIONS,
|
||||
},
|
||||
{
|
||||
icon: 'star-emphasis',
|
||||
label: 'APPLICATIONS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/applications`),
|
||||
toStateName: 'settings_applications',
|
||||
featureFlag: FEATURE_FLAGS.INTEGRATIONS,
|
||||
},
|
||||
|
||||
@@ -51,10 +51,9 @@
|
||||
<script>
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
@@ -88,13 +87,13 @@ export default {
|
||||
account_name: this.accountName,
|
||||
});
|
||||
this.$emit('close-account-create-modal');
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.SUCCESS_MESSAGE'));
|
||||
useAlert(this.$t('CREATE_ACCOUNT.API.SUCCESS_MESSAGE'));
|
||||
window.location = `/app/accounts/${account_id}/dashboard`;
|
||||
} catch (error) {
|
||||
if (error.response.status === 422) {
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.EXIST_MESSAGE'));
|
||||
useAlert(this.$t('CREATE_ACCOUNT.API.EXIST_MESSAGE'));
|
||||
} else {
|
||||
this.showAlert(this.$t('CREATE_ACCOUNT.API.ERROR_MESSAGE'));
|
||||
useAlert(this.$t('CREATE_ACCOUNT.API.ERROR_MESSAGE'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -94,8 +94,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import adminMixin from '../../../mixins/isAdmin';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import configMixin from 'shared/mixins/configMixin';
|
||||
import {
|
||||
getInboxClassByType,
|
||||
@@ -111,13 +110,19 @@ import Policy from '../../policy.vue';
|
||||
|
||||
export default {
|
||||
components: { SecondaryChildNavItem, Policy },
|
||||
mixins: [adminMixin, configMixin],
|
||||
mixins: [configMixin],
|
||||
props: {
|
||||
menuItem: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
activeInbox: 'getSelectedInbox',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
delay: { show: 1500, hide: 0 },
|
||||
hideOnClick: true,
|
||||
}"
|
||||
class="text-xxs text-slate-500 dark:text-slate-500 leading-4 ml-auto hover:text-slate-900 dark:hover:text-slate-100"
|
||||
class="ml-auto leading-4 text-xxs text-slate-500 dark:text-slate-500 hover:text-slate-900 dark:hover:text-slate-100"
|
||||
>
|
||||
<span>{{ `${createdAtTime} • ${lastActivityTime}` }}</span>
|
||||
</div>
|
||||
@@ -16,11 +16,14 @@ const MINUTE_IN_MILLI_SECONDS = 60000;
|
||||
const HOUR_IN_MILLI_SECONDS = MINUTE_IN_MILLI_SECONDS * 60;
|
||||
const DAY_IN_MILLI_SECONDS = HOUR_IN_MILLI_SECONDS * 24;
|
||||
|
||||
import timeMixin from 'dashboard/mixins/time';
|
||||
import {
|
||||
dynamicTime,
|
||||
dateFormat,
|
||||
shortTimestamp,
|
||||
} from 'shared/helpers/timeHelper';
|
||||
|
||||
export default {
|
||||
name: 'TimeAgo',
|
||||
mixins: [timeMixin],
|
||||
props: {
|
||||
isAutoRefreshEnabled: {
|
||||
type: Boolean,
|
||||
@@ -37,17 +40,17 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lastActivityAtTimeAgo: this.dynamicTime(this.lastActivityTimestamp),
|
||||
createdAtTimeAgo: this.dynamicTime(this.createdAtTimestamp),
|
||||
lastActivityAtTimeAgo: dynamicTime(this.lastActivityTimestamp),
|
||||
createdAtTimeAgo: dynamicTime(this.createdAtTimestamp),
|
||||
timer: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
lastActivityTime() {
|
||||
return this.shortTimestamp(this.lastActivityAtTimeAgo);
|
||||
return shortTimestamp(this.lastActivityAtTimeAgo);
|
||||
},
|
||||
createdAtTime() {
|
||||
return this.shortTimestamp(this.createdAtTimeAgo);
|
||||
return shortTimestamp(this.createdAtTimeAgo);
|
||||
},
|
||||
createdAt() {
|
||||
const createdTimeDiff = Date.now() - this.createdAtTimestamp * 1000;
|
||||
@@ -56,9 +59,9 @@ export default {
|
||||
? `${this.$t('CHAT_LIST.CHAT_TIME_STAMP.CREATED.LATEST')} ${
|
||||
this.createdAtTimeAgo
|
||||
}`
|
||||
: `${this.$t(
|
||||
'CHAT_LIST.CHAT_TIME_STAMP.CREATED.OLDEST'
|
||||
)} ${this.dateFormat(this.createdAtTimestamp)}`;
|
||||
: `${this.$t('CHAT_LIST.CHAT_TIME_STAMP.CREATED.OLDEST')} ${dateFormat(
|
||||
this.createdAtTimestamp
|
||||
)}`;
|
||||
},
|
||||
lastActivity() {
|
||||
const lastActivityTimeDiff =
|
||||
@@ -70,7 +73,7 @@ export default {
|
||||
}`
|
||||
: `${this.$t(
|
||||
'CHAT_LIST.CHAT_TIME_STAMP.LAST_ACTIVITY.NOT_ACTIVE'
|
||||
)} ${this.dateFormat(this.lastActivityTimestamp)}`;
|
||||
)} ${dateFormat(this.lastActivityTimestamp)}`;
|
||||
},
|
||||
tooltipText() {
|
||||
return `${this.createdAt}
|
||||
@@ -79,10 +82,10 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
lastActivityTimestamp() {
|
||||
this.lastActivityAtTimeAgo = this.dynamicTime(this.lastActivityTimestamp);
|
||||
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
|
||||
},
|
||||
createdAtTimestamp() {
|
||||
this.createdAtTimeAgo = this.dynamicTime(this.createdAtTimestamp);
|
||||
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
@@ -96,10 +99,8 @@ export default {
|
||||
methods: {
|
||||
createTimer() {
|
||||
this.timer = setTimeout(() => {
|
||||
this.lastActivityAtTimeAgo = this.dynamicTime(
|
||||
this.lastActivityTimestamp
|
||||
);
|
||||
this.createdAtTimeAgo = this.dynamicTime(this.createdAtTimestamp);
|
||||
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
|
||||
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
|
||||
this.createTimer();
|
||||
}, this.refreshTime());
|
||||
},
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import AICTAModal from './AICTAModal.vue';
|
||||
import AIAssistanceModal from './AIAssistanceModal.vue';
|
||||
import adminMixin from 'dashboard/mixins/aiMixin';
|
||||
import aiMixin from 'dashboard/mixins/isAdmin';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
import { CMD_AI_ASSIST } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import AIAssistanceCTAButton from './AIAssistanceCTAButton.vue';
|
||||
|
||||
export default {
|
||||
@@ -50,7 +50,17 @@ export default {
|
||||
AICTAModal,
|
||||
AIAssistanceCTAButton,
|
||||
},
|
||||
mixins: [aiMixin, keyboardEventListenerMixins, adminMixin, uiSettingsMixin],
|
||||
mixins: [aiMixin, keyboardEventListenerMixins],
|
||||
setup() {
|
||||
const { uiSettings, updateUISettings } = useUISettings();
|
||||
const { isAdmin } = useAdmin();
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
data: () => ({
|
||||
showAIAssistanceModal: false,
|
||||
showAICtaModal: false,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="px-0 min-w-0 flex-1">
|
||||
<div class="flex-1 min-w-0 px-0">
|
||||
<woot-modal-header
|
||||
:header-title="$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.TITLE')"
|
||||
:header-content="$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.DESC')"
|
||||
/>
|
||||
<form
|
||||
class="flex flex-wrap flex-col modal-content"
|
||||
class="flex flex-col flex-wrap modal-content"
|
||||
@submit.prevent="finishOpenAI"
|
||||
>
|
||||
<div class="mt-2 w-full">
|
||||
<div class="w-full mt-2">
|
||||
<woot-input
|
||||
v-model="value"
|
||||
type="text"
|
||||
@@ -19,7 +19,7 @@
|
||||
@blur="$v.value.$touch"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between gap-2 py-2 px-0 w-full">
|
||||
<div class="flex flex-row justify-between w-full gap-2 px-0 py-2">
|
||||
<woot-button variant="link" @click.prevent="openOpenAIDoc">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.NEED_HELP') }}
|
||||
</woot-button>
|
||||
@@ -39,13 +39,20 @@
|
||||
<script>
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
|
||||
export default {
|
||||
mixins: [aiMixin, alertMixin, uiSettingsMixin],
|
||||
mixins: [aiMixin],
|
||||
setup() {
|
||||
const { updateUISettings } = useUISettings();
|
||||
|
||||
return {
|
||||
updateUISettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
@@ -67,7 +74,7 @@ export default {
|
||||
},
|
||||
|
||||
onDismiss() {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.DISMISS_MESSAGE')
|
||||
);
|
||||
this.updateUISettings({
|
||||
@@ -97,7 +104,7 @@ export default {
|
||||
this.alertMessage =
|
||||
errorMessage || this.$t('INTEGRATION_APPS.ADD.API.ERROR_MESSAGE');
|
||||
} finally {
|
||||
this.showAlert(this.alertMessage);
|
||||
useAlert(this.alertMessage);
|
||||
}
|
||||
},
|
||||
openOpenAIDoc() {
|
||||
|
||||
@@ -26,13 +26,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
export default {
|
||||
components: {
|
||||
Spinner,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
@@ -71,7 +70,7 @@ export default {
|
||||
} catch (error) {
|
||||
this.uploadState = 'failed';
|
||||
this.label = this.$t('AUTOMATION.ATTACHMENT.LABEL_UPLOAD_FAILED');
|
||||
this.showAlert(this.$t('AUTOMATION.ATTACHMENT.UPLOAD_ERROR'));
|
||||
useAlert(this.$t('AUTOMATION.ATTACHMENT.UPLOAD_ERROR'));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,34 +1,40 @@
|
||||
<script setup>
|
||||
import router from '../../routes/index';
|
||||
const props = defineProps({
|
||||
backUrl: {
|
||||
type: [String, Object],
|
||||
default: '',
|
||||
},
|
||||
buttonLabel: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const goBack = () => {
|
||||
if (props.backUrl !== '') {
|
||||
router.push(props.backUrl);
|
||||
} else {
|
||||
router.go(-1);
|
||||
}
|
||||
};
|
||||
|
||||
const buttonStyleClass = props.compact
|
||||
? 'text-sm text-slate-600 dark:text-slate-300'
|
||||
: 'text-base text-woot-500 dark:text-woot-500';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
class="header-section flex items-center text-base font-normal mr-4 ml-2 p-0 cursor-pointer text-woot-500 dark:text-woot-500"
|
||||
class="flex items-center font-normal p-0 cursor-pointer"
|
||||
:class="buttonStyleClass"
|
||||
@click.capture="goBack"
|
||||
>
|
||||
<fluent-icon icon="chevron-left" />
|
||||
<fluent-icon icon="chevron-left" class="-ml-1" />
|
||||
{{ buttonLabel || $t('GENERAL_SETTINGS.BACK') }}
|
||||
</button>
|
||||
</template>
|
||||
<script>
|
||||
import router from '../../routes/index';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
backUrl: {
|
||||
type: [String, Object],
|
||||
default: '',
|
||||
},
|
||||
buttonLabel: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
if (this.backUrl !== '') {
|
||||
router.push(this.backUrl);
|
||||
} else {
|
||||
router.go(-1);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
import AddLabel from 'shared/components/ui/dropdown/AddLabel.vue';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import LabelDropdown from 'shared/components/ui/label/LabelDropdown.vue';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -41,7 +41,7 @@ export default {
|
||||
LabelDropdown,
|
||||
},
|
||||
|
||||
mixins: [adminMixin, keyboardEventListenerMixins],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
|
||||
props: {
|
||||
allLabels: {
|
||||
@@ -54,6 +54,13 @@ export default {
|
||||
},
|
||||
},
|
||||
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showSearchDropdownLabel: false,
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import DyteAPI from 'dashboard/api/integrations/dyte';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
conversationId: {
|
||||
type: Number,
|
||||
@@ -47,7 +46,7 @@ export default {
|
||||
try {
|
||||
await DyteAPI.createAMeeting(this.conversationId);
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('INTEGRATION_SETTINGS.DYTE.CREATE_ERROR'));
|
||||
useAlert(this.$t('INTEGRATION_SETTINGS.DYTE.CREATE_ERROR'));
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'videojs-record/dist/css/videojs.record.css';
|
||||
|
||||
import videojs from 'video.js';
|
||||
|
||||
import alertMixin from '../../../../shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
import Recorder from 'opus-recorder';
|
||||
|
||||
@@ -50,7 +50,6 @@ const RECORDER_CONFIG = {
|
||||
|
||||
export default {
|
||||
name: 'WootAudioRecorder',
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
audioRecordFormat: {
|
||||
type: String,
|
||||
@@ -188,14 +187,10 @@ export default {
|
||||
deviceErrorName?.includes('notallowederror') ||
|
||||
deviceErrorName?.includes('permissiondeniederror')
|
||||
) {
|
||||
this.showAlert(
|
||||
this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_PERMISSION')
|
||||
);
|
||||
useAlert(this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_PERMISSION'));
|
||||
this.fireStateRecorderChanged('notallowederror');
|
||||
} else {
|
||||
this.showAlert(
|
||||
this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_ERROR')
|
||||
);
|
||||
useAlert(this.$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_ERROR'));
|
||||
}
|
||||
},
|
||||
formatTimeProgress() {
|
||||
|
||||
@@ -80,8 +80,7 @@ import {
|
||||
hasPressedCommandAndEnter,
|
||||
} from 'shared/helpers/KeyboardHelpers';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import {
|
||||
replaceVariablesInMessage,
|
||||
createTypingIndicator,
|
||||
@@ -89,7 +88,7 @@ import {
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
|
||||
import { uploadFile } from 'dashboard/helper/uploadHelper';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import {
|
||||
MESSAGE_EDITOR_MENU_OPTIONS,
|
||||
MESSAGE_EDITOR_IMAGE_RESIZES,
|
||||
@@ -119,7 +118,7 @@ const createState = (
|
||||
export default {
|
||||
name: 'WootMessageEditor',
|
||||
components: { TagAgents, CannedResponse, VariableList },
|
||||
mixins: [keyboardEventListenerMixins, uiSettingsMixin, alertMixin],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
props: {
|
||||
value: { type: String, default: '' },
|
||||
editorId: { type: String, default: '' },
|
||||
@@ -139,6 +138,19 @@ export default {
|
||||
channelType: { type: String, default: '' },
|
||||
showImageResizeToolbar: { type: Boolean, default: false }, // A kill switch to show or hide the image toolbar
|
||||
},
|
||||
setup() {
|
||||
const {
|
||||
uiSettings,
|
||||
isEditorHotKeyEnabled,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
} = useUISettings();
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
isEditorHotKeyEnabled,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typingIndicator: createTypingIndicator(
|
||||
@@ -278,7 +290,7 @@ export default {
|
||||
// this is considered the source of truth, we watch this property
|
||||
// on change, we toggle the signature in the editor
|
||||
if (this.allowSignature && !this.isPrivate && this.channelType) {
|
||||
return this.fetchSignatureFlagFromUiSettings(this.channelType);
|
||||
return this.fetchSignatureFlagFromUISettings(this.channelType);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -521,10 +533,10 @@ export default {
|
||||
}
|
||||
},
|
||||
isEnterToSendEnabled() {
|
||||
return isEditorHotKeyEnabled(this.uiSettings, 'enter');
|
||||
return this.isEditorHotKeyEnabled('enter');
|
||||
},
|
||||
isCmdPlusEnterToSendEnabled() {
|
||||
return isEditorHotKeyEnabled(this.uiSettings, 'cmd_enter');
|
||||
return this.isEditorHotKeyEnabled('cmd_enter');
|
||||
},
|
||||
getKeyboardEvents() {
|
||||
return {
|
||||
@@ -611,7 +623,7 @@ export default {
|
||||
if (checkFileSizeLimit(file, MAXIMUM_FILE_UPLOAD_SIZE)) {
|
||||
this.uploadImageToStorage(file);
|
||||
} else {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.IMAGE_UPLOAD_SIZE_ERROR',
|
||||
{
|
||||
@@ -629,13 +641,13 @@ export default {
|
||||
if (fileUrl) {
|
||||
this.onImageInsertInEditor(fileUrl);
|
||||
}
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.IMAGE_UPLOAD_SUCCESS'
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t(
|
||||
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.IMAGE_UPLOAD_ERROR'
|
||||
)
|
||||
|
||||
@@ -24,9 +24,9 @@ import {
|
||||
Selection,
|
||||
} from '@chatwoot/prosemirror-schema';
|
||||
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
|
||||
const MAXIMUM_FILE_UPLOAD_SIZE = 4; // in MB
|
||||
const createState = (
|
||||
@@ -51,13 +51,21 @@ const createState = (
|
||||
};
|
||||
|
||||
export default {
|
||||
mixins: [keyboardEventListenerMixins, uiSettingsMixin, alertMixin],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
props: {
|
||||
value: { type: String, default: '' },
|
||||
editorId: { type: String, default: '' },
|
||||
placeholder: { type: String, default: '' },
|
||||
enabledMenuOptions: { type: Array, default: () => [] },
|
||||
},
|
||||
setup() {
|
||||
const { uiSettings, updateUISettings } = useUISettings();
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editorView: null,
|
||||
@@ -108,7 +116,7 @@ export default {
|
||||
if (checkFileSizeLimit(file, MAXIMUM_FILE_UPLOAD_SIZE)) {
|
||||
this.uploadImageToStorage(file);
|
||||
} else {
|
||||
this.showAlert(
|
||||
useAlert(
|
||||
this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.ERROR_FILE_SIZE', {
|
||||
size: MAXIMUM_FILE_UPLOAD_SIZE,
|
||||
})
|
||||
@@ -127,13 +135,9 @@ export default {
|
||||
if (fileUrl) {
|
||||
this.onImageUploadStart(fileUrl);
|
||||
}
|
||||
this.showAlert(
|
||||
this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.SUCCESS')
|
||||
);
|
||||
useAlert(this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.SUCCESS'));
|
||||
} catch (error) {
|
||||
this.showAlert(
|
||||
this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.ERROR')
|
||||
);
|
||||
useAlert(this.$t('HELP_CENTER.ARTICLE_EDITOR.IMAGE_UPLOAD.ERROR'));
|
||||
}
|
||||
},
|
||||
onImageUploadStart(fileUrl) {
|
||||
|
||||
@@ -134,10 +134,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import FileUpload from 'vue-upload-component';
|
||||
import * as ActiveStorage from 'activestorage';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
import {
|
||||
@@ -153,7 +153,7 @@ import { mapGetters } from 'vuex';
|
||||
export default {
|
||||
name: 'ReplyBottomPanel',
|
||||
components: { FileUpload, VideoCallButton, AIAssistanceButton },
|
||||
mixins: [keyboardEventListenerMixins, uiSettingsMixin, inboxMixin],
|
||||
mixins: [keyboardEventListenerMixins, inboxMixin],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
@@ -248,6 +248,15 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { setSignatureFlagForInbox, fetchSignatureFlagFromUISettings } =
|
||||
useUISettings();
|
||||
|
||||
return {
|
||||
setSignatureFlagForInbox,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
accountId: 'getCurrentAccountId',
|
||||
@@ -320,7 +329,7 @@ export default {
|
||||
},
|
||||
sendWithSignature() {
|
||||
// channelType is sourced from inboxMixin
|
||||
return this.fetchSignatureFlagFromUiSettings(this.channelType);
|
||||
return this.fetchSignatureFlagFromUISettings(this.channelType);
|
||||
},
|
||||
signatureToggleTooltip() {
|
||||
return this.sendWithSignature
|
||||
|
||||
+3
-3
@@ -79,7 +79,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
||||
import FilterInputBox from '../FilterInput/Index.vue';
|
||||
import languages from './advancedFilterItems/languages';
|
||||
@@ -94,7 +94,7 @@ export default {
|
||||
components: {
|
||||
FilterInputBox,
|
||||
},
|
||||
mixins: [alertMixin, filterMixin],
|
||||
mixins: [filterMixin],
|
||||
props: {
|
||||
onClose: {
|
||||
type: Function,
|
||||
@@ -341,7 +341,7 @@ export default {
|
||||
},
|
||||
removeFilter(index) {
|
||||
if (this.appliedFilters.length <= 1) {
|
||||
this.showAlert(this.$t('FILTER.FILTER_DELETE_ERROR'));
|
||||
useAlert(this.$t('FILTER.FILTER_DELETE_ERROR'));
|
||||
} else {
|
||||
this.appliedFilters.splice(index, 1);
|
||||
}
|
||||
|
||||
+13
-7
@@ -12,10 +12,10 @@
|
||||
<div
|
||||
v-if="showActionsDropdown"
|
||||
v-on-clickaway="closeDropdown"
|
||||
class="dropdown-pane dropdown-pane--open mt-1 right-0 basic-filter"
|
||||
class="right-0 mt-1 dropdown-pane dropdown-pane--open basic-filter"
|
||||
>
|
||||
<div class="items-center flex justify-between last:mt-4">
|
||||
<span class="text-slate-800 dark:text-slate-100 text-xs font-medium">{{
|
||||
<div class="flex items-center justify-between last:mt-4">
|
||||
<span class="text-xs font-medium text-slate-800 dark:text-slate-100">{{
|
||||
$t('CHAT_LIST.CHAT_SORT.STATUS')
|
||||
}}</span>
|
||||
<filter-item
|
||||
@@ -26,8 +26,8 @@
|
||||
@onChangeFilter="onChangeFilter"
|
||||
/>
|
||||
</div>
|
||||
<div class="items-center flex justify-between last:mt-4">
|
||||
<span class="text-slate-800 dark:text-slate-100 text-xs font-medium">{{
|
||||
<div class="flex items-center justify-between last:mt-4">
|
||||
<span class="text-xs font-medium text-slate-800 dark:text-slate-100">{{
|
||||
$t('CHAT_LIST.CHAT_SORT.ORDER_BY')
|
||||
}}</span>
|
||||
<filter-item
|
||||
@@ -46,13 +46,19 @@
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import { mapGetters } from 'vuex';
|
||||
import FilterItem from './FilterItem.vue';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
FilterItem,
|
||||
},
|
||||
mixins: [uiSettingsMixin],
|
||||
setup() {
|
||||
const { updateUISettings } = useUISettings();
|
||||
|
||||
return {
|
||||
updateUISettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showActionsDropdown: false,
|
||||
|
||||
@@ -120,13 +120,11 @@ import { mapGetters } from 'vuex';
|
||||
import Thumbnail from '../Thumbnail.vue';
|
||||
import MessagePreview from './MessagePreview.vue';
|
||||
import conversationMixin from '../../../mixins/conversations';
|
||||
import timeMixin from '../../../mixins/time';
|
||||
import router from '../../../routes';
|
||||
import { frontendURL, conversationUrl } from '../../../helper/URLHelper';
|
||||
import InboxName from '../InboxName.vue';
|
||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||
import ConversationContextMenu from './contextMenu/Index.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import TimeAgo from 'dashboard/components/ui/TimeAgo.vue';
|
||||
import CardLabels from './conversationCardComponents/CardLabels.vue';
|
||||
import PriorityMark from './PriorityMark.vue';
|
||||
@@ -143,8 +141,7 @@ export default {
|
||||
PriorityMark,
|
||||
SLACardLabel,
|
||||
},
|
||||
|
||||
mixins: [inboxMixin, timeMixin, conversationMixin, alertMixin],
|
||||
mixins: [inboxMixin, conversationMixin],
|
||||
props: {
|
||||
activeLabel: {
|
||||
type: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<woot-modal :show.sync="show" :on-close="onCancel">
|
||||
<div class="h-auto overflow-auto flex flex-col">
|
||||
<div class="flex flex-col h-auto overflow-auto">
|
||||
<woot-modal-header
|
||||
:header-title="$t('EMAIL_TRANSCRIPT.TITLE')"
|
||||
:header-content="$t('EMAIL_TRANSCRIPT.DESC')"
|
||||
@@ -61,7 +61,7 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||
<woot-submit-button
|
||||
:button-text="$t('EMAIL_TRANSCRIPT.SUBMIT')"
|
||||
:disabled="!isFormValid"
|
||||
@@ -77,9 +77,8 @@
|
||||
|
||||
<script>
|
||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
@@ -142,10 +141,10 @@ export default {
|
||||
email: this.selectedEmailAddress,
|
||||
conversationId: this.currentChat.id,
|
||||
});
|
||||
this.showAlert(this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'));
|
||||
useAlert(this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'));
|
||||
this.onCancel();
|
||||
} catch (error) {
|
||||
this.showAlert(this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'));
|
||||
useAlert(this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'));
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import adminMixin from 'dashboard/mixins/isAdmin';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import OnboardingView from '../OnboardingView.vue';
|
||||
import EmptyStateMessage from './EmptyStateMessage.vue';
|
||||
@@ -45,13 +45,19 @@ export default {
|
||||
OnboardingView,
|
||||
EmptyStateMessage,
|
||||
},
|
||||
mixins: [accountMixin, adminMixin],
|
||||
mixins: [accountMixin],
|
||||
props: {
|
||||
isOnExpandedLayout: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentChat: 'getSelectedChat',
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="shouldShowContextMenu"
|
||||
class="context-menu-wrap invisible group-hover:visible"
|
||||
class="invisible context-menu-wrap group-hover:visible"
|
||||
>
|
||||
<context-menu
|
||||
v-if="isBubble && !isMessageDeleted"
|
||||
@@ -157,8 +157,7 @@ import ContextMenu from 'dashboard/modules/conversations/components/MessageConte
|
||||
import InstagramStory from './bubble/InstagramStory.vue';
|
||||
import InstagramStoryReply from './bubble/InstagramStoryReply.vue';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import contentTypeMixin from 'shared/mixins/contentTypeMixin';
|
||||
import { CONTENT_TYPES } from 'shared/constants/contentType';
|
||||
import { MESSAGE_TYPE, MESSAGE_STATUS } from 'shared/constants/messages';
|
||||
import { generateBotMessageContent } from './helpers/botMessageContentHelper';
|
||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||
@@ -166,6 +165,7 @@ import { ACCOUNT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||
import { getDayDifferenceFromNow } from 'shared/helpers/DateHelper';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -183,7 +183,7 @@ export default {
|
||||
InstagramStoryReply,
|
||||
Spinner,
|
||||
},
|
||||
mixins: [alertMixin, messageFormatterMixin, contentTypeMixin],
|
||||
mixins: [messageFormatterMixin],
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
@@ -481,6 +481,9 @@ export default {
|
||||
}
|
||||
return '';
|
||||
},
|
||||
isEmailContentType() {
|
||||
return this.contentType === CONTENT_TYPES.INCOMING_EMAIL;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
data() {
|
||||
@@ -498,19 +501,35 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
isAttachmentImageVideoAudio(fileType) {
|
||||
return ['image', 'audio', 'video', 'story_mention'].includes(fileType);
|
||||
return ['image', 'audio', 'video', 'story_mention', 'ig_reel'].includes(
|
||||
fileType
|
||||
);
|
||||
},
|
||||
hasMediaAttachment(type) {
|
||||
if (this.hasAttachments && this.data.attachments.length > 0) {
|
||||
const { attachments = [{}] } = this.data;
|
||||
const { file_type: fileType } = attachments[0];
|
||||
return fileType === type && !this.hasMediaLoadError;
|
||||
return this.compareMessageFileType(this.data, type);
|
||||
}
|
||||
if (this.storyReply) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
compareMessageFileType(messageData, type) {
|
||||
try {
|
||||
const { attachments = [{}] } = messageData;
|
||||
const { file_type: fileType } = attachments[0];
|
||||
return fileType === type && !this.hasMediaLoadError;
|
||||
} catch (err) {
|
||||
Sentry.setContext('attachment-parsing-error', {
|
||||
messageData,
|
||||
type,
|
||||
hasMediaLoadError: this.hasMediaLoadError,
|
||||
});
|
||||
|
||||
Sentry.captureException(err);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
handleContextMenuClick() {
|
||||
this.showContextMenu = !this.showContextMenu;
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex actions--container relative items-center gap-2">
|
||||
<div class="relative flex items-center gap-2 actions--container">
|
||||
<woot-button
|
||||
v-if="!currentChat.muted"
|
||||
v-tooltip="$t('CONTACT_PANEL.MUTE_CONTACT')"
|
||||
@@ -37,7 +37,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import EmailTranscriptModal from './EmailTranscriptModal.vue';
|
||||
import ResolveAction from '../../buttons/ResolveAction.vue';
|
||||
import {
|
||||
@@ -51,7 +51,6 @@ export default {
|
||||
EmailTranscriptModal,
|
||||
ResolveAction,
|
||||
},
|
||||
mixins: [alertMixin],
|
||||
data() {
|
||||
return {
|
||||
showEmailActionsModal: false,
|
||||
@@ -73,11 +72,11 @@ export default {
|
||||
methods: {
|
||||
mute() {
|
||||
this.$store.dispatch('muteConversation', this.currentChat.id);
|
||||
this.showAlert(this.$t('CONTACT_PANEL.MUTED_SUCCESS'));
|
||||
useAlert(this.$t('CONTACT_PANEL.MUTED_SUCCESS'));
|
||||
},
|
||||
unmute() {
|
||||
this.$store.dispatch('unmuteConversation', this.currentChat.id);
|
||||
this.showAlert(this.$t('CONTACT_PANEL.UNMUTED_SUCCESS'));
|
||||
useAlert(this.$t('CONTACT_PANEL.UNMUTED_SUCCESS'));
|
||||
},
|
||||
toggleEmailActionsModal() {
|
||||
this.showEmailActionsModal = !this.showEmailActionsModal;
|
||||
|
||||
@@ -153,7 +153,8 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
|
||||
import CannedResponse from './CannedResponse.vue';
|
||||
@@ -180,10 +181,8 @@ import {
|
||||
import WhatsappTemplates from './WhatsappTemplates/Modal.vue';
|
||||
import { MESSAGE_MAX_LENGTH } from 'shared/helpers/MessageTypeHelper';
|
||||
import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { trimContent, debounce } from '@chatwoot/utils';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
import rtlMixin from 'shared/mixins/rtlMixin';
|
||||
import fileUploadMixin from 'dashboard/mixins/fileUploadMixin';
|
||||
@@ -218,8 +217,6 @@ export default {
|
||||
},
|
||||
mixins: [
|
||||
inboxMixin,
|
||||
uiSettingsMixin,
|
||||
alertMixin,
|
||||
messageFormatterMixin,
|
||||
rtlMixin,
|
||||
fileUploadMixin,
|
||||
@@ -231,6 +228,21 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
isEditorHotKeyEnabled,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
} = useUISettings();
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
isEditorHotKeyEnabled,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
message: '',
|
||||
@@ -310,7 +322,7 @@ export default {
|
||||
agentId,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_AGENT'));
|
||||
useAlert(this.$t('CONVERSATION.CHANGE_AGENT'));
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -406,7 +418,7 @@ export default {
|
||||
if (this.isPrivate) {
|
||||
sendMessageText = this.$t('CONVERSATION.REPLYBOX.CREATE');
|
||||
}
|
||||
const keyLabel = isEditorHotKeyEnabled(this.uiSettings, 'cmd_enter')
|
||||
const keyLabel = this.isEditorHotKeyEnabled('cmd_enter')
|
||||
? '(⌘ + ↵)'
|
||||
: '(↵)';
|
||||
return `${sendMessageText} ${keyLabel}`;
|
||||
@@ -479,7 +491,7 @@ export default {
|
||||
return !!this.signatureToApply;
|
||||
},
|
||||
sendWithSignature() {
|
||||
return this.fetchSignatureFlagFromUiSettings(this.channelType);
|
||||
return this.fetchSignatureFlagFromUISettings(this.channelType);
|
||||
},
|
||||
editorMessageKey() {
|
||||
const { editor_message_key: isEnabled } = this.uiSettings;
|
||||
@@ -748,7 +760,7 @@ export default {
|
||||
!this.showCannedMenu &&
|
||||
!this.showVariablesMenu &&
|
||||
this.isFocused &&
|
||||
isEditorHotKeyEnabled(this.uiSettings, selectedKey)
|
||||
this.isEditorHotKeyEnabled(selectedKey)
|
||||
);
|
||||
},
|
||||
onPaste(e) {
|
||||
@@ -880,7 +892,7 @@ export default {
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error?.response?.data?.error || this.$t('CONVERSATION.MESSAGE_ERROR');
|
||||
this.showAlert(errorMessage);
|
||||
useAlert(errorMessage);
|
||||
}
|
||||
},
|
||||
async onSendWhatsAppReply(messagePayload) {
|
||||
|
||||
@@ -77,10 +77,10 @@
|
||||
import { MESSAGE_TYPE, MESSAGE_STATUS } from 'shared/constants/messages';
|
||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||
import { mapGetters } from 'vuex';
|
||||
import timeMixin from '../../../../mixins/time';
|
||||
import { messageTimestamp } from 'shared/helpers/timeHelper';
|
||||
|
||||
export default {
|
||||
mixins: [inboxMixin, timeMixin],
|
||||
mixins: [inboxMixin],
|
||||
props: {
|
||||
sender: {
|
||||
type: Object,
|
||||
@@ -159,7 +159,7 @@ export default {
|
||||
return MESSAGE_STATUS.SENT === this.messageStatus;
|
||||
},
|
||||
readableTime() {
|
||||
return this.messageTimestamp(this.createdAt, 'LLL d, h:mm a');
|
||||
return messageTimestamp(this.createdAt, 'LLL d, h:mm a');
|
||||
},
|
||||
screenName() {
|
||||
const { additional_attributes: additionalAttributes = {} } =
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import {
|
||||
DuplicateContactException,
|
||||
ExceptionWithMessage,
|
||||
} from 'shared/helpers/CustomErrors';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
@@ -52,18 +51,18 @@ export default {
|
||||
'contacts/create',
|
||||
this.getContactObject()
|
||||
);
|
||||
this.showAlert(this.$t('CONTACT_FORM.SUCCESS_MESSAGE'));
|
||||
useAlert(this.$t('CONTACT_FORM.SUCCESS_MESSAGE'));
|
||||
}
|
||||
this.openContactNewTab(contact.id);
|
||||
} catch (error) {
|
||||
if (error instanceof DuplicateContactException) {
|
||||
if (error.data.includes('phone_number')) {
|
||||
this.showAlert(this.$t('CONTACT_FORM.FORM.PHONE_NUMBER.DUPLICATE'));
|
||||
useAlert(this.$t('CONTACT_FORM.FORM.PHONE_NUMBER.DUPLICATE'));
|
||||
}
|
||||
} else if (error instanceof ExceptionWithMessage) {
|
||||
this.showAlert(error.data);
|
||||
useAlert(error.data);
|
||||
} else {
|
||||
this.showAlert(this.$t('CONTACT_FORM.ERROR_MESSAGE'));
|
||||
useAlert(this.$t('CONTACT_FORM.ERROR_MESSAGE'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -40,6 +40,7 @@ const ALLOWED_FILE_TYPES = {
|
||||
IMAGE: 'image',
|
||||
VIDEO: 'video',
|
||||
AUDIO: 'audio',
|
||||
IG_REEL: 'ig_reel',
|
||||
};
|
||||
|
||||
export default {
|
||||
@@ -66,7 +67,10 @@ export default {
|
||||
return this.attachment.file_type === ALLOWED_FILE_TYPES.IMAGE;
|
||||
},
|
||||
isVideo() {
|
||||
return this.attachment.file_type === ALLOWED_FILE_TYPES.VIDEO;
|
||||
return (
|
||||
this.attachment.file_type === ALLOWED_FILE_TYPES.VIDEO ||
|
||||
this.attachment.file_type === ALLOWED_FILE_TYPES.IG_REEL
|
||||
);
|
||||
},
|
||||
isAudio() {
|
||||
return this.attachment.file_type === ALLOWED_FILE_TYPES.AUDIO;
|
||||
|
||||
+2
-3
@@ -31,10 +31,9 @@
|
||||
<script>
|
||||
import DyteAPI from 'dashboard/api/integrations/dyte';
|
||||
import { buildDyteURL } from 'shared/helpers/IntegrationHelper';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
messageId: {
|
||||
type: Number,
|
||||
@@ -61,7 +60,7 @@ export default {
|
||||
await DyteAPI.addParticipantToMeeting(this.messageId);
|
||||
this.dyteAuthToken = authToken;
|
||||
} catch (err) {
|
||||
this.showAlert(this.$t('INTEGRATION_SETTINGS.DYTE.JOIN_ERROR'));
|
||||
useAlert(this.$t('INTEGRATION_SETTINGS.DYTE.JOIN_ERROR'));
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
+10
-6
@@ -12,7 +12,7 @@
|
||||
@click="onClose"
|
||||
>
|
||||
<div
|
||||
class="bg-white dark:bg-slate-900 z-10 flex items-center justify-between w-full h-16 px-6 py-2"
|
||||
class="z-10 flex items-center justify-between w-full h-16 px-6 py-2 bg-white dark:bg-slate-900"
|
||||
@click.stop
|
||||
>
|
||||
<div
|
||||
@@ -167,7 +167,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center w-full h-16 px-6 py-2 z-10">
|
||||
<div class="z-10 flex items-center justify-center w-full h-16 px-6 py-2">
|
||||
<div
|
||||
class="items-center rounded-sm flex font-semibold justify-center min-w-[5rem] p-1 bg-slate-25 dark:bg-slate-800 text-slate-600 dark:text-slate-200 text-sm"
|
||||
>
|
||||
@@ -182,13 +182,14 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import timeMixin from 'dashboard/mixins/time';
|
||||
import { messageTimestamp } from 'shared/helpers/timeHelper';
|
||||
|
||||
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||
|
||||
const ALLOWED_FILE_TYPES = {
|
||||
IMAGE: 'image',
|
||||
VIDEO: 'video',
|
||||
IG_REEL: 'ig_reel',
|
||||
AUDIO: 'audio',
|
||||
};
|
||||
|
||||
@@ -199,7 +200,7 @@ export default {
|
||||
components: {
|
||||
Thumbnail,
|
||||
},
|
||||
mixins: [keyboardEventListenerMixins, timeMixin],
|
||||
mixins: [keyboardEventListenerMixins],
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
@@ -236,13 +237,16 @@ export default {
|
||||
readableTime() {
|
||||
const { created_at: createdAt } = this.activeAttachment;
|
||||
if (!createdAt) return '';
|
||||
return this.messageTimestamp(createdAt, 'LLL d yyyy, h:mm a') || '';
|
||||
return messageTimestamp(createdAt, 'LLL d yyyy, h:mm a') || '';
|
||||
},
|
||||
isImage() {
|
||||
return this.activeFileType === ALLOWED_FILE_TYPES.IMAGE;
|
||||
},
|
||||
isVideo() {
|
||||
return this.activeFileType === ALLOWED_FILE_TYPES.VIDEO;
|
||||
return (
|
||||
this.activeFileType === ALLOWED_FILE_TYPES.VIDEO ||
|
||||
this.activeFileType === ALLOWED_FILE_TYPES.IG_REEL
|
||||
);
|
||||
},
|
||||
isAudio() {
|
||||
return this.activeFileType === ALLOWED_FILE_TYPES.AUDIO;
|
||||
|
||||
@@ -85,11 +85,11 @@ describe('MoveActions', () => {
|
||||
it('shows alert', async () => {
|
||||
await moreActions.find('button:first-child').trigger('click');
|
||||
|
||||
expect(emitter.emit).toBeCalledWith(
|
||||
'newToastMessage',
|
||||
'This contact is blocked successfully. You will not be notified of any future conversations.',
|
||||
undefined
|
||||
);
|
||||
expect(emitter.emit).toBeCalledWith('newToastMessage', {
|
||||
message:
|
||||
'This contact is blocked successfully. You will not be notified of any future conversations.',
|
||||
action: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,11 +111,10 @@ describe('MoveActions', () => {
|
||||
it('shows alert', async () => {
|
||||
await moreActions.find('button:first-child').trigger('click');
|
||||
|
||||
expect(emitter.emit).toBeCalledWith(
|
||||
'newToastMessage',
|
||||
'This contact is unblocked successfully.',
|
||||
undefined
|
||||
);
|
||||
expect(emitter.emit).toBeCalledWith('newToastMessage', {
|
||||
message: 'This contact is unblocked successfully.',
|
||||
action: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
|
||||
/**
|
||||
* Custom hook to track events
|
||||
* @returns {Function} The track function
|
||||
*/
|
||||
export const useTrack = () => {
|
||||
const vm = getCurrentInstance();
|
||||
if (!vm) throw new Error('must be called in setup');
|
||||
@@ -8,6 +12,11 @@ export const useTrack = () => {
|
||||
return vm.proxy.$track;
|
||||
};
|
||||
|
||||
export function useAlert(message, action) {
|
||||
emitter.emit('newToastMessage', message, action);
|
||||
}
|
||||
/**
|
||||
* Emits a toast message event using a global emitter.
|
||||
* @param {string} message - The message to be displayed in the toast.
|
||||
* @param {Object|null} action - Optional callback function or object to execute.
|
||||
*/
|
||||
export const useAlert = (message, action = null) => {
|
||||
emitter.emit('newToastMessage', { message, action });
|
||||
};
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
import { useTrack, useAlert } from '../index';
|
||||
|
||||
vi.mock('vue', () => ({
|
||||
getCurrentInstance: vi.fn(),
|
||||
}));
|
||||
vi.mock('shared/helpers/mitt', () => ({
|
||||
emitter: {
|
||||
emit: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('useTrack', () => {
|
||||
it('should return $track from the current instance proxy', () => {
|
||||
const mockProxy = { $track: vi.fn() };
|
||||
getCurrentInstance.mockReturnValue({ proxy: mockProxy });
|
||||
const track = useTrack();
|
||||
expect(track).toBe(mockProxy.$track);
|
||||
});
|
||||
|
||||
it('should throw an error if called outside of setup', () => {
|
||||
getCurrentInstance.mockReturnValue(null);
|
||||
expect(useTrack).toThrowError('must be called in setup');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useAlert', () => {
|
||||
it('should emit a newToastMessage event with the provided message and action', () => {
|
||||
const message = 'Toast message';
|
||||
const action = {
|
||||
type: 'link',
|
||||
to: '/app/accounts/1/conversations/1',
|
||||
message: 'Navigate',
|
||||
};
|
||||
useAlert(message, action);
|
||||
expect(emitter.emit).toHaveBeenCalledWith('newToastMessage', {
|
||||
message,
|
||||
action,
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit a newToastMessage event with the provided message and no action if action is null', () => {
|
||||
const message = 'Toast message';
|
||||
useAlert(message);
|
||||
expect(emitter.emit).toHaveBeenCalledWith('newToastMessage', {
|
||||
message,
|
||||
action: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { ref } from 'vue';
|
||||
import { useAdmin } from '../useAdmin';
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
vi.mock('dashboard/composables/store');
|
||||
|
||||
describe('useAdmin', () => {
|
||||
it('returns true if the current user is an administrator', () => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentRole: ref('administrator'),
|
||||
});
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
expect(isAdmin.value).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if the current user is not an administrator', () => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentRole: ref('user'),
|
||||
});
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
expect(isAdmin.value).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if the current user role is null', () => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentRole: ref(null),
|
||||
});
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
expect(isAdmin.value).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if the current user role is undefined', () => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentRole: ref(undefined),
|
||||
});
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
expect(isAdmin.value).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if the current user role is an empty string', () => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentRole: ref(''),
|
||||
});
|
||||
|
||||
const { isAdmin } = useAdmin();
|
||||
expect(isAdmin.value).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
import { ref } from 'vue';
|
||||
import {
|
||||
useUISettings,
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
} from 'dashboard/composables/useUISettings';
|
||||
|
||||
// Mocking the store composables
|
||||
const mockDispatch = vi.fn();
|
||||
|
||||
const getUISettingsMock = ref({
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order: DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
editor_message_key: 'enter',
|
||||
});
|
||||
|
||||
vi.mock('dashboard/composables/store', () => ({
|
||||
useStoreGetters: () => ({
|
||||
getUISettings: getUISettingsMock,
|
||||
}),
|
||||
useStore: () => ({
|
||||
dispatch: mockDispatch,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useUISettings', () => {
|
||||
beforeEach(() => {
|
||||
mockDispatch.mockClear();
|
||||
});
|
||||
|
||||
it('returns uiSettings', () => {
|
||||
const { uiSettings } = useUISettings();
|
||||
expect(uiSettings.value).toEqual({
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order:
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
editor_message_key: 'enter',
|
||||
});
|
||||
});
|
||||
|
||||
it('updates UI settings correctly', () => {
|
||||
const { updateUISettings } = useUISettings();
|
||||
updateUISettings({ enter_to_send_enabled: true });
|
||||
expect(mockDispatch).toHaveBeenCalledWith('updateUISettings', {
|
||||
uiSettings: {
|
||||
enter_to_send_enabled: true,
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order:
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
editor_message_key: 'enter',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('toggles sidebar UI state correctly', () => {
|
||||
const { toggleSidebarUIState } = useUISettings();
|
||||
toggleSidebarUIState('is_ct_labels_open');
|
||||
expect(mockDispatch).toHaveBeenCalledWith('updateUISettings', {
|
||||
uiSettings: {
|
||||
is_ct_labels_open: false,
|
||||
conversation_sidebar_items_order:
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
editor_message_key: 'enter',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns correct conversation sidebar items order', () => {
|
||||
const { conversationSidebarItemsOrder } = useUISettings();
|
||||
expect(conversationSidebarItemsOrder.value).toEqual(
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct contact sidebar items order', () => {
|
||||
const { contactSidebarItemsOrder } = useUISettings();
|
||||
expect(contactSidebarItemsOrder.value).toEqual(
|
||||
DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct value for isContactSidebarItemOpen', () => {
|
||||
const { isContactSidebarItemOpen } = useUISettings();
|
||||
expect(isContactSidebarItemOpen('is_ct_labels_open')).toBe(true);
|
||||
expect(isContactSidebarItemOpen('non_existent_key')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets signature flag for inbox correctly', () => {
|
||||
const { setSignatureFlagForInbox } = useUISettings();
|
||||
setSignatureFlagForInbox('email', true);
|
||||
expect(mockDispatch).toHaveBeenCalledWith('updateUISettings', {
|
||||
uiSettings: {
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order:
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
email_signature_enabled: true,
|
||||
editor_message_key: 'enter',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('fetches signature flag from UI settings correctly', () => {
|
||||
const { fetchSignatureFlagFromUISettings } = useUISettings();
|
||||
expect(fetchSignatureFlagFromUISettings('email')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('returns correct value for isEditorHotKeyEnabled when editor_message_key is configured', () => {
|
||||
getUISettingsMock.value.enter_to_send_enabled = false;
|
||||
const { isEditorHotKeyEnabled } = useUISettings();
|
||||
expect(isEditorHotKeyEnabled('enter')).toBe(true);
|
||||
expect(isEditorHotKeyEnabled('cmd_enter')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns correct value for isEditorHotKeyEnabled when editor_message_key is not configured', () => {
|
||||
getUISettingsMock.value.editor_message_key = undefined;
|
||||
const { isEditorHotKeyEnabled } = useUISettings();
|
||||
expect(isEditorHotKeyEnabled('enter')).toBe(false);
|
||||
expect(isEditorHotKeyEnabled('cmd_enter')).toBe(true);
|
||||
});
|
||||
|
||||
it('handles non-existent keys', () => {
|
||||
const {
|
||||
isContactSidebarItemOpen,
|
||||
fetchSignatureFlagFromUISettings,
|
||||
isEditorHotKeyEnabled,
|
||||
} = useUISettings();
|
||||
expect(isContactSidebarItemOpen('non_existent_key')).toBe(false);
|
||||
expect(fetchSignatureFlagFromUISettings('non_existent_key')).toBe(
|
||||
undefined
|
||||
);
|
||||
expect(isEditorHotKeyEnabled('non_existent_key')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { computed } from 'vue';
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
/**
|
||||
* Composable to determine if the current user is an administrator.
|
||||
* @returns {Boolean} - True if the current user is an administrator, false otherwise.
|
||||
*/
|
||||
export function useAdmin() {
|
||||
const getters = useStoreGetters();
|
||||
|
||||
const currentUserRole = computed(() => getters.getCurrentRole.value);
|
||||
const isAdmin = computed(() => currentUserRole.value === 'administrator');
|
||||
|
||||
return {
|
||||
isAdmin,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
import { computed } from 'vue';
|
||||
import { useStore, useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
export const DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER = Object.freeze([
|
||||
{ name: 'conversation_actions' },
|
||||
{ name: 'macros' },
|
||||
{ name: 'conversation_info' },
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'previous_conversation' },
|
||||
{ name: 'conversation_participants' },
|
||||
]);
|
||||
|
||||
export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = Object.freeze([
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'contact_labels' },
|
||||
{ name: 'previous_conversation' },
|
||||
]);
|
||||
|
||||
/**
|
||||
* Slugifies the channel name.
|
||||
* Replaces spaces, hyphens, and double colons with underscores.
|
||||
* @param {string} name - The channel name to slugify.
|
||||
* @returns {string} The slugified channel name.
|
||||
*/
|
||||
const slugifyChannel = name =>
|
||||
name?.toLowerCase().replace(' ', '_').replace('-', '_').replace('::', '_');
|
||||
|
||||
/**
|
||||
* Computes the order of items in the conversation sidebar, using defaults if not present.
|
||||
* @param {Object} uiSettings - Reactive UI settings object.
|
||||
* @returns {Array} Ordered list of sidebar items.
|
||||
*/
|
||||
const useConversationSidebarItemsOrder = uiSettings => {
|
||||
return computed(() => {
|
||||
const { conversation_sidebar_items_order: itemsOrder } = uiSettings.value;
|
||||
// If the sidebar order is not set, use the default order.
|
||||
if (!itemsOrder) {
|
||||
return DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER;
|
||||
}
|
||||
// Create a copy of itemsOrder to avoid mutating the original store object.
|
||||
const itemsOrderCopy = [...itemsOrder];
|
||||
// If the sidebar order doesn't have the new elements, then add them to the list.
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER.forEach(item => {
|
||||
if (!itemsOrderCopy.find(i => i.name === item.name)) {
|
||||
itemsOrderCopy.push(item);
|
||||
}
|
||||
});
|
||||
return itemsOrderCopy;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the order of items in the contact sidebar,using defaults if not present.
|
||||
* @param {Object} uiSettings - Reactive UI settings object.
|
||||
* @returns {Array} Ordered list of sidebar items.
|
||||
*/
|
||||
const useContactSidebarItemsOrder = uiSettings => {
|
||||
return computed(() => {
|
||||
const { contact_sidebar_items_order: itemsOrder } = uiSettings.value;
|
||||
return itemsOrder || DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles the open state of a sidebar item.
|
||||
* @param {string} key - The key of the sidebar item to toggle.
|
||||
* @param {Object} uiSettings - Reactive UI settings object.
|
||||
* @param {Function} updateUISettings - Function to update UI settings.
|
||||
*/
|
||||
const toggleSidebarUIState = (key, uiSettings, updateUISettings) => {
|
||||
updateUISettings({ [key]: !uiSettings.value[key] });
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the signature flag for a specific channel type in the inbox settings.
|
||||
* @param {string} channelType - The type of the channel.
|
||||
* @param {boolean} value - The value to set for the signature enabled flag.
|
||||
* @param {Function} updateUISettings - Function to update UI settings.
|
||||
*/
|
||||
const setSignatureFlagForInbox = (channelType, value, updateUISettings) => {
|
||||
if (!channelType) return;
|
||||
|
||||
const slugifiedChannel = slugifyChannel(channelType);
|
||||
updateUISettings({ [`${slugifiedChannel}_signature_enabled`]: value });
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the signature flag for a specific channel type from UI settings.
|
||||
* @param {string} channelType - The type of the channel.
|
||||
* @param {Object} uiSettings - Reactive UI settings object.
|
||||
* @returns {boolean} The value of the signature enabled flag.
|
||||
*/
|
||||
const fetchSignatureFlagFromUISettings = (channelType, uiSettings) => {
|
||||
if (!channelType) return false;
|
||||
|
||||
const slugifiedChannel = slugifyChannel(channelType);
|
||||
return uiSettings.value[`${slugifiedChannel}_signature_enabled`];
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a specific editor hotkey is enabled.
|
||||
* @param {string} key - The key to check.
|
||||
* @param {Object} uiSettings - Reactive UI settings object.
|
||||
* @returns {boolean} True if the hotkey is enabled, otherwise false.
|
||||
*/
|
||||
const isEditorHotKeyEnabled = (key, uiSettings) => {
|
||||
const {
|
||||
editor_message_key: editorMessageKey,
|
||||
enter_to_send_enabled: enterToSendEnabled,
|
||||
} = uiSettings.value || {};
|
||||
if (!editorMessageKey) {
|
||||
return key === (enterToSendEnabled ? 'enter' : 'cmd_enter');
|
||||
}
|
||||
return editorMessageKey === key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main composable function for managing UI settings.
|
||||
* @returns {Object} An object containing reactive properties and methods for UI settings management.
|
||||
*/
|
||||
export function useUISettings() {
|
||||
const getters = useStoreGetters();
|
||||
const store = useStore();
|
||||
const uiSettings = computed(() => getters.getUISettings.value);
|
||||
|
||||
const updateUISettings = (settings = {}) => {
|
||||
store.dispatch('updateUISettings', {
|
||||
uiSettings: {
|
||||
...uiSettings.value,
|
||||
...settings,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
uiSettings,
|
||||
updateUISettings,
|
||||
conversationSidebarItemsOrder: useConversationSidebarItemsOrder(uiSettings),
|
||||
contactSidebarItemsOrder: useContactSidebarItemsOrder(uiSettings),
|
||||
isContactSidebarItemOpen: key => !!uiSettings.value[key],
|
||||
toggleSidebarUIState: key =>
|
||||
toggleSidebarUIState(key, uiSettings, updateUISettings),
|
||||
setSignatureFlagForInbox: (channelType, value) =>
|
||||
setSignatureFlagForInbox(channelType, value, updateUISettings),
|
||||
fetchSignatureFlagFromUISettings: channelType =>
|
||||
fetchSignatureFlagFromUISettings(channelType, uiSettings),
|
||||
isEditorHotKeyEnabled: key => isEditorHotKeyEnabled(key, uiSettings),
|
||||
};
|
||||
}
|
||||
@@ -38,9 +38,10 @@ export class AnalyticsHelper {
|
||||
* @param {Object} user - User object
|
||||
*/
|
||||
identify(user) {
|
||||
if (!this.analytics) {
|
||||
if (!this.analytics || !user) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
this.analytics.identify(this.user.email, {
|
||||
userId: this.user.id,
|
||||
|
||||
@@ -52,6 +52,10 @@ class DashboardAudioNotificationHelper {
|
||||
};
|
||||
|
||||
executeRecurringNotification = () => {
|
||||
if (!window.WOOT || !window.WOOT.$store) {
|
||||
this.clearSetTimeout();
|
||||
return;
|
||||
}
|
||||
const mineConversation = window.WOOT.$store.getters.getMineChats({
|
||||
assigneeType: 'me',
|
||||
status: 'open',
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
const SCRIPT_TYPE = 'text/javascript';
|
||||
const DATA_LOADED_ATTR = 'data-loaded';
|
||||
const SCRIPT_PROPERTIES = [
|
||||
'defer',
|
||||
'crossOrigin',
|
||||
'noModule',
|
||||
'referrerPolicy',
|
||||
'id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Custom error class for script loading failures.
|
||||
* @extends Error
|
||||
*/
|
||||
class ScriptLoaderError extends Error {
|
||||
/**
|
||||
* Creates a new ScriptLoaderError.
|
||||
* @param {string} src - The source URL of the script that failed to load.
|
||||
* @param {string} message - The error message.
|
||||
*/
|
||||
constructor(src, message = 'Failed to load script') {
|
||||
super(message);
|
||||
this.name = 'ScriptLoaderError';
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets detailed error information.
|
||||
* @returns {string} A string containing the error details.
|
||||
*/
|
||||
getErrorDetails() {
|
||||
return `Failed to load script from source: ${this.src}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new script element with the specified attributes.
|
||||
* @param {string} src - The source URL of the script.
|
||||
* @param {Object} options - Options for configuring the script element.
|
||||
* @param {string} [options.type='text/javascript'] - The type of the script.
|
||||
* @param {boolean} [options.async=true] - Whether the script should load asynchronously.
|
||||
* @param {boolean} [options.defer] - Whether the script execution should be deferred.
|
||||
* @param {string} [options.crossOrigin] - The CORS setting for the script.
|
||||
* @param {boolean} [options.noModule] - Whether the script should not be treated as a JavaScript module.
|
||||
* @param {string} [options.referrerPolicy] - The referrer policy for the script.
|
||||
* @param {string} [options.id] - The id attribute for the script element.
|
||||
* @param {Object} [options.attrs] - Additional attributes to set on the script element.
|
||||
* @returns {HTMLScriptElement} The created script element.
|
||||
*/
|
||||
const createScriptElement = (src, options) => {
|
||||
const el = document.createElement('script');
|
||||
el.type = options.type || SCRIPT_TYPE;
|
||||
el.async = options.async !== false;
|
||||
el.src = src;
|
||||
|
||||
SCRIPT_PROPERTIES.forEach(property => {
|
||||
if (property in options) {
|
||||
el[property] = options[property];
|
||||
}
|
||||
});
|
||||
|
||||
Object.entries(options.attrs || {}).forEach(([name, value]) =>
|
||||
el.setAttribute(name, value)
|
||||
);
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds an existing script element with the specified source URL.
|
||||
* @param {string} src - The source URL to search for.
|
||||
* @returns {HTMLScriptElement|null} The found script element, or null if not found.
|
||||
*/
|
||||
const findExistingScript = src => {
|
||||
return document.querySelector(`script[src="${src}"]`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads a script asynchronously and returns a promise.
|
||||
* @param {string} src - The source URL of the script to load.
|
||||
* @param {Object} options - Options for configuring the script element.
|
||||
* @param {string} [options.type='text/javascript'] - The type of the script.
|
||||
* @param {boolean} [options.async=true] - Whether the script should load asynchronously.
|
||||
* @param {boolean} [options.defer] - Whether the script execution should be deferred.
|
||||
* @param {string} [options.crossOrigin] - The CORS setting for the script.
|
||||
* @param {boolean} [options.noModule] - Whether the script should not be treated as a JavaScript module.
|
||||
* @param {string} [options.referrerPolicy] - The referrer policy for the script.
|
||||
* @param {string} [options.id] - The id attribute for the script element.
|
||||
* @param {Object} [options.attrs] - Additional attributes to set on the script element.
|
||||
* @returns {Promise<HTMLScriptElement|boolean>} A promise that resolves with the loaded script element,
|
||||
* or false if the script couldn't be loaded.
|
||||
* @throws {ScriptLoaderError} If the script fails to load.
|
||||
*/
|
||||
export async function loadScript(src, options) {
|
||||
if (typeof window === 'undefined' || !window.document) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof src !== 'string' || src.trim() === '') {
|
||||
reject(new Error('Invalid source URL provided'));
|
||||
return;
|
||||
}
|
||||
|
||||
let el = findExistingScript(src);
|
||||
|
||||
if (!el) {
|
||||
el = createScriptElement(src, options);
|
||||
document.head.appendChild(el);
|
||||
} else if (el.hasAttribute(DATA_LOADED_ATTR)) {
|
||||
resolve(el);
|
||||
return;
|
||||
}
|
||||
|
||||
const handleError = () => reject(new ScriptLoaderError(src));
|
||||
|
||||
el.addEventListener('error', handleError);
|
||||
el.addEventListener('abort', handleError);
|
||||
el.addEventListener('load', () => {
|
||||
el.setAttribute(DATA_LOADED_ATTR, 'true');
|
||||
resolve(el);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -73,7 +73,14 @@ class ActionCableConnector extends BaseActionCableConnector {
|
||||
const { id } = payload;
|
||||
if (id) {
|
||||
this.app.$store.dispatch('updateConversation', payload);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'[Chatwoot] Skipping assignee change event with payload: ',
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
this.fetchConversationStats();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
const FEATURE_HELP_URLS = {
|
||||
channel_email: 'https://chwt.app/hc/email',
|
||||
channel_facebook: 'https://chwt.app/hc/fb',
|
||||
help_center: 'https://chwt.app/hc/help-center',
|
||||
agent_bots: 'https://chwt.app/hc/agent-bots',
|
||||
team_management: 'https://chwt.app/hc/teams',
|
||||
labels: 'https://chwt.app/hc/labels',
|
||||
custom_attributes: 'https://chwt.app/hc/custom-attributes',
|
||||
canned_responses: 'https://chwt.app/hc/canned',
|
||||
integrations: 'https://chwt.app/hc/integrations',
|
||||
campaigns: 'https://chwt.app/hc/campaigns',
|
||||
reports: 'https://chwt.app/hc/reports',
|
||||
message_reply_to: 'https://chwt.app/hc/reply-to',
|
||||
sla: 'https://chwt.app/hc/sla',
|
||||
dashboard_apps: 'https://chwt.app/hc/dashboard-apps',
|
||||
};
|
||||
|
||||
export function getHelpUrlForFeature(featureName) {
|
||||
const { helpUrls } = window.chatwootConfig;
|
||||
return helpUrls[featureName];
|
||||
return FEATURE_HELP_URLS[featureName];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-console */
|
||||
import NotificationSubscriptions from '../api/notificationSubscription';
|
||||
import auth from '../api/auth';
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export const verifyServiceWorkerExistence = (callback = () => {}) => {
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
@@ -69,19 +69,13 @@ export const registerSubscription = (onSuccess = () => {}) => {
|
||||
onSuccess();
|
||||
})
|
||||
.catch(() => {
|
||||
emitter.emit(
|
||||
'newToastMessage',
|
||||
'This browser does not support desktop notification'
|
||||
);
|
||||
useAlert('This browser does not support desktop notification');
|
||||
});
|
||||
};
|
||||
|
||||
export const requestPushPermissions = ({ onSuccess }) => {
|
||||
if (!('Notification' in window)) {
|
||||
emitter.emit(
|
||||
'newToastMessage',
|
||||
'This browser does not support desktop notification'
|
||||
);
|
||||
useAlert('This browser does not support desktop notification');
|
||||
} else if (Notification.permission === 'granted') {
|
||||
registerSubscription(onSuccess);
|
||||
} else if (Notification.permission !== 'denied') {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { loadScript } from '../DOMHelpers';
|
||||
import { JSDOM } from 'jsdom';
|
||||
|
||||
describe('loadScript', () => {
|
||||
let dom;
|
||||
let window;
|
||||
let document;
|
||||
|
||||
beforeEach(() => {
|
||||
dom = new JSDOM('<!DOCTYPE html><html><head></head><body></body></html>', {
|
||||
url: 'http://localhost',
|
||||
});
|
||||
window = dom.window;
|
||||
document = window.document;
|
||||
global.document = document;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
delete global.document;
|
||||
});
|
||||
|
||||
it('should load a script successfully', async () => {
|
||||
const src = 'https://example.com/script.js';
|
||||
const loadPromise = loadScript(src, {});
|
||||
|
||||
// Simulate successful script load
|
||||
setTimeout(() => {
|
||||
const script = document.querySelector(`script[src="${src}"]`);
|
||||
if (script) {
|
||||
script.dispatchEvent(new window.Event('load'));
|
||||
}
|
||||
}, 0);
|
||||
|
||||
const script = await loadPromise;
|
||||
|
||||
expect(script).toBeTruthy();
|
||||
expect(script.getAttribute('src')).toBe(src);
|
||||
expect(script.getAttribute('data-loaded')).toBe('true');
|
||||
});
|
||||
|
||||
it('should not load a script if document is not available', async () => {
|
||||
delete global.document;
|
||||
const result = await loadScript('https://example.com/script.js', {});
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should use an existing script if already present', async () => {
|
||||
const src = 'https://example.com/existing-script.js';
|
||||
const existingScript = document.createElement('script');
|
||||
existingScript.src = src;
|
||||
existingScript.setAttribute('data-loaded', 'true');
|
||||
document.head.appendChild(existingScript);
|
||||
|
||||
const script = await loadScript(src, {});
|
||||
|
||||
expect(script).toBe(existingScript);
|
||||
});
|
||||
|
||||
it('should set custom attributes on the script element', async () => {
|
||||
const src = 'https://example.com/custom-script.js';
|
||||
const options = {
|
||||
type: 'module',
|
||||
async: false,
|
||||
defer: true,
|
||||
crossOrigin: 'anonymous',
|
||||
noModule: true,
|
||||
referrerPolicy: 'origin',
|
||||
id: 'custom-script',
|
||||
attrs: { 'data-custom': 'value' },
|
||||
};
|
||||
|
||||
const loadPromise = loadScript(src, options);
|
||||
|
||||
// Simulate successful script load
|
||||
setTimeout(() => {
|
||||
const script = document.querySelector(`script[src="${src}"]`);
|
||||
if (script) {
|
||||
script.dispatchEvent(new window.Event('load'));
|
||||
}
|
||||
}, 0);
|
||||
|
||||
const script = await loadPromise;
|
||||
|
||||
expect(script.type).toBe('module');
|
||||
expect(script.async).toBe(false);
|
||||
expect(script.defer).toBe(true);
|
||||
expect(script.crossOrigin).toBe('anonymous');
|
||||
expect(script.noModule).toBe(true);
|
||||
expect(script.referrerPolicy).toBe('origin');
|
||||
expect(script.id).toBe('custom-script');
|
||||
expect(script.getAttribute('data-custom')).toBe('value');
|
||||
});
|
||||
});
|
||||
@@ -33,7 +33,7 @@
|
||||
"NONE": "None",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,9 @@
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"OFFLINE": "Offline"
|
||||
"OFFLINE": "Offline",
|
||||
"RECONNECTING": "Reconnecting...",
|
||||
"RECONNECT_SUCCESS": "Reconnected"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "Refresh"
|
||||
@@ -154,7 +156,7 @@
|
||||
"UNTIL_TOMORROW": "Until tomorrow",
|
||||
"UNTIL_NEXT_MONTH": "Until next month",
|
||||
"AN_HOUR_FROM_NOW": "Until an hour from now",
|
||||
"CUSTOM": "Custom...",
|
||||
"UNTIL_CUSTOM_TIME": "Custom...",
|
||||
"CHANGE_APPEARANCE": "Change Appearance",
|
||||
"LIGHT_MODE": "Light",
|
||||
"DARK_MODE": "Dark",
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
"INBOX_MGMT": {
|
||||
"HEADER": "Inboxes",
|
||||
"SIDEBAR_TXT": "<p><b>Inbox</b></p> <p> When you connect a website or a facebook Page to Chatwoot, it is called an <b>Inbox</b>. You can have unlimited inboxes in your Chatwoot account. </p><p> Click on <b>Add Inbox</b> to connect a website or a Facebook Page. </p><p> 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. </p><p> You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard. </p>",
|
||||
"RECONNECTION_REQUIRED": "Your inbox is disconnected. You won't receive new messages until you reauthorize it.",
|
||||
"CLICK_TO_RECONNECT": "Click here to reconnect.",
|
||||
"LIST": {
|
||||
"404": "There are no inboxes attached to this account."
|
||||
},
|
||||
@@ -364,6 +366,7 @@
|
||||
"TITLE": "Microsoft Email",
|
||||
"DESCRIPTION": "Click on the Sign in with Microsoft button to get started. You will redirected to the email sign in page. Once you accept the requested permissions, you would be redirected back to the inbox creation step.",
|
||||
"EMAIL_PLACEHOLDER": "Enter email address",
|
||||
"SIGN_IN": "Sign in with Microsoft",
|
||||
"HELP": "To add your Microsoft account as a channel, you need to authenticate your Microsoft account by clicking on 'Sign in with Microsoft' ",
|
||||
"ERROR_MESSAGE": "There was an error connecting to Microsoft, please try again"
|
||||
}
|
||||
|
||||
@@ -209,6 +209,87 @@
|
||||
"API_SUCCESS": "Dashboard app deleted successfully",
|
||||
"API_ERROR": "We couldn't delete the app. Please try again later"
|
||||
}
|
||||
},
|
||||
"LINEAR": {
|
||||
"ADD_OR_LINK_BUTTON": "Create/Link Linear Issue",
|
||||
"LOADING": "Fetching linear issues...",
|
||||
"LOADING_ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"CREATE": "Create",
|
||||
"LINK": {
|
||||
"SEARCH": "Search issues",
|
||||
"SELECT": "Select issue",
|
||||
"TITLE": "Link",
|
||||
"EMPTY_LIST": "No linear issues found",
|
||||
"LOADING": "Loading",
|
||||
"ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"LINK_SUCCESS": "Issue linked successfully",
|
||||
"LINK_ERROR": "There was an error linking the issue, please try again",
|
||||
"LINK_TITLE": "Conversation (#%{conversationId}) with %{name}"
|
||||
},
|
||||
"ADD_OR_LINK": {
|
||||
"TITLE": "Create/link linear issue",
|
||||
"DESCRIPTION": "Create Linear issues from conversations, or link existing ones for seamless tracking.",
|
||||
"FORM": {
|
||||
"TITLE": {
|
||||
"LABEL": "Title",
|
||||
"PLACEHOLDER": "Enter title",
|
||||
"REQUIRED_ERROR": "Title is required"
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Description",
|
||||
"PLACEHOLDER": "Enter description"
|
||||
},
|
||||
"TEAM": {
|
||||
"LABEL": "Team",
|
||||
"PLACEHOLDER": "Select team",
|
||||
"SEARCH": "Search team",
|
||||
"REQUIRED_ERROR": "Team is required"
|
||||
},
|
||||
"ASSIGNEE": {
|
||||
"LABEL": "Assignee",
|
||||
"PLACEHOLDER": "Select assignee",
|
||||
"SEARCH": "Search assignee"
|
||||
},
|
||||
"PRIORITY": {
|
||||
"LABEL": "Priority",
|
||||
"PLACEHOLDER": "Select priority",
|
||||
"SEARCH": "Search priority"
|
||||
},
|
||||
"LABEL": {
|
||||
"LABEL": "Label",
|
||||
"PLACEHOLDER": "Select label",
|
||||
"SEARCH": "Search label"
|
||||
},
|
||||
"STATUS": {
|
||||
"LABEL": "Status",
|
||||
"PLACEHOLDER": "Select status",
|
||||
"SEARCH": "Search status"
|
||||
},
|
||||
"PROJECT": {
|
||||
"LABEL": "Project",
|
||||
"PLACEHOLDER": "Select project",
|
||||
"SEARCH": "Search project"
|
||||
}
|
||||
},
|
||||
"CREATE": "Create",
|
||||
"CANCEL": "Cancel",
|
||||
"CREATE_SUCCESS": "Issue created successfully",
|
||||
"CREATE_ERROR": "There was an error creating the issue, please try again",
|
||||
"LOADING_TEAM_ERROR": "There was an error fetching the teams, please try again",
|
||||
"LOADING_TEAM_ENTITIES_ERROR": "There was an error fetching the team entities, please try again"
|
||||
},
|
||||
"ISSUE": {
|
||||
"STATUS": "Status",
|
||||
"PRIORITY": "Priority",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"LABELS": "Labels",
|
||||
"CREATED_AT": "Created at %{createdAt}"
|
||||
},
|
||||
"UNLINK": {
|
||||
"TITLE": "Unlink",
|
||||
"SUCCESS": "Issue unlinked successfully",
|
||||
"ERROR": "There was an error unlinking the issue, please try again"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
"SLA": "SLA",
|
||||
"BETA": "Beta",
|
||||
"REPORTS_OVERVIEW": "Overview",
|
||||
"FACEBOOK_REAUTHORIZE": "Your Facebook connection has expired, please reconnect your Facebook page to continue services",
|
||||
"REAUTHORIZE": "Your inbox connection has expired, please reconnect\n to continue receiving and sending messages",
|
||||
"HELP_CENTER": {
|
||||
"TITLE": "Help Center",
|
||||
"ALL_ARTICLES": "All Articles",
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"FILTER": {
|
||||
"TITLE": "تصفية المحادثات",
|
||||
"SUBTITLE": "Add your filters below and hit 'Apply filters' to cut through the chat clutter.",
|
||||
"EDIT_CUSTOM_FILTER": "Edit Folder",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
|
||||
"ADD_NEW_FILTER": "Add filter",
|
||||
"FILTER_DELETE_ERROR": "Oops, looks like we can't save nothing! Please add at least one filter to save it.",
|
||||
"SUBTITLE": "أضف عوامل التصفية أدناه واضغط على 'تطبيق الفلترة' لتجنب الفوضى في المحادثات.",
|
||||
"EDIT_CUSTOM_FILTER": "تحرير المجلد",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "أضف أو أزل الفلاتر وقم بتحديث المجلد الخاص بك.",
|
||||
"ADD_NEW_FILTER": "إضافة فلتر",
|
||||
"FILTER_DELETE_ERROR": "عذرًا، يبدو أننا لا نستطيع حفظ أي شيء! يرجى إضافة فلتر واحد على الأقل لحفظه.",
|
||||
"SUBMIT_BUTTON_LABEL": "تطبيق عامل التصفية",
|
||||
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||
"UPDATE_BUTTON_LABEL": "تحديث المجلد",
|
||||
"CANCEL_BUTTON_LABEL": "إلغاء",
|
||||
"CLEAR_BUTTON_LABEL": "Clear filters",
|
||||
"FOLDER_LABEL": "Folder Name",
|
||||
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||
"CLEAR_BUTTON_LABEL": "مسح الفلاتر",
|
||||
"FOLDER_LABEL": "اسم المجلد",
|
||||
"FOLDER_QUERY_LABEL": "استعلام المجلد",
|
||||
"EMPTY_VALUE_ERROR": "القيمة مطلوبة.",
|
||||
"TOOLTIP_LABEL": "تصفية المحادثات",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
@@ -36,15 +36,15 @@
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"STATUS": "الحالة",
|
||||
"ASSIGNEE_NAME": "Assignee name",
|
||||
"ASSIGNEE_NAME": "اسم المستلم",
|
||||
"INBOX_NAME": "اسم صندوق الوارد",
|
||||
"TEAM_NAME": "اسم الفريق",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation identifier",
|
||||
"CAMPAIGN_NAME": "Campaign name",
|
||||
"CONVERSATION_IDENTIFIER": "معرف المحادثة",
|
||||
"CAMPAIGN_NAME": "اسم الحملة",
|
||||
"LABELS": "الوسوم",
|
||||
"BROWSER_LANGUAGE": "Browser language",
|
||||
"BROWSER_LANGUAGE": "لغة المتصفح",
|
||||
"PRIORITY": "الأولوية",
|
||||
"COUNTRY_NAME": "Country name",
|
||||
"COUNTRY_NAME": "اسم الدولة",
|
||||
"REFERER_LINK": "رابط المرجع",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "القائمة",
|
||||
"CUSTOM_ATTRIBUTE_TEXT": "النص",
|
||||
@@ -55,15 +55,15 @@
|
||||
"LAST_ACTIVITY": "النشاط الأخير"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "Standard filters",
|
||||
"ADDITIONAL_FILTERS": "Additional filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom attributes"
|
||||
"STANDARD_FILTERS": "الفلاتر القياسية",
|
||||
"ADDITIONAL_FILTERS": "الفلاتر الإضافية",
|
||||
"CUSTOM_ATTRIBUTES": "الخصائص المخصصة"
|
||||
},
|
||||
"CUSTOM_VIEWS": {
|
||||
"ADD": {
|
||||
"TITLE": "هل تريد حفظ هذا الفلتر؟",
|
||||
"LABEL": "تسمية هذا الفلتر",
|
||||
"PLACEHOLDER": "Name your filter to refer it later.",
|
||||
"PLACEHOLDER": "قم بتسمية الفلتر لتتمكن من الرجوع إليه لاحقًا.",
|
||||
"ERROR_MESSAGE": "الاسم مطلوب.",
|
||||
"SAVE_BUTTON": "حفظ الفلتر",
|
||||
"CANCEL_BUTTON": "إلغاء",
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"EDIT_BUTTON": "Edit folder"
|
||||
"EDIT_BUTTON": "تحرير المجلد"
|
||||
},
|
||||
"DELETE": {
|
||||
"DELETE_BUTTON": "حذف الفلتر",
|
||||
@@ -85,7 +85,7 @@
|
||||
"CONFIRM": {
|
||||
"TITLE": "تأكيد الحذف",
|
||||
"MESSAGE": "هل أنت متأكد من حذف الفلتر ",
|
||||
"YES": "Yes, delete",
|
||||
"YES": "نعم، احذف",
|
||||
"NO": "لا، احتفظ به"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
{
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "Loading editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"HEADER": "البوتات",
|
||||
"LOADING_EDITOR": "جارٍ تحميل المحرر...",
|
||||
"HEADER_BTN_TXT": "إضافة تكوين بوت",
|
||||
"SIDEBAR_TXT": "<p><b>البوتات</b> <p>البوتات هي مثل الأعضاء الأكثر روعة في فريقك. يمكنهم التعامل مع الأمور الصغيرة، حتى تتمكن من التركيز على الأمور التي تهمك. جربهم.</p> <p> يمكنك إدارة البوتات الخاصة بك من هذه الصفحة أو إنشاء بوتات جديدة باستخدام زر 'إضافة تكوين بوت'.</p> <p> افتح <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">دليل البوتات</a> في علامة تبويب أخرى للحصول على مساعدة.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
"LABEL": "اسم البوت",
|
||||
"PLACEHOLDER": "قم بتسمية البوت الخاص بك.",
|
||||
"ERROR": "اسم البوت مطلوب."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
"LABEL": "وصف البوت",
|
||||
"PLACEHOLDER": "ماذا يفعل هذا البوت؟"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
"ERROR": "يرجى إدخال تكوين بوت CSML الخاص بك أعلاه.",
|
||||
"API_ERROR": "تكوين CSML الخاص بك غير صالح. يرجى إصلاحه والمحاولة مرة أخرى."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
"SUBMIT": "التحقق والحفظ"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"TITLE": "اختر بوت",
|
||||
"DESC": "قم بتعيين بوت لصندوق الوارد الخاص بك. يمكنهم التعامل مع المحادثات الأولية ونقلها إلى وكيل مباشر عند الضرورة.",
|
||||
"SUBMIT": "تحديث",
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
"DISCONNECT": "فصل البوت",
|
||||
"SUCCESS_MESSAGE": "تم تحديث البوت بنجاح.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "تم فصل البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث البوت. يرجى المحاولة مرة أخرى.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "تعذر فصل البوت. يرجى المحاولة مرة أخرى.",
|
||||
"SELECT_PLACEHOLDER": "اختر بوت"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"TITLE": "تكوين بوت جديد",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
"SUCCESS_MESSAGE": "تمت إضافة البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر إضافة البوت. يرجى المحاولة مرة أخرى لاحقًا."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
"404": "لم يتم العثور على أي بوتات. يمكنك إنشاء بوت بالنقر على زر 'تكوين بوت جديد' ↗",
|
||||
"LOADING": "جارٍ جلب البوتات...",
|
||||
"TYPE": "نوع البوت"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "حذف",
|
||||
"TITLE": "Delete bot",
|
||||
"TITLE": "حذف البوت",
|
||||
"SUBMIT": "حذف",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"DESCRIPTION": "هل أنت متأكد أنك تريد حذف هذا البوت؟ هذا الإجراء لا يمكن التراجع عنه.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
"SUCCESS_MESSAGE": "تم حذف البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر حذف البوت. يرجى المحاولة مرة أخرى."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "تعديل",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"LOADING": "جارٍ جلب البوتات...",
|
||||
"TITLE": "تعديل البوت",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
"SUCCESS_MESSAGE": "تم تحديث البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث البوت. يرجى المحاولة مرة أخرى."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "Webhook bot",
|
||||
"CSML": "CSML bot"
|
||||
"WEBHOOK": "بوت Webhook",
|
||||
"CSML": "بوت CSML"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@
|
||||
"IN_VALID": "مفتاح غير صالح"
|
||||
},
|
||||
"REGEX_PATTERN": {
|
||||
"LABEL": "Regex Pattern",
|
||||
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||
"LABEL": "نمط Regex",
|
||||
"PLACEHOLDER": "الرجاء إدخال سمة مخصصة ريمكس (اختياري)"
|
||||
},
|
||||
"REGEX_CUE": {
|
||||
"LABEL": "Regex Cue",
|
||||
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||
"PLACEHOLDER": "الرجاء إدخال تلميح نمط regex (اختياري)"
|
||||
},
|
||||
"ENABLE_REGEX": {
|
||||
"LABEL": "Enable regex validation"
|
||||
"LABEL": "تمكين التحقق من صحة regex"
|
||||
}
|
||||
},
|
||||
"API": {
|
||||
@@ -106,15 +106,15 @@
|
||||
"NOT_FOUND": "لا توجد سمات مخصصة تم تكوينها"
|
||||
},
|
||||
"REGEX_PATTERN": {
|
||||
"LABEL": "Regex Pattern",
|
||||
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||
"LABEL": "نمط Regex",
|
||||
"PLACEHOLDER": "الرجاء إدخال سمة مخصصة ريمكس (اختياري)"
|
||||
},
|
||||
"REGEX_CUE": {
|
||||
"LABEL": "Regex Cue",
|
||||
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||
"PLACEHOLDER": "الرجاء إدخال تلميح نمط regex (اختياري)"
|
||||
},
|
||||
"ENABLE_REGEX": {
|
||||
"LABEL": "Enable regex validation"
|
||||
"LABEL": "تمكين التحقق من صحة regex"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
{
|
||||
"AUDIT_LOGS": {
|
||||
"HEADER": "Audit Logs",
|
||||
"HEADER_BTN_TXT": "Add Audit Logs",
|
||||
"LOADING": "Fetching Audit Logs",
|
||||
"HEADER": "سجلات التدقيق",
|
||||
"HEADER_BTN_TXT": "إضافة سجلات التدقيق",
|
||||
"LOADING": "جارٍ جلب سجلات التدقيق",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام",
|
||||
"SIDEBAR_TXT": "<p><b>Audit Logs</b> </p><p> Audit Logs are trails for events and actions in a Chatwoot System. </p>",
|
||||
"SIDEBAR_TXT": "<p><b>سجلات التدقيق</b> </p><p> سجلات التدقيق هي مسارات للأحداث والإجراءات في نظام Chatwoot. </p>",
|
||||
"LIST": {
|
||||
"404": "There are no Audit Logs available in this account.",
|
||||
"TITLE": "Manage Audit Logs",
|
||||
"DESC": "Audit Logs are trails for events and actions in a Chatwoot System.",
|
||||
"404": "لا توجد سجلات تدقيق متاحة في هذا الحساب.",
|
||||
"TITLE": "إدارة سجلات التدقيق",
|
||||
"DESC": "سجلات التدقيق هي مسارات للأحداث والإجراءات في نظام Chatwoot.",
|
||||
"TABLE_HEADER": [
|
||||
"User",
|
||||
"Action",
|
||||
"المستخدم",
|
||||
"الإجراء",
|
||||
"عنوان IP"
|
||||
]
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "AuditLogs retrieved successfully",
|
||||
"SUCCESS_MESSAGE": "تم استرجاع سجلات التدقيق بنجاح",
|
||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
},
|
||||
"DEFAULT_USER": "System",
|
||||
"DEFAULT_USER": "النظام",
|
||||
"AUTOMATION_RULE": {
|
||||
"ADD": "%{agentName} created a new automation rule (#%{id})",
|
||||
"EDIT": "%{agentName} updated an automation rule (#%{id})",
|
||||
"DELETE": "%{agentName} deleted an automation rule (#%{id})"
|
||||
"ADD": "%{agentName} أنشأ قاعدة أتمتة جديدة (#%{id})",
|
||||
"EDIT": "%{agentName} قام بتحديث قاعدة أتمتة (#%{id})",
|
||||
"DELETE": "%{agentName} حذف قاعدة أتمتة (#%{id})"
|
||||
},
|
||||
"ACCOUNT_USER": {
|
||||
"ADD": "%{agentName} invited %{invitee} to the account as an %{role}",
|
||||
"ADD": "%{agentName} دعا %{invitee} إلى الحساب كـ %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} changed their %{attributes} to %{values}",
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}"
|
||||
"SELF": "%{agentName} غير %{attributes} الخاصة به إلى %{values}",
|
||||
"OTHER": "%{agentName} غير %{attributes} لـ %{user} إلى %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
"ADD": "%{agentName} created a new inbox (#%{id})",
|
||||
"EDIT": "%{agentName} updated an inbox (#%{id})",
|
||||
"DELETE": "%{agentName} deleted an inbox (#%{id})"
|
||||
"ADD": "%{agentName} أنشأ صندوق وارد جديد (#%{id})",
|
||||
"EDIT": "%{agentName} قام بتحديث صندوق الوارد (#%{id})",
|
||||
"DELETE": "%{agentName} حذف صندوق الوارد (#%{id})"
|
||||
},
|
||||
"WEBHOOK": {
|
||||
"ADD": "%{agentName} created a new webhook (#%{id})",
|
||||
"EDIT": "%{agentName} updated a webhook (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a webhook (#%{id})"
|
||||
"ADD": "%{agentName} أنشأ Webhook جديد (#%{id})",
|
||||
"EDIT": "%{agentName} قام بتحديث Webhook (#%{id})",
|
||||
"DELETE": "%{agentName} حذف Webhook (#%{id})"
|
||||
},
|
||||
"USER_ACTION": {
|
||||
"SIGN_IN": "%{agentName} signed in",
|
||||
"SIGN_OUT": "%{agentName} signed out"
|
||||
"SIGN_IN": "%{agentName} قام بتسجيل الدخول",
|
||||
"SIGN_OUT": "%{agentName} قام بتسجيل الخروج"
|
||||
},
|
||||
"TEAM": {
|
||||
"ADD": "%{agentName} created a new team (#%{id})",
|
||||
"EDIT": "%{agentName} updated a team (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a team (#%{id})"
|
||||
"ADD": "%{agentName} أنشأ فريق جديد (#%{id})",
|
||||
"EDIT": "%{agentName} قام بتحديث الفريق (#%{id})",
|
||||
"DELETE": "%{agentName} حذف الفريق (#%{id})"
|
||||
},
|
||||
"MACRO": {
|
||||
"ADD": "%{agentName} created a new macro (#%{id})",
|
||||
"EDIT": "%{agentName} updated a macro (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a macro (#%{id})"
|
||||
"ADD": "%{agentName} أنشأ ماكرو جديد (#%{id})",
|
||||
"EDIT": "%{agentName} قام بتحديث ماكرو (#%{id})",
|
||||
"DELETE": "%{agentName} حذف ماكرو (#%{id})"
|
||||
},
|
||||
"INBOX_MEMBER": {
|
||||
"ADD": "%{agentName} added %{user} to the inbox(#%{inbox_id})",
|
||||
"REMOVE": "%{agentName} removed %{user} from the inbox(#%{inbox_id})"
|
||||
"ADD": "%{agentName} أضاف %{user} إلى صندوق الوارد (#%{inbox_id})",
|
||||
"REMOVE": "%{agentName} أزال %{user} من صندوق الوارد (#%{inbox_id})"
|
||||
},
|
||||
"TEAM_MEMBER": {
|
||||
"ADD": "%{agentName} added %{user} to the team(#%{team_id})",
|
||||
"REMOVE": "%{agentName} removed %{user} from the team(#%{team_id})"
|
||||
"ADD": "%{agentName} أضاف %{user} إلى الفريق (#%{team_id})",
|
||||
"REMOVE": "%{agentName} أزال %{user} من الفريق (#%{team_id})"
|
||||
},
|
||||
"ACCOUNT": {
|
||||
"EDIT": "%{agentName} updated the account configuration (#%{id})"
|
||||
"EDIT": "%{agentName} قام بتحديث إعدادات الحساب (#%{id})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,23 +10,23 @@
|
||||
"ASSIGN_AGENT_TOOLTIP": "تعيين وكيل",
|
||||
"ASSIGN_TEAM_TOOLTIP": "تعيين فريق",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين المحادثات بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"ASSIGN_FAILED": "فشل في تعيين المحادثات، الرجاء المحاولة مرة أخرى.",
|
||||
"RESOLVE_SUCCESFUL": "تم تسوية المحادثات بنجاح.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"RESOLVE_FAILED": "فشل في حل المحادثات، يرجى المحاولة مرة أخرى.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "المحادثات المرئية في هذه الصفحة هي المحددة فقط.",
|
||||
"AGENT_LIST_LOADING": "جاري تحميل الوكلاء",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "تغيير الحالة",
|
||||
"SNOOZE_UNTIL": "غفوة",
|
||||
"UPDATE_SUCCESFUL": "تم تحديث حالة المحادثة بنجاح.",
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
"UPDATE_FAILED": "فشل تحديث المحادثات، الرجاء المحاولة مرة أخرى."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"ASSIGN_LABELS": "إضافة وسم",
|
||||
"NO_LABELS_FOUND": "لم يتم العثور على تسميات لـ",
|
||||
"ASSIGN_SELECTED_LABELS": "تعيين التسميات المحددة",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين التسميات بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
"ASSIGN_FAILED": "فشل في تعيين التسميات ، الرجاء المحاولة مرة أخرى."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "اختيار فريق",
|
||||
@@ -34,7 +34,7 @@
|
||||
"NO_TEAMS_AVAILABLE": "لا توجد فرق مضافة إلى هذا الحساب حتى الآن.",
|
||||
"ASSIGN_SELECTED_TEAMS": "تعيين فريق محدد.",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين الفرق بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
"ASSIGN_FAILED": "فشل تعيين الفريق، الرجاء المحاولة مرة أخرى."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
"HEADER_BTN_TXT": "إضافة رد جاهز",
|
||||
"LOADING": "جاري جلب الردود الجاهزة...",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام.",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are pre-written reply templates that help you quickly respond to a conversation. To insert a canned response during a chat, agents can type a short code preceded by a '/' character. </p><p> You can manage your canned responses from this page or create new ones using the \"Add canned response\" button.</p><p>Open the <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\">Canned Responses handbook</a> in another tab for a helping hand.</p><p>Also, check out the all-new <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">Canned Responses Library</a>.</p>",
|
||||
"SIDEBAR_TXT": "<p><b>الردود المسبقة</b> </p></p><p> الردود المسبقة هي قوالب رد مكتوبة مسبقاً تساعدك على الرد بسرعة على محادثة. لإدراج استجابة مسبقة أثناء الدردشة، يمكن للوكلاء كتابة رمز قصير يسبقه حرف '/'. </p><p> يمكنك إدارة ردودك المعلبة من هذه الصفحة أو إنشاء استجابات جديدة باستخدام زر \"إضافة استجابة مسبقة\".</p><p>افتح دليل الردود المسبقة <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\"></a> في علامة تبويب أخرى للحصول على يد المساعدة.</p><p>أيضا، تحقق من كل المكتبة <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">الردود المسبقة</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "لا توجد ردود جاهزة متوفرة في هذا الحساب.",
|
||||
"TITLE": "إدارة الردود الجاهزة",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"DESC": "الردود الجاهزة هي قوالب رسائل معدة مسبقاً يمكن استخدامها لتسريع كتابة الردود في المحادثات.",
|
||||
"TABLE_HEADER": [
|
||||
"كود مختصر",
|
||||
"المحتوى",
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "إضافة رد جاهز",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"DESC": "الردود الجاهزة هي قوالب رسائل معدة مسبقاً يمكن استخدامها لتسريع كتابة الردود في المحادثات.",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
|
||||
@@ -59,22 +59,22 @@
|
||||
"TEXT": "اخر نشاط: الأحدث أولا"
|
||||
},
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
"TEXT": "تم إنشاؤها في: الأحدث أولاً"
|
||||
},
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
"TEXT": "تم إنشاؤها في: أقدم أولاً"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
"TEXT": "الأولوية: الأعلى أولا"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
"TEXT": "الأولوية: الأقل أولاً"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
"TEXT": "الرد المعلق: الأطول أولا"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
"TEXT": "الرد المعلق: أقصر أولاً"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
@@ -110,7 +110,7 @@
|
||||
"LABEL": "تم إنشاؤها في"
|
||||
},
|
||||
"LAST_USER_MESSAGE_AT": {
|
||||
"NAME": "Last user message at",
|
||||
"NAME": "آخر رسالة للمستخدم في",
|
||||
"LABEL": "أخر رسالة"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
"TITLE": "اضافة تصنيف جديد",
|
||||
"PLACEHOLDER": "ابحث عن تصنيفات",
|
||||
"NO_RESULT": "لم يتم العثور على تصنيفات",
|
||||
"CREATE_LABEL": "Create new label"
|
||||
"CREATE_LABEL": "إنشاء تسمية جديدة"
|
||||
}
|
||||
},
|
||||
"MERGE_CONTACT": "دمج جهة الاتصال",
|
||||
"CONTACT_ACTIONS": "إجراءات جهات الاتصال",
|
||||
"MUTE_CONTACT": "احجب جهة الاتصال",
|
||||
"UNMUTE_CONTACT": "إلغاء حجب جهة الاتصال",
|
||||
"MUTED_SUCCESS": "This contact is blocked successfully. You will not be notified of any future conversations.",
|
||||
"MUTED_SUCCESS": "تم حظر جهة الاتصال هذه بنجاح، لن يتم إعلامك بأي محادثات في المستقبل.",
|
||||
"UNMUTED_SUCCESS": "تم إلغاء حجب جهة الاتصال بنجاح.",
|
||||
"SEND_TRANSCRIPT": "إرسال النص",
|
||||
"EDIT_LABEL": "تعديل",
|
||||
@@ -72,7 +72,7 @@
|
||||
"SUBMIT": "استيراد",
|
||||
"CANCEL": "إلغاء"
|
||||
},
|
||||
"SUCCESS_MESSAGE": "You will be notified via email when the import is complete.",
|
||||
"SUCCESS_MESSAGE": "سيتم إعلامك عبر البريد الإلكتروني عند اكتمال الاستيراد.",
|
||||
"ERROR_MESSAGE": "حدث خطأ، الرجاء المحاولة مرة أخرى"
|
||||
},
|
||||
"EXPORT_CONTACTS": {
|
||||
@@ -83,8 +83,8 @@
|
||||
"ERROR_MESSAGE": "حدث خطأ، الرجاء المحاولة مرة أخرى",
|
||||
"CONFIRM": {
|
||||
"TITLE": "تصدير جهات الاتصال",
|
||||
"MESSAGE": "Are you sure you want to export all contacts?",
|
||||
"FILTERED_MESSAGE": "Are you sure you want to export all the filtered contacts?",
|
||||
"MESSAGE": "هل أنت متأكد من أنك تريد تصدير جميع جهات الاتصال؟",
|
||||
"FILTERED_MESSAGE": "هل أنت متأكد من أنك تريد تصدير جميع جهات الاتصال التي تم تصفيتها؟",
|
||||
"YES": "نعم, قم بالتصدير",
|
||||
"NO": "نعم, إلغاء"
|
||||
}
|
||||
@@ -138,7 +138,7 @@
|
||||
"LABEL": "رقم الهاتف",
|
||||
"HELP": "يجب ان يحتوى رقم الهاتف على كود دولتك تسبقها علامة +\nمثال: +20101243567",
|
||||
"ERROR": "يجب ان تكون خانة رقم الهاتف إما فارغة او مكتملة مع رمز الدولة",
|
||||
"DIAL_CODE_ERROR": "Please select a dial code from the list",
|
||||
"DIAL_CODE_ERROR": "الرجاء تحديد رمز الاتصال من القائمة",
|
||||
"DUPLICATE": "رقم الهاتف هذا مستخدم لجهة اتصال أخرى."
|
||||
},
|
||||
"LOCATION": {
|
||||
@@ -213,8 +213,8 @@
|
||||
"ERROR": "لا يمكن أن تكون الرسالة فارغة"
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
"SELECT": "Choose files",
|
||||
"HELP_TEXT": "Drag and drop files here or choose files to attach"
|
||||
"SELECT": "اختر الملفات",
|
||||
"HELP_TEXT": "قم بسحب وإسقاط الملفات هنا أو اختر ملفات لإرفاقها"
|
||||
},
|
||||
"SUBMIT": "إرسال الرسالة",
|
||||
"CANCEL": "إلغاء",
|
||||
@@ -231,7 +231,7 @@
|
||||
"FILTER_CONTACTS": "فلترة",
|
||||
"FILTER_CONTACTS_SAVE": "حفظ الفلتر",
|
||||
"FILTER_CONTACTS_DELETE": "حذف الفلتر",
|
||||
"FILTER_CONTACTS_EDIT": "Edit segment",
|
||||
"FILTER_CONTACTS_EDIT": "تحرير الجزء",
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "جاري تحميل جهات الاتصال...",
|
||||
"404": "لا توجد جهات اتصال تطابق بحثك 🔍",
|
||||
@@ -298,8 +298,8 @@
|
||||
"BUTTON": "إضافة سمة خاصة",
|
||||
"NOT_AVAILABLE": "لا توجد سمات مخصصة متاحة لجهة الاتصال هذه.",
|
||||
"COPY_SUCCESSFUL": "تم النسخ إلى الحافظة بنجاح",
|
||||
"SHOW_MORE": "Show all attributes",
|
||||
"SHOW_LESS": "Show less attributes",
|
||||
"SHOW_MORE": "إظهار كافة السمات",
|
||||
"SHOW_LESS": "عرض سمات أقل",
|
||||
"ACTIONS": {
|
||||
"COPY": "نسخ السمة",
|
||||
"DELETE": "حذف السمة",
|
||||
@@ -350,7 +350,7 @@
|
||||
"VALIDATIONS": {
|
||||
"REQUIRED": "القيمة الصالحة مطلوبة",
|
||||
"INVALID_URL": "عنوان URL غير صالح",
|
||||
"INVALID_INPUT": "Invalid Input"
|
||||
"INVALID_INPUT": "مدخلات غير صالح"
|
||||
}
|
||||
},
|
||||
"MERGE_CONTACTS": {
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
"CONTACTS_FILTER": {
|
||||
"TITLE": "تصفية جهات الاتصال",
|
||||
"SUBTITLE": "إضافة فلاتر أدناه واضغط على 'إرسال' لتصفية جهات الاتصال.",
|
||||
"EDIT_CUSTOM_SEGMENT": "Edit Segment",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your segment.",
|
||||
"EDIT_CUSTOM_SEGMENT": "تحرير الجزء",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "أضف أو أزل الفلاتر وقم بتحديث المجلد الخاص بك.",
|
||||
"ADD_NEW_FILTER": "إضافة فلتر",
|
||||
"CLEAR_ALL_FILTERS": "مسح جميع الفلاتر",
|
||||
"FILTER_DELETE_ERROR": "يجب ان يكون لديك فلتر واحد على الاقل",
|
||||
"SUBMIT_BUTTON_LABEL": "إرسال",
|
||||
"UPDATE_BUTTON_LABEL": "Update Segment",
|
||||
"UPDATE_BUTTON_LABEL": "تحديث الجزء",
|
||||
"CANCEL_BUTTON_LABEL": "إلغاء",
|
||||
"CLEAR_BUTTON_LABEL": "مسح الفلاتر",
|
||||
"EMPTY_VALUE_ERROR": "القيمة مطلوبة",
|
||||
"SEGMENT_LABEL": "Segment Name",
|
||||
"SEGMENT_QUERY_LABEL": "Segment Query",
|
||||
"SEGMENT_LABEL": "اسم القسم",
|
||||
"SEGMENT_QUERY_LABEL": "استعلام الجزء",
|
||||
"TOOLTIP_LABEL": "تصفية جهات الاتصال",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "و",
|
||||
@@ -45,7 +45,7 @@
|
||||
"CREATED_AT": "تم إنشاؤها في",
|
||||
"LAST_ACTIVITY": "آخر نشاط",
|
||||
"REFERER_LINK": "رابط المرجع",
|
||||
"BLOCKED": "Blocked"
|
||||
"BLOCKED": "محظور"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "الفلاتر القياسية",
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
"NO_INBOX_AGENT": "يبدو أنه لم يتم إسنادك لأي قنوات تواصل بعد. الرجاء التواصل مع المدير لإضافتك لصناديق الوارد الخاصة بقنوات التواصل",
|
||||
"SEARCH_MESSAGES": "البحث عن رسائل في المحادثات",
|
||||
"EMPTY_STATE": {
|
||||
"CMD_BAR": "to open command menu",
|
||||
"KEYBOARD_SHORTCUTS": "to view keyboard shortcuts"
|
||||
"CMD_BAR": "لفتح قائمة الأوامر",
|
||||
"KEYBOARD_SHORTCUTS": "لعرض اختصارات لوحة المفاتيح"
|
||||
},
|
||||
"SEARCH": {
|
||||
"TITLE": "البحث في الرسائل",
|
||||
@@ -40,16 +40,16 @@
|
||||
"UNKNOWN_FILE_TYPE": "ملف غير معروف",
|
||||
"SAVE_CONTACT": "حفظ",
|
||||
"UPLOADING_ATTACHMENTS": "جاري تحميل المرفقات...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"UNSUPPORTED_MESSAGE": "This message is unsupported.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
|
||||
"REPLIED_TO_STORY": "رد على قصتك",
|
||||
"UNSUPPORTED_MESSAGE": "هذه الرسالة غير مدعومة.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "هذه الرسالة غير مدعومة، يمكنك مشاهدة هذه الرسالة على تطبيق فيسبوك (Messenger).",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "هذه الرسالة غير مدعومة، يمكنك عرض هذه الرسالة على تطبيق Instagram.",
|
||||
"SUCCESS_DELETE_MESSAGE": "تم حذف الرسالة بنجاح",
|
||||
"FAIL_DELETE_MESSSAGE": "تعذر حذف الرسالة! حاول مرة أخرى",
|
||||
"NO_RESPONSE": "لا توجد استجابة",
|
||||
"RATING_TITLE": "التقييم",
|
||||
"FEEDBACK_TITLE": "الملاحظات",
|
||||
"REPLY_MESSAGE_NOT_FOUND": "Message not available",
|
||||
"REPLY_MESSAGE_NOT_FOUND": "الرسالة غير متوفرة",
|
||||
"CARD": {
|
||||
"SHOW_LABELS": "إظهار السمات",
|
||||
"HIDE_LABELS": "إخفاء السمات"
|
||||
@@ -61,7 +61,7 @@
|
||||
"OPEN": "المزيد",
|
||||
"CLOSE": "أغلق",
|
||||
"DETAILS": "التفاصيل",
|
||||
"SNOOZED_UNTIL": "Snoozed until",
|
||||
"SNOOZED_UNTIL": "غفوة حتى",
|
||||
"SNOOZED_UNTIL_TOMORROW": "غفوة حتى الغد",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "غفوة حتى الأسبوع القادم",
|
||||
"SNOOZED_UNTIL_NEXT_REPLY": "غفوة حتى الرد التالي",
|
||||
@@ -69,8 +69,8 @@
|
||||
"FRT": "FRT {status}",
|
||||
"NRT": "NRT {status}",
|
||||
"RT": "RT {status}",
|
||||
"MISSED": "missed",
|
||||
"DUE": "due"
|
||||
"MISSED": "مفقود",
|
||||
"DUE": "مستحق"
|
||||
}
|
||||
},
|
||||
"RESOLVE_DROPDOWN": {
|
||||
@@ -92,17 +92,17 @@
|
||||
"TITLE": "الأولوية",
|
||||
"OPTIONS": {
|
||||
"NONE": "لا شيء",
|
||||
"URGENT": "Urgent",
|
||||
"HIGH": "High",
|
||||
"MEDIUM": "Medium",
|
||||
"LOW": "Low"
|
||||
"URGENT": "عاجل",
|
||||
"HIGH": "عالية",
|
||||
"MEDIUM": "متوسطة",
|
||||
"LOW": "منخفضة"
|
||||
},
|
||||
"CHANGE_PRIORITY": {
|
||||
"SELECT_PLACEHOLDER": "لا شيء",
|
||||
"INPUT_PLACEHOLDER": "Select priority",
|
||||
"INPUT_PLACEHOLDER": "تحديد الأولوية",
|
||||
"NO_RESULTS": "لم يتم العثور على النتائج",
|
||||
"SUCCESSFUL": "Changed priority of conversation id %{conversationId} to %{priority}",
|
||||
"FAILED": "Couldn't change priority. Please try again."
|
||||
"SUCCESSFUL": "تغيير أولوية معرف المحادثة %{conversationId} إلى %{priority}",
|
||||
"FAILED": "تعذر تغيير الأولوية، الرجاء المحاولة مرة أخرى."
|
||||
}
|
||||
},
|
||||
"CARD_CONTEXT_MENU": {
|
||||
@@ -150,8 +150,8 @@
|
||||
"SEND": "إرسال",
|
||||
"CREATE": "إضافة ملاحظة",
|
||||
"INSERT_READ_MORE": "اقرأ المزيد",
|
||||
"DISMISS_REPLY": "Dismiss reply",
|
||||
"REPLYING_TO": "Replying to:",
|
||||
"DISMISS_REPLY": "تجاهل الرد",
|
||||
"REPLYING_TO": "الرد على:",
|
||||
"TIP_FORMAT_ICON": "عرض محرر النصوص",
|
||||
"TIP_EMOJI_ICON": "إظهار قائمة الرموز التعبيرية",
|
||||
"TIP_ATTACH_ICON": "إرفاق الملفات",
|
||||
@@ -163,7 +163,7 @@
|
||||
"STOP_AUDIO_RECORDING": "إيقاف التسجيل الصوتي",
|
||||
"": "",
|
||||
"EMAIL_HEAD": {
|
||||
"TO": "TO",
|
||||
"TO": "إلى",
|
||||
"ADD_BCC": "إضافة bcc",
|
||||
"CC": {
|
||||
"LABEL": "CC",
|
||||
@@ -206,15 +206,15 @@
|
||||
},
|
||||
"CONTEXT_MENU": {
|
||||
"COPY": "نسخ",
|
||||
"REPLY_TO": "Reply to this message",
|
||||
"REPLY_TO": "الرد على هذه الرسالة",
|
||||
"DELETE": "حذف",
|
||||
"CREATE_A_CANNED_RESPONSE": "إضافة إلى الردود السريعة",
|
||||
"TRANSLATE": "ترجم",
|
||||
"COPY_PERMALINK": "Copy link to the message",
|
||||
"LINK_COPIED": "Message URL copied to the clipboard",
|
||||
"COPY_PERMALINK": "نسخ الرابط إلى الرسالة",
|
||||
"LINK_COPIED": "تم نسخ عنوان URL للرسالة إلى الحافظة",
|
||||
"DELETE_CONFIRMATION": {
|
||||
"TITLE": "Are you sure you want to delete this message?",
|
||||
"MESSAGE": "You cannot undo this action",
|
||||
"TITLE": "هل أنت متأكد من أنك تريد حذف هذه الرسالة؟",
|
||||
"MESSAGE": "لا يمكنك التراجع عن هذا الإجراء",
|
||||
"DELETE": "حذف",
|
||||
"CANCEL": "إلغاء"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"DATE_PICKER": {
|
||||
"APPLY_BUTTON": "تطبيق",
|
||||
"CLEAR_BUTTON": "Clear",
|
||||
"CLEAR_BUTTON": "مسح",
|
||||
"DATE_RANGE_INPUT": {
|
||||
"START": "Start Date",
|
||||
"END": "End Date"
|
||||
"START": "تاريخ البدء",
|
||||
"END": "تاريخ الانتهاء"
|
||||
},
|
||||
"DATE_RANGE_OPTIONS": {
|
||||
"TITLE": "DATE RANGE",
|
||||
"TITLE": "نطاق التاريخ",
|
||||
"LAST_7_DAYS": "آخر 7 أيام",
|
||||
"LAST_30_DAYS": "آخر 30 يوماً",
|
||||
"LAST_3_MONTHS": "آخر 3 أشهر",
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
},
|
||||
"UPDATE_CHATWOOT": "يتوفر تحديث %{latestChatwootVersion} لـ Chatwoot. الرجاء التحديث.",
|
||||
"LEARN_MORE": "اعرف المزيد",
|
||||
"PAYMENT_PENDING": "Your payment is pending. Please update your payment information to continue using Chatwoot",
|
||||
"LIMITS_UPGRADE": "Your account has exceeded the usage limits, please upgrade your plan to continue using Chatwoot",
|
||||
"PAYMENT_PENDING": "الدفعة الخاصة بك معلقة. الرجاء تحديث معلومات الدفع الخاصة بك للاستمرار في استخدام Chatwoot",
|
||||
"LIMITS_UPGRADE": "لقد تجاوز حسابك حدود الاستخدام، يرجى ترقية خطتك للاستمرار في استخدام Chatwoot",
|
||||
"OPEN_BILLING": "فتح الفواتير"
|
||||
},
|
||||
"FORMS": {
|
||||
@@ -88,14 +88,16 @@
|
||||
"assigned_conversation_new_message": "رسالة جديدة",
|
||||
"participating_conversation_new_message": "رسالة جديدة",
|
||||
"conversation_mention": "إشارة",
|
||||
"sla_missed_first_response": "SLA Missed",
|
||||
"sla_missed_next_response": "SLA Missed",
|
||||
"sla_missed_resolution": "SLA Missed"
|
||||
"sla_missed_first_response": "فشل اتفاقية مستوى الخدمة",
|
||||
"sla_missed_next_response": "فشل اتفاقية مستوى الخدمة",
|
||||
"sla_missed_resolution": "فشل اتفاقية مستوى الخدمة"
|
||||
}
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"OFFLINE": "غير متصل"
|
||||
"OFFLINE": "غير متصل",
|
||||
"RECONNECTING": "Reconnecting...",
|
||||
"RECONNECT_SUCCESS": "Reconnected"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "تحديث"
|
||||
@@ -107,7 +109,7 @@
|
||||
"GENERAL": "عام",
|
||||
"REPORTS": "التقارير",
|
||||
"CONVERSATION": "المحادثات",
|
||||
"BULK_ACTIONS": "Bulk Actions",
|
||||
"BULK_ACTIONS": "الإجراءات الشاملة",
|
||||
"CHANGE_ASSIGNEE": "تغيير المحال إليه",
|
||||
"CHANGE_PRIORITY": "تغيير الأولوية",
|
||||
"CHANGE_TEAM": "تغيير الفريق",
|
||||
@@ -115,7 +117,7 @@
|
||||
"ADD_LABEL": "إضافة تسمية إلى المحادثة",
|
||||
"REMOVE_LABEL": "إزالة التسمية من المحادثة",
|
||||
"SETTINGS": "الإعدادات",
|
||||
"AI_ASSIST": "AI Assist",
|
||||
"AI_ASSIST": "مساعدة AI",
|
||||
"APPEARANCE": "مظهر",
|
||||
"SNOOZE_NOTIFICATION": "تأجيل التنبيهات"
|
||||
},
|
||||
@@ -139,7 +141,7 @@
|
||||
"GO_TO_NOTIFICATIONS": "الذهاب إلى الإشعارات",
|
||||
"ADD_LABELS_TO_CONVERSATION": "إضافة تسمية إلى المحادثة",
|
||||
"ASSIGN_AN_AGENT": "تعيين وكيل",
|
||||
"AI_ASSIST": "AI Assist",
|
||||
"AI_ASSIST": "مساعدة AI",
|
||||
"ASSIGN_PRIORITY": "تعيين الأولوية",
|
||||
"ASSIGN_A_TEAM": "تعيين فريق",
|
||||
"MUTE_CONVERSATION": "كتم المحادثة",
|
||||
@@ -154,9 +156,9 @@
|
||||
"UNTIL_TOMORROW": "حتى الغد",
|
||||
"UNTIL_NEXT_MONTH": "حتي الشهر القادم",
|
||||
"AN_HOUR_FROM_NOW": "حتي ساعة من الأن",
|
||||
"CUSTOM": "مخصص...",
|
||||
"UNTIL_CUSTOM_TIME": "مخصص...",
|
||||
"CHANGE_APPEARANCE": "تغيير المظهر",
|
||||
"LIGHT_MODE": "Light",
|
||||
"LIGHT_MODE": "فاتح",
|
||||
"DARK_MODE": "مظلم",
|
||||
"SYSTEM_MODE": "نظام",
|
||||
"SNOOZE_NOTIFICATION": "تأجيل التنبيهات"
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
"BACK_RESULTS": "Back to results"
|
||||
},
|
||||
"UPGRADE_PAGE": {
|
||||
"TITLE": "Help Center",
|
||||
"TITLE": "مركز المساعدة",
|
||||
"DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.",
|
||||
"SELF_HOSTED_DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Please contact your administrator to enable this feature.",
|
||||
"BUTTON": {
|
||||
|
||||
@@ -2,63 +2,63 @@
|
||||
"INBOX": {
|
||||
"LIST": {
|
||||
"TITLE": "صندوق الوارد",
|
||||
"DISPLAY_DROPDOWN": "Display",
|
||||
"LOADING": "Fetching notifications",
|
||||
"404": "There are no active notifications in this group.",
|
||||
"NO_NOTIFICATIONS": "No notifications",
|
||||
"NOTE": "Notifications from all subscribed inboxes",
|
||||
"NO_MESSAGES_AVAILABLE": "Oops! Not able to fetch messages",
|
||||
"SNOOZED_UNTIL": "Snoozed until",
|
||||
"DISPLAY_DROPDOWN": "عرض",
|
||||
"LOADING": "جارٍ جلب الإشعارات",
|
||||
"404": "لا توجد إشعارات نشطة في هذه المجموعة.",
|
||||
"NO_NOTIFICATIONS": "لا توجد إشعارات",
|
||||
"NOTE": "الإشعارات من جميع صناديق الوارد المشترك بها",
|
||||
"NO_MESSAGES_AVAILABLE": "عذرًا! لا يمكن جلب الرسائل",
|
||||
"SNOOZED_UNTIL": "غفوة حتى",
|
||||
"SNOOZED_UNTIL_TOMORROW": "غفوة حتى الغد",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "غفوة حتى الأسبوع القادم"
|
||||
},
|
||||
"ACTION_HEADER": {
|
||||
"SNOOZE": "Snooze notification",
|
||||
"DELETE": "Delete notification",
|
||||
"SNOOZE": "غفوة الإشعار",
|
||||
"DELETE": "حذف الإشعار",
|
||||
"BACK": "العودة"
|
||||
},
|
||||
"TYPES": {
|
||||
"CONVERSATION_MENTION": "You have been mentioned in a conversation",
|
||||
"CONVERSATION_CREATION": "New conversation created",
|
||||
"CONVERSATION_ASSIGNMENT": "A conversation has been assigned to you",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "New message in an assigned conversation",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "New message in a conversation you are participating in",
|
||||
"SLA_MISSED_FIRST_RESPONSE": "SLA target first response missed for conversation",
|
||||
"SLA_MISSED_NEXT_RESPONSE": "SLA target next response missed for conversation",
|
||||
"SLA_MISSED_RESOLUTION": "SLA target resolution missed for conversation"
|
||||
"CONVERSATION_MENTION": "تم ذكرك في محادثة",
|
||||
"CONVERSATION_CREATION": "تم إنشاء محادثة جديدة",
|
||||
"CONVERSATION_ASSIGNMENT": "تم تعيين محادثة لك",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "رسالة جديدة في محادثة معينة لك",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "رسالة جديدة في محادثة تشارك فيها",
|
||||
"SLA_MISSED_FIRST_RESPONSE": "تم تجاوز الهدف الأول للرد للمحادثة",
|
||||
"SLA_MISSED_NEXT_RESPONSE": "تم تجاوز الهدف التالي للرد للمحادثة",
|
||||
"SLA_MISSED_RESOLUTION": "تم تجاوز الهدف النهائي للحل للمحادثة"
|
||||
},
|
||||
"MENU_ITEM": {
|
||||
"MARK_AS_READ": "Mark as read",
|
||||
"MARK_AS_READ": "وضع علامة كمقروء",
|
||||
"MARK_AS_UNREAD": "وضع علامة كغير مقروء",
|
||||
"SNOOZE": "غفوة",
|
||||
"DELETE": "حذف",
|
||||
"MARK_ALL_READ": "تحديد الكل كمقروء",
|
||||
"DELETE_ALL": "Delete all",
|
||||
"DELETE_ALL_READ": "Delete all read"
|
||||
"DELETE_ALL": "حذف الكل",
|
||||
"DELETE_ALL_READ": "حذف كل المقروء"
|
||||
},
|
||||
"DISPLAY_MENU": {
|
||||
"SORT": "Sort",
|
||||
"DISPLAY": "Display :",
|
||||
"SORT": "فرز",
|
||||
"DISPLAY": "عرض :",
|
||||
"SORT_OPTIONS": {
|
||||
"NEWEST": "Newest",
|
||||
"OLDEST": "Oldest",
|
||||
"NEWEST": "الأحدث",
|
||||
"OLDEST": "الأقدم",
|
||||
"PRIORITY": "الأولوية"
|
||||
},
|
||||
"DISPLAY_OPTIONS": {
|
||||
"SNOOZED": "غفوة",
|
||||
"READ": "قرائة",
|
||||
"READ": "قراءة",
|
||||
"LABELS": "الوسوم",
|
||||
"CONVERSATION_ID": "Conversation ID"
|
||||
"CONVERSATION_ID": "معرف المحادثة"
|
||||
}
|
||||
},
|
||||
"ALERTS": {
|
||||
"MARK_AS_READ": "Notification marked as read",
|
||||
"MARK_AS_UNREAD": "Notification marked as unread",
|
||||
"SNOOZE": "Notification snoozed",
|
||||
"DELETE": "Notification deleted",
|
||||
"MARK_ALL_READ": "All notifications marked as read",
|
||||
"DELETE_ALL": "All notifications deleted",
|
||||
"DELETE_ALL_READ": "All read notifications deleted"
|
||||
"MARK_AS_READ": "تم وضع علامة الإشعار كمقروء",
|
||||
"MARK_AS_UNREAD": "تم وضع علامة الإشعار كغير مقروء",
|
||||
"SNOOZE": "تم تأجيل الإشعار",
|
||||
"DELETE": "تم حذف الإشعار",
|
||||
"MARK_ALL_READ": "تم وضع علامة كل الإشعارات كمقروء",
|
||||
"DELETE_ALL": "تم حذف كل الإشعارات",
|
||||
"DELETE_ALL_READ": "تم حذف كل الإشعارات المقروءة"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
"INBOX_MGMT": {
|
||||
"HEADER": "قنوات التواصل",
|
||||
"SIDEBAR_TXT": "<p><b>قنوات التواصل</b></p> <p> عند ربطك لموقع ويب أو صفحة فيسبوك إلى Chatwoot، يتم تسميتها <b>قناة تواصل</b>. يمكنك إنشاء قنوات تواصل غير محدودة من مختلف الأنواع في حساب Chatwoot الخاص بك. </p><p> انقر فوق <b>إضافة قناة تواصل</b> لربط موقع الويب أو صفحة فيسبوك الخاصة بك. </p><p> من لوحة الإدارة، يمكنك رؤية جميع المحادثات من جميع صناديق الوارد الخاصة بك والرد عليها من مكان موّحد عبر الضغط على علامة التبويب \"المحادثات\". </p><p> يمكنك أيضًا مشاهدة المحادثات الخاصة بصندوق وارد معين بالنقر على اسم صندوق الوارد على الجزء الجانبي من لوحة الإدارة. </p>",
|
||||
"RECONNECTION_REQUIRED": "Your inbox is disconnected. You won't receive new messages until you reauthorize it.",
|
||||
"CLICK_TO_RECONNECT": "Click here to reconnect.",
|
||||
"LIST": {
|
||||
"404": "لا توجد صناديق وارد لقنوات تواصل مرتبطة بهذا الحساب."
|
||||
},
|
||||
@@ -364,6 +366,7 @@
|
||||
"TITLE": "Microsoft Email",
|
||||
"DESCRIPTION": "Click on the Sign in with Microsoft button to get started. You will redirected to the email sign in page. Once you accept the requested permissions, you would be redirected back to the inbox creation step.",
|
||||
"EMAIL_PLACEHOLDER": "Enter email address",
|
||||
"SIGN_IN": "Sign in with Microsoft",
|
||||
"HELP": "To add your Microsoft account as a channel, you need to authenticate your Microsoft account by clicking on 'Sign in with Microsoft' ",
|
||||
"ERROR_MESSAGE": "There was an error connecting to Microsoft, please try again"
|
||||
}
|
||||
@@ -518,7 +521,7 @@
|
||||
"UPDATE_PRE_CHAT_FORM_SETTINGS": "Update Pre Chat Form Settings"
|
||||
},
|
||||
"HELP_CENTER": {
|
||||
"LABEL": "Help Center",
|
||||
"LABEL": "مركز المساعدة",
|
||||
"PLACEHOLDER": "Select Help Center",
|
||||
"SELECT_PLACEHOLDER": "Select Help Center",
|
||||
"REMOVE": "Remove Help Center",
|
||||
|
||||
@@ -209,6 +209,87 @@
|
||||
"API_SUCCESS": "تم حذف تطبيق لوحة التحكم بنجاح",
|
||||
"API_ERROR": "لم نتمكن من حذف التطبيق. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
}
|
||||
},
|
||||
"LINEAR": {
|
||||
"ADD_OR_LINK_BUTTON": "Create/Link Linear Issue",
|
||||
"LOADING": "Fetching linear issues...",
|
||||
"LOADING_ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"CREATE": "إنشاء",
|
||||
"LINK": {
|
||||
"SEARCH": "Search issues",
|
||||
"SELECT": "Select issue",
|
||||
"TITLE": "الرابط",
|
||||
"EMPTY_LIST": "No linear issues found",
|
||||
"LOADING": "جار التحميل",
|
||||
"ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"LINK_SUCCESS": "Issue linked successfully",
|
||||
"LINK_ERROR": "There was an error linking the issue, please try again",
|
||||
"LINK_TITLE": "Conversation (#%{conversationId}) with %{name}"
|
||||
},
|
||||
"ADD_OR_LINK": {
|
||||
"TITLE": "Create/link linear issue",
|
||||
"DESCRIPTION": "Create Linear issues from conversations, or link existing ones for seamless tracking.",
|
||||
"FORM": {
|
||||
"TITLE": {
|
||||
"LABEL": "العنوان",
|
||||
"PLACEHOLDER": "Enter title",
|
||||
"REQUIRED_ERROR": "العنوان مطلوب"
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "الوصف",
|
||||
"PLACEHOLDER": "Enter description"
|
||||
},
|
||||
"TEAM": {
|
||||
"LABEL": "الفريق",
|
||||
"PLACEHOLDER": "اختيار فريق",
|
||||
"SEARCH": "Search team",
|
||||
"REQUIRED_ERROR": "Team is required"
|
||||
},
|
||||
"ASSIGNEE": {
|
||||
"LABEL": "Assignee",
|
||||
"PLACEHOLDER": "Select assignee",
|
||||
"SEARCH": "Search assignee"
|
||||
},
|
||||
"PRIORITY": {
|
||||
"LABEL": "الأولوية",
|
||||
"PLACEHOLDER": "تحديد الأولوية",
|
||||
"SEARCH": "Search priority"
|
||||
},
|
||||
"LABEL": {
|
||||
"LABEL": "الوسم",
|
||||
"PLACEHOLDER": "Select label",
|
||||
"SEARCH": "Search label"
|
||||
},
|
||||
"STATUS": {
|
||||
"LABEL": "الحالة",
|
||||
"PLACEHOLDER": "Select status",
|
||||
"SEARCH": "Search status"
|
||||
},
|
||||
"PROJECT": {
|
||||
"LABEL": "Project",
|
||||
"PLACEHOLDER": "Select project",
|
||||
"SEARCH": "Search project"
|
||||
}
|
||||
},
|
||||
"CREATE": "إنشاء",
|
||||
"CANCEL": "إلغاء",
|
||||
"CREATE_SUCCESS": "Issue created successfully",
|
||||
"CREATE_ERROR": "There was an error creating the issue, please try again",
|
||||
"LOADING_TEAM_ERROR": "There was an error fetching the teams, please try again",
|
||||
"LOADING_TEAM_ENTITIES_ERROR": "There was an error fetching the team entities, please try again"
|
||||
},
|
||||
"ISSUE": {
|
||||
"STATUS": "الحالة",
|
||||
"PRIORITY": "الأولوية",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"LABELS": "الوسوم",
|
||||
"CREATED_AT": "Created at %{createdAt}"
|
||||
},
|
||||
"UNLINK": {
|
||||
"TITLE": "Unlink",
|
||||
"SUCCESS": "Issue unlinked successfully",
|
||||
"ERROR": "There was an error unlinking the issue, please try again"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,7 +517,7 @@
|
||||
"DOWNLOAD_SLA_REPORTS": "Download SLA reports",
|
||||
"DOWNLOAD_FAILED": "Failed to download SLA Reports",
|
||||
"DROPDOWN": {
|
||||
"ADD_FIlTER": "Add filter",
|
||||
"ADD_FIlTER": "إضافة فلتر",
|
||||
"CLEAR_ALL": "Clear all",
|
||||
"CLEAR_FILTER": "Clear filter",
|
||||
"EMPTY_LIST": "لم يتم العثور على النتائج",
|
||||
|
||||
@@ -278,9 +278,9 @@
|
||||
"SLA": "SLA",
|
||||
"BETA": "تجريبي",
|
||||
"REPORTS_OVERVIEW": "نظرة عامة",
|
||||
"FACEBOOK_REAUTHORIZE": "انتهت صلاحية اتصال الفيسبوك الخاص بك، يرجى إعادة الاتصال بصفحة الفيسبوك الخاصة بك لمواصلة الخدمات",
|
||||
"REAUTHORIZE": "Your inbox connection has expired, please reconnect\n to continue receiving and sending messages",
|
||||
"HELP_CENTER": {
|
||||
"TITLE": "Help Center",
|
||||
"TITLE": "مركز المساعدة",
|
||||
"ALL_ARTICLES": "جميع المقالات",
|
||||
"MY_ARTICLES": "مقالاتي",
|
||||
"DRAFT": "مسودة",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"NONE": "Нито един",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,9 @@
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"OFFLINE": "Offline"
|
||||
"OFFLINE": "Offline",
|
||||
"RECONNECTING": "Reconnecting...",
|
||||
"RECONNECT_SUCCESS": "Reconnected"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "Refresh"
|
||||
@@ -154,7 +156,7 @@
|
||||
"UNTIL_TOMORROW": "Until tomorrow",
|
||||
"UNTIL_NEXT_MONTH": "Until next month",
|
||||
"AN_HOUR_FROM_NOW": "Until an hour from now",
|
||||
"CUSTOM": "Custom...",
|
||||
"UNTIL_CUSTOM_TIME": "Custom...",
|
||||
"CHANGE_APPEARANCE": "Change Appearance",
|
||||
"LIGHT_MODE": "Light",
|
||||
"DARK_MODE": "Dark",
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
"INBOX_MGMT": {
|
||||
"HEADER": "Inboxes",
|
||||
"SIDEBAR_TXT": "<p><b>Inbox</b></p> <p> When you connect a website or a facebook Page to Chatwoot, it is called an <b>Inbox</b>. You can have unlimited inboxes in your Chatwoot account. </p><p> Click on <b>Add Inbox</b> to connect a website or a Facebook Page. </p><p> 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. </p><p> You can also see conversations specific to an inbox by clicking on the inbox name on the left pane of the dashboard. </p>",
|
||||
"RECONNECTION_REQUIRED": "Your inbox is disconnected. You won't receive new messages until you reauthorize it.",
|
||||
"CLICK_TO_RECONNECT": "Click here to reconnect.",
|
||||
"LIST": {
|
||||
"404": "There are no inboxes attached to this account."
|
||||
},
|
||||
@@ -364,6 +366,7 @@
|
||||
"TITLE": "Microsoft Email",
|
||||
"DESCRIPTION": "Click on the Sign in with Microsoft button to get started. You will redirected to the email sign in page. Once you accept the requested permissions, you would be redirected back to the inbox creation step.",
|
||||
"EMAIL_PLACEHOLDER": "Enter email address",
|
||||
"SIGN_IN": "Sign in with Microsoft",
|
||||
"HELP": "To add your Microsoft account as a channel, you need to authenticate your Microsoft account by clicking on 'Sign in with Microsoft' ",
|
||||
"ERROR_MESSAGE": "There was an error connecting to Microsoft, please try again"
|
||||
}
|
||||
|
||||
@@ -209,6 +209,87 @@
|
||||
"API_SUCCESS": "Dashboard app deleted successfully",
|
||||
"API_ERROR": "We couldn't delete the app. Please try again later"
|
||||
}
|
||||
},
|
||||
"LINEAR": {
|
||||
"ADD_OR_LINK_BUTTON": "Create/Link Linear Issue",
|
||||
"LOADING": "Fetching linear issues...",
|
||||
"LOADING_ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"CREATE": "Създаване",
|
||||
"LINK": {
|
||||
"SEARCH": "Search issues",
|
||||
"SELECT": "Select issue",
|
||||
"TITLE": "Link",
|
||||
"EMPTY_LIST": "No linear issues found",
|
||||
"LOADING": "Loading",
|
||||
"ERROR": "There was an error fetching the linear issues, please try again",
|
||||
"LINK_SUCCESS": "Issue linked successfully",
|
||||
"LINK_ERROR": "There was an error linking the issue, please try again",
|
||||
"LINK_TITLE": "Conversation (#%{conversationId}) with %{name}"
|
||||
},
|
||||
"ADD_OR_LINK": {
|
||||
"TITLE": "Create/link linear issue",
|
||||
"DESCRIPTION": "Create Linear issues from conversations, or link existing ones for seamless tracking.",
|
||||
"FORM": {
|
||||
"TITLE": {
|
||||
"LABEL": "Title",
|
||||
"PLACEHOLDER": "Enter title",
|
||||
"REQUIRED_ERROR": "Title is required"
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Описание",
|
||||
"PLACEHOLDER": "Enter description"
|
||||
},
|
||||
"TEAM": {
|
||||
"LABEL": "Team",
|
||||
"PLACEHOLDER": "Изберете екип",
|
||||
"SEARCH": "Search team",
|
||||
"REQUIRED_ERROR": "Team is required"
|
||||
},
|
||||
"ASSIGNEE": {
|
||||
"LABEL": "Assignee",
|
||||
"PLACEHOLDER": "Select assignee",
|
||||
"SEARCH": "Search assignee"
|
||||
},
|
||||
"PRIORITY": {
|
||||
"LABEL": "Priority",
|
||||
"PLACEHOLDER": "Select priority",
|
||||
"SEARCH": "Search priority"
|
||||
},
|
||||
"LABEL": {
|
||||
"LABEL": "Label",
|
||||
"PLACEHOLDER": "Select label",
|
||||
"SEARCH": "Search label"
|
||||
},
|
||||
"STATUS": {
|
||||
"LABEL": "Статус",
|
||||
"PLACEHOLDER": "Select status",
|
||||
"SEARCH": "Search status"
|
||||
},
|
||||
"PROJECT": {
|
||||
"LABEL": "Project",
|
||||
"PLACEHOLDER": "Select project",
|
||||
"SEARCH": "Search project"
|
||||
}
|
||||
},
|
||||
"CREATE": "Създаване",
|
||||
"CANCEL": "Отмени",
|
||||
"CREATE_SUCCESS": "Issue created successfully",
|
||||
"CREATE_ERROR": "There was an error creating the issue, please try again",
|
||||
"LOADING_TEAM_ERROR": "There was an error fetching the teams, please try again",
|
||||
"LOADING_TEAM_ENTITIES_ERROR": "There was an error fetching the team entities, please try again"
|
||||
},
|
||||
"ISSUE": {
|
||||
"STATUS": "Статус",
|
||||
"PRIORITY": "Priority",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"LABELS": "Етикети",
|
||||
"CREATED_AT": "Created at %{createdAt}"
|
||||
},
|
||||
"UNLINK": {
|
||||
"TITLE": "Unlink",
|
||||
"SUCCESS": "Issue unlinked successfully",
|
||||
"ERROR": "There was an error unlinking the issue, please try again"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
"SLA": "SLA",
|
||||
"BETA": "Beta",
|
||||
"REPORTS_OVERVIEW": "Overview",
|
||||
"FACEBOOK_REAUTHORIZE": "Your Facebook connection has expired, please reconnect your Facebook page to continue services",
|
||||
"REAUTHORIZE": "Your inbox connection has expired, please reconnect\n to continue receiving and sending messages",
|
||||
"HELP_CENTER": {
|
||||
"TITLE": "Help Center",
|
||||
"ALL_ARTICLES": "All Articles",
|
||||
|
||||
@@ -2,67 +2,67 @@
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "S'està carregant l'editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"HEADER_BTN_TXT": "Afegir configuració del bot",
|
||||
"SIDEBAR_TXT": "<p><b>Bots d'Agent</b> <p>Bots d'Agent són com els membres més fabulosos del teu equip. Poden gestionar les coses petites, de manera que us podeu centrar en les coses importants. Prova-ls.</p> <p> Pots gestionar els teus bots des d'aquesta pàgina o crear-ne de nous mitjançant el botó \"Afegeix una configuració de bot\".</p> <p> Obre el <a href=\"https:/ /www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Manual de robots d'agent</a> en una altra pestanya per a un cop de mà.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
"LABEL": "Nom del bot",
|
||||
"PLACEHOLDER": "Anomena el teu bot.",
|
||||
"ERROR": "El nom del bot és obligatori."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
"LABEL": "Descripció del bot",
|
||||
"PLACEHOLDER": "Què fa aquest bot?"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
"ERROR": "Introdueix la configuració del bot CSML més amunt.",
|
||||
"API_ERROR": "La vostra configuració CSML no és vàlida. Arregla-ho i torna-ho a provar."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
"SUBMIT": "Valida i desa"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"TITLE": "Selecciona un bot d'agent",
|
||||
"DESC": "Assigna un bot d'agent a la teva safata d'entrada. Poden gestionar les converses inicials i transferir-les a un agent en directe quan sigui necessari.",
|
||||
"SUBMIT": "Actualitza",
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
"DISCONNECT": "Desconnecta el bot",
|
||||
"SUCCESS_MESSAGE": "S'ha actualitzat correctament el bot de l'agent.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "S'ha desconnectat correctament el bot de l'agent.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut actualitzar el bot de l'agent. Torneu-ho a provar.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "No s'ha pogut desconnectar el bot de l'agent. Torneu-ho a provar.",
|
||||
"SELECT_PLACEHOLDER": "Selecciona el bot"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"TITLE": "Configura el nou bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
"SUCCESS_MESSAGE": "Bot afegit correctament.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut afegir el bot. Torneu-ho a provar més endavant."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
"404": "No s'han trobat bots. Pots crear un bot fent clic al botó \"Configura un bot nou\" ↗",
|
||||
"LOADING": "S'estan obtenint bots...",
|
||||
"TYPE": "Tipus de bot"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Esborrar",
|
||||
"TITLE": "Delete bot",
|
||||
"TITLE": "Suprimeix el bot",
|
||||
"SUBMIT": "Esborrar",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"DESCRIPTION": "Estàs segur que vols suprimir aquest bot? Aquesta acció és irreversible.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
"SUCCESS_MESSAGE": "S'ha esborrat el bot correctament.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut eliminar el bot. Torneu-ho a provar més endavant."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "Edita",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"LOADING": "S'estan obtenint bots...",
|
||||
"TITLE": "Edita el bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
"SUCCESS_MESSAGE": "Bot actualitzat correctament.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut actualitzar el bot. Torneu-ho a provar."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
"PLACEHOLDER": {
|
||||
"AGENT": "Cerca agents",
|
||||
"TEAM": "Cerca equips",
|
||||
"INPUT": "Cerca agents"
|
||||
"INPUT": "Cerca agent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
{
|
||||
"ATTRIBUTES_MGMT": {
|
||||
"HEADER": "Atributs personalitzats",
|
||||
"HEADER_BTN_TXT": "Add Custom Attribute",
|
||||
"LOADING": "Fetching custom attributes",
|
||||
"SIDEBAR_TXT": "<p><b>Custom Attributes</b> <p>A custom attribute tracks facts about your contacts/conversation — like the subscription plan, or when they ordered the first item etc. <br /><br />For creating a Custom Attribute, just click on the <b>Add Custom Attribute.</b> You can also edit or delete an existing Custom Attribute by clicking on the Edit or Delete button.</p>",
|
||||
"HEADER_BTN_TXT": "Afegir atribut personalitzat",
|
||||
"LOADING": "S'estan recollint atributs personalitzats",
|
||||
"SIDEBAR_TXT": "<p><b>Atributs personalitzats</b> <p>Un atribut personalitzat fa un seguiment dels fets sobre els vostres contactes/converses, com ara el pla de subscripció, o quan van demanar el primer element, etc. <br /><br />Per crear un atribut personalitzat, només cal que feu clic a <b>Afegeix un atribut personalitzat.</b> També podeu editar o suprimir un atribut personalitzat existent fent clic al botó Edita o Suprimeix.</p>",
|
||||
"ADD": {
|
||||
"TITLE": "Add Custom Attribute",
|
||||
"TITLE": "Afegir atribut personalitzat",
|
||||
"SUBMIT": "Crear",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"FORM": {
|
||||
"NAME": {
|
||||
"LABEL": "Display Name",
|
||||
"PLACEHOLDER": "Enter custom attribute display name",
|
||||
"ERROR": "Name is required"
|
||||
"LABEL": "Mostre el nom",
|
||||
"PLACEHOLDER": "Introdueix el nom de visualització de l'atribut personalitzat",
|
||||
"ERROR": "El valor és necessari"
|
||||
},
|
||||
"DESC": {
|
||||
"LABEL": "Descripció",
|
||||
"PLACEHOLDER": "Enter custom attribute description",
|
||||
"ERROR": "Description is required"
|
||||
"PLACEHOLDER": "Introdueix la descripció de l'atribut personalitzat",
|
||||
"ERROR": "La descripció és necessària"
|
||||
},
|
||||
"MODEL": {
|
||||
"LABEL": "Applies to",
|
||||
"PLACEHOLDER": "Please select one",
|
||||
"ERROR": "Model is required"
|
||||
"LABEL": "S'aplica a",
|
||||
"PLACEHOLDER": "Selecciona un",
|
||||
"ERROR": "El model és necessari"
|
||||
},
|
||||
"TYPE": {
|
||||
"LABEL": "Type",
|
||||
"LABEL": "Tipus",
|
||||
"PLACEHOLDER": "Selecciona un tipus",
|
||||
"ERROR": "Type is required",
|
||||
"ERROR": "El tipus és necessari",
|
||||
"LIST": {
|
||||
"LABEL": "List Values",
|
||||
"PLACEHOLDER": "Please enter value and press enter key",
|
||||
"ERROR": "Must have at least one value"
|
||||
"LABEL": "Llista de valors",
|
||||
"PLACEHOLDER": "Introdueix el valor i prem la tecla Intro",
|
||||
"ERROR": "Ha de tenir almenys un valor"
|
||||
}
|
||||
},
|
||||
"KEY": {
|
||||
"LABEL": "Key",
|
||||
"PLACEHOLDER": "Enter custom attribute key",
|
||||
"ERROR": "Key is required",
|
||||
"IN_VALID": "Invalid key"
|
||||
"LABEL": "Clau",
|
||||
"PLACEHOLDER": "Introduïu la clau d'atribut personalitzada",
|
||||
"ERROR": "La clau és necessària",
|
||||
"IN_VALID": "Clau no vàlida"
|
||||
},
|
||||
"REGEX_PATTERN": {
|
||||
"LABEL": "Regex Pattern",
|
||||
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||
"LABEL": "Patró d'expressió regular",
|
||||
"PLACEHOLDER": "Introdueix un patró d'expressió regular d'atribut personalitzat. (Opcional)"
|
||||
},
|
||||
"REGEX_CUE": {
|
||||
"LABEL": "Regex Cue",
|
||||
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||
"LABEL": "Senyal d'expressió regular",
|
||||
"PLACEHOLDER": "Introdueix la pista del patró d'expressió regular. (Opcional)"
|
||||
},
|
||||
"ENABLE_REGEX": {
|
||||
"LABEL": "Enable regex validation"
|
||||
"LABEL": "Activa la validació d'expressions regulars"
|
||||
}
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Custom Attribute added successfully!",
|
||||
"ERROR_MESSAGE": "Could not create a Custom Attribute. Please try again later."
|
||||
"SUCCESS_MESSAGE": "Atribut personalitzat afegit correctament!",
|
||||
"ERROR_MESSAGE": "No s'ha pogut crear un atribut personalitzat. Intenta-ho més tard."
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Esborrar",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Custom Attribute deleted successfully.",
|
||||
"ERROR_MESSAGE": "Couldn't delete the custom attribute. Try again."
|
||||
"SUCCESS_MESSAGE": "Atribut personalitzat suprimit correctament.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut suprimir l'atribut personalitzat. Torna-ho a provar."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Are you sure want to delete - %{attributeName}",
|
||||
"PLACE_HOLDER": "Please type {attributeName} to confirm",
|
||||
"MESSAGE": "Deleting will remove the custom attribute",
|
||||
"TITLE": "Estàs segur que vols suprimir - %{attributeName}",
|
||||
"PLACE_HOLDER": "Escriu {attributeName} per confirmar",
|
||||
"MESSAGE": "En suprimir, s'eliminarà l'atribut personalitzat",
|
||||
"YES": "Suprimeix ",
|
||||
"NO": "Cancel·la"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Edit Custom Attribute",
|
||||
"TITLE": "Edita atribut personalitzat",
|
||||
"UPDATE_BUTTON_TEXT": "Actualitza",
|
||||
"TYPE": {
|
||||
"LIST": {
|
||||
"LABEL": "List Values",
|
||||
"PLACEHOLDER": "Please enter values and press enter key"
|
||||
"LABEL": "Llista de valors",
|
||||
"PLACEHOLDER": "Introdueix els valors i prem la tecla Intro"
|
||||
}
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Custom Attribute updated successfully",
|
||||
"ERROR_MESSAGE": "There was an error updating custom attribute, please try again"
|
||||
"SUCCESS_MESSAGE": "Atribut personalitzat actualitzat correctament",
|
||||
"ERROR_MESSAGE": "S'ha produït un error en actualitzar l'atribut personalitzat. Torneu-ho a provar"
|
||||
}
|
||||
},
|
||||
"TABS": {
|
||||
"HEADER": "Atributs personalitzats",
|
||||
"CONVERSATION": "Conversation",
|
||||
"CONTACT": "Contact"
|
||||
"CONVERSATION": "Conversa",
|
||||
"CONTACT": "Contacte"
|
||||
},
|
||||
"LIST": {
|
||||
"TABLE_HEADER": [
|
||||
"Nom",
|
||||
"Descripció",
|
||||
"Type",
|
||||
"Key"
|
||||
"Tipus",
|
||||
"Clau"
|
||||
],
|
||||
"BUTTONS": {
|
||||
"EDIT": "Edita",
|
||||
"DELETE": "Esborrar"
|
||||
},
|
||||
"EMPTY_RESULT": {
|
||||
"404": "There are no custom attributes created",
|
||||
"NOT_FOUND": "There are no custom attributes configured"
|
||||
"404": "No s'han creat atributs personalitzats",
|
||||
"NOT_FOUND": "No hi ha atributs personalitzats configurats"
|
||||
},
|
||||
"REGEX_PATTERN": {
|
||||
"LABEL": "Regex Pattern",
|
||||
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||
"LABEL": "Patró d'expressió regular",
|
||||
"PLACEHOLDER": "Introdueix un patró d'expressió regular d'atribut personalitzat. (Opcional)"
|
||||
},
|
||||
"REGEX_CUE": {
|
||||
"LABEL": "Regex Cue",
|
||||
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||
"LABEL": "Senyal d'expressió regular",
|
||||
"PLACEHOLDER": "Introdueix la pista del patró d'expressió regular. (Opcional)"
|
||||
},
|
||||
"ENABLE_REGEX": {
|
||||
"LABEL": "Enable regex validation"
|
||||
"LABEL": "Activa la validació d'expressions regulars"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"AUDIT_LOGS": {
|
||||
"HEADER": "Audit Logs",
|
||||
"HEADER_BTN_TXT": "Add Audit Logs",
|
||||
"LOADING": "Fetching Audit Logs",
|
||||
"HEADER": "Registres d'auditoria",
|
||||
"HEADER_BTN_TXT": "Afegeix registres d'auditoria",
|
||||
"LOADING": "S'estan recollint registres d'auditoria",
|
||||
"SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta",
|
||||
"SIDEBAR_TXT": "<p><b>Audit Logs</b> </p><p> Audit Logs are trails for events and actions in a Chatwoot System. </p>",
|
||||
"SIDEBAR_TXT": "<p><b>Registres d'auditoria</b> </p><p> Els registres d'auditoria són pistes d'esdeveniments i accions en un sistema de Chatwoot. </p>",
|
||||
"LIST": {
|
||||
"404": "There are no Audit Logs available in this account.",
|
||||
"TITLE": "Manage Audit Logs",
|
||||
"DESC": "Audit Logs are trails for events and actions in a Chatwoot System.",
|
||||
"404": "No hi ha registres d'auditoria disponibles en aquest compte.",
|
||||
"TITLE": "Gestiona els registres d'auditoria",
|
||||
"DESC": "Els registres d'auditoria són pistes d'esdeveniments i accions en un sistema Chatwoot.",
|
||||
"TABLE_HEADER": [
|
||||
"User",
|
||||
"Temps",
|
||||
@@ -16,56 +16,56 @@
|
||||
]
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "AuditLogs retrieved successfully",
|
||||
"SUCCESS_MESSAGE": "Els registres d'auditoria s'han recuperat correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||
},
|
||||
"DEFAULT_USER": "System",
|
||||
"DEFAULT_USER": "Sistema",
|
||||
"AUTOMATION_RULE": {
|
||||
"ADD": "%{agentName} created a new automation rule (#%{id})",
|
||||
"EDIT": "%{agentName} updated an automation rule (#%{id})",
|
||||
"DELETE": "%{agentName} deleted an automation rule (#%{id})"
|
||||
"ADD": "%{agentName} ha creat una nova regla d'automatització (#%{id})",
|
||||
"EDIT": "%{agentName} ha actualitzat una regla d'automatització (#%{id})",
|
||||
"DELETE": "%{agentName} ha suprimit una regla d'automatització (#%{id})"
|
||||
},
|
||||
"ACCOUNT_USER": {
|
||||
"ADD": "%{agentName} invited %{invitee} to the account as an %{role}",
|
||||
"ADD": "%{agentName} ha convidat %{invitee} al compte com a %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} changed their %{attributes} to %{values}",
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}"
|
||||
"SELF": "%{agentName} ha canviat els seus %{attributes} a %{values}",
|
||||
"OTHER": "%{agentName} ha canviat %{attributes} de %{user} a %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
"ADD": "%{agentName} created a new inbox (#%{id})",
|
||||
"EDIT": "%{agentName} updated an inbox (#%{id})",
|
||||
"DELETE": "%{agentName} deleted an inbox (#%{id})"
|
||||
"ADD": "%{agentName} ha creat una safata d'entrada nova (#%{id})",
|
||||
"EDIT": "%{agentName} ha actualitzat una safata d'entrada (#%{id})",
|
||||
"DELETE": "%{agentName} ha suprimit una safata d'entrada (#%{id})"
|
||||
},
|
||||
"WEBHOOK": {
|
||||
"ADD": "%{agentName} created a new webhook (#%{id})",
|
||||
"EDIT": "%{agentName} updated a webhook (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a webhook (#%{id})"
|
||||
"ADD": "%{agentName} ha creat un nou webhook (#%{id})",
|
||||
"EDIT": "%{agentName} ha actualitzat un webhook (#%{id})",
|
||||
"DELETE": "%{agentName} ha suprimit un webhook (#%{id})"
|
||||
},
|
||||
"USER_ACTION": {
|
||||
"SIGN_IN": "%{agentName} signed in",
|
||||
"SIGN_OUT": "%{agentName} signed out"
|
||||
"SIGN_IN": "%{agentName} ha iniciat la sessió",
|
||||
"SIGN_OUT": "%{agentName} ha tancat la sessió"
|
||||
},
|
||||
"TEAM": {
|
||||
"ADD": "%{agentName} created a new team (#%{id})",
|
||||
"EDIT": "%{agentName} updated a team (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a team (#%{id})"
|
||||
"ADD": "%{agentName} ha creat un equip nou (#%{id})",
|
||||
"EDIT": "%{agentName} ha actualitzat un equip (#%{id})",
|
||||
"DELETE": "%{agentName} ha suprimit un equip (#%{id})"
|
||||
},
|
||||
"MACRO": {
|
||||
"ADD": "%{agentName} created a new macro (#%{id})",
|
||||
"EDIT": "%{agentName} updated a macro (#%{id})",
|
||||
"DELETE": "%{agentName} deleted a macro (#%{id})"
|
||||
"ADD": "%{agentName} ha creat una macro nova (#%{id})",
|
||||
"EDIT": "%{agentName} ha actualitzat una macro (#%{id})",
|
||||
"DELETE": "%{agentName} ha suprimit una macro (#%{id})"
|
||||
},
|
||||
"INBOX_MEMBER": {
|
||||
"ADD": "%{agentName} added %{user} to the inbox(#%{inbox_id})",
|
||||
"REMOVE": "%{agentName} removed %{user} from the inbox(#%{inbox_id})"
|
||||
"ADD": "%{agentName} ha afegit %{user} a la safata d'entrada(#%{inbox_id})",
|
||||
"REMOVE": "%{agentName} ha eliminat %{user} de la safata d'entrada(#%{inbox_id})"
|
||||
},
|
||||
"TEAM_MEMBER": {
|
||||
"ADD": "%{agentName} added %{user} to the team(#%{team_id})",
|
||||
"REMOVE": "%{agentName} removed %{user} from the team(#%{team_id})"
|
||||
"ADD": "%{agentName} ha afegit %{user} a l'equip (#%{team_id})",
|
||||
"REMOVE": "%{agentName} ha eliminat %{user} de l'equip (#%{team_id})"
|
||||
},
|
||||
"ACCOUNT": {
|
||||
"EDIT": "%{agentName} updated the account configuration (#%{id})"
|
||||
"EDIT": "%{agentName} ha actualitzat la configuració del compte (#%{id})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
{
|
||||
"AUTOMATION": {
|
||||
"HEADER": "Automations",
|
||||
"HEADER_BTN_TXT": "Add Automation Rule",
|
||||
"LOADING": "Fetching automation rules",
|
||||
"SIDEBAR_TXT": "<p><b>Automation Rules</b> <p>Automation can replace and automate existing processes that require manual effort. You can do many things with automation, including adding labels and assigning conversation to the best agent. So the team focuses on what they do best and spends more little time on manual tasks.</p>",
|
||||
"HEADER": "Automatització",
|
||||
"HEADER_BTN_TXT": "Afegeix una regla d'automatització",
|
||||
"LOADING": "S'estan recollint regles d'automatització",
|
||||
"SIDEBAR_TXT": "<p><b>Regles d'automatització</b> <p>L'automatització pot substituir i automatitzar processos existents que requereixen un esforç manual. Pots fer moltes coses amb l'automatització, com ara afegir etiquetes i assignar converses al millor agent. Així, l'equip se centra en allò que millor fa i dedica més poc temps a les tasques manuals.</p>",
|
||||
"ADD": {
|
||||
"TITLE": "Add Automation Rule",
|
||||
"TITLE": "Afegeix una regla d'automatització",
|
||||
"SUBMIT": "Crear",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"FORM": {
|
||||
"NAME": {
|
||||
"LABEL": "Rule Name",
|
||||
"PLACEHOLDER": "Enter rule name",
|
||||
"ERROR": "Name is required"
|
||||
"LABEL": "Nom de la regla",
|
||||
"PLACEHOLDER": "Introdueix el nom de la regla",
|
||||
"ERROR": "El valor és necessari"
|
||||
},
|
||||
"DESC": {
|
||||
"LABEL": "Descripció",
|
||||
"PLACEHOLDER": "Enter rule description",
|
||||
"ERROR": "Description is required"
|
||||
"PLACEHOLDER": "Introdueix la descripció de la regla",
|
||||
"ERROR": "La descripció és necessària"
|
||||
},
|
||||
"EVENT": {
|
||||
"LABEL": "Esdeveniment",
|
||||
"PLACEHOLDER": "Please select one",
|
||||
"ERROR": "Event is required"
|
||||
"PLACEHOLDER": "Selecciona un",
|
||||
"ERROR": "És necessari un esdeveniment"
|
||||
},
|
||||
"CONDITIONS": {
|
||||
"LABEL": "Conditions"
|
||||
"LABEL": "Condicions"
|
||||
},
|
||||
"ACTIONS": {
|
||||
"LABEL": "Accions"
|
||||
}
|
||||
},
|
||||
"CONDITION_BUTTON_LABEL": "Add Condition",
|
||||
"ACTION_BUTTON_LABEL": "Add Action",
|
||||
"CONDITION_BUTTON_LABEL": "Afegeix condició",
|
||||
"ACTION_BUTTON_LABEL": "Afegeix acció",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Automation rule added successfully",
|
||||
"ERROR_MESSAGE": "Could not able to create a automation rule, Please try again later"
|
||||
"SUCCESS_MESSAGE": "La regla d'automatització s'ha afegit correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut crear una regla d'automatització. Intenta-ho més tard"
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"TABLE_HEADER": [
|
||||
"Nom",
|
||||
"Descripció",
|
||||
"Active",
|
||||
"Created on"
|
||||
"Actiu",
|
||||
"Creat el"
|
||||
],
|
||||
"404": "No automation rules found"
|
||||
"404": "No s'han trobat regles d'automatització"
|
||||
},
|
||||
"DELETE": {
|
||||
"TITLE": "Delete Automation Rule",
|
||||
"TITLE": "Suprimeix una regla d'automatització",
|
||||
"SUBMIT": "Esborrar",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"CONFIRM": {
|
||||
@@ -58,24 +58,24 @@
|
||||
"NO": "No, segueix "
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Automation rule deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not able to delete a automation rule, Please try again later"
|
||||
"SUCCESS_MESSAGE": "La regla d'automatització s'ha suprimit correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut suprimir una regla d'automatització. Intenta-ho més tard"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Edit Automation Rule",
|
||||
"TITLE": "Edita una regla d'automatització",
|
||||
"SUBMIT": "Actualitza",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Automation rule updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update automation rule, Please try again later"
|
||||
"SUCCESS_MESSAGE": "La regla d'automatització s'ha actualitzat correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut actualitzar una regla d'automatització. Intenta-ho més tard"
|
||||
}
|
||||
},
|
||||
"CLONE": {
|
||||
"TOOLTIP": "Clone",
|
||||
"TOOLTIP": "Clona",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Automation cloned successfully",
|
||||
"ERROR_MESSAGE": "Could not clone automation rule, Please try again later"
|
||||
"SUCCESS_MESSAGE": "L'automatització s'ha clonat correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut clonar una regla d'automatització. Intenta-ho més tard"
|
||||
}
|
||||
},
|
||||
"FORM": {
|
||||
@@ -83,36 +83,36 @@
|
||||
"CREATE": "Crear",
|
||||
"DELETE": "Esborrar",
|
||||
"CANCEL": "Cancel·la",
|
||||
"RESET_MESSAGE": "Changing event type will reset the conditions and events you have added below"
|
||||
"RESET_MESSAGE": "Si canvies el tipus d'esdeveniment, es restabliran les condicions i els esdeveniments que has afegit a continuació"
|
||||
},
|
||||
"CONDITION": {
|
||||
"DELETE_MESSAGE": "You need to have atleast one condition to save",
|
||||
"CONTACT_CUSTOM_ATTR_LABEL": "Contact Custom Attributes",
|
||||
"CONVERSATION_CUSTOM_ATTR_LABEL": "Conversation Custom Attributes"
|
||||
"DELETE_MESSAGE": "Necessites almenys una condició per desar",
|
||||
"CONTACT_CUSTOM_ATTR_LABEL": "Contacta amb Atributs personalitzats",
|
||||
"CONVERSATION_CUSTOM_ATTR_LABEL": "Atributs personalitzats de conversa"
|
||||
},
|
||||
"ACTION": {
|
||||
"DELETE_MESSAGE": "You need to have atleast one action to save",
|
||||
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Enter your message here",
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||
"DELETE_MESSAGE": "Necessites almenys una acció per desar",
|
||||
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Introdueix el teu missatge aquí",
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Selecciona els equips"
|
||||
},
|
||||
"TOGGLE": {
|
||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||
"DEACTIVATION_TITLE": "Deactivate Automation Rule",
|
||||
"ACTIVATION_DESCRIPTION": "This action will activate the automation rule '{automationName}'. Are you sure you want to proceed?",
|
||||
"DEACTIVATION_DESCRIPTION": "This action will deactivate the automation rule '{automationName}'. Are you sure you want to proceed?",
|
||||
"ACTIVATION_SUCCESFUL": "Automation Rule Activated Successfully",
|
||||
"DEACTIVATION_SUCCESFUL": "Automation Rule Deactivated Successfully",
|
||||
"ACTIVATION_ERROR": "Could not Activate Automation, Please try again later",
|
||||
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
|
||||
"ACTIVATION_TITLE": "Activa la regla d'automatització",
|
||||
"DEACTIVATION_TITLE": "Desactiva la regla d'automatització",
|
||||
"ACTIVATION_DESCRIPTION": "Aquesta acció activarà la regla d'automatització '{automationName}'. Estàs segur que vols continuar?",
|
||||
"DEACTIVATION_DESCRIPTION": "Aquesta acció desactivarà la regla d'automatització '{automationName}'. Estàs segur que vols continuar?",
|
||||
"ACTIVATION_SUCCESFUL": "La regla d'automatització s'ha activat correctament",
|
||||
"DEACTIVATION_SUCCESFUL": "La regla d'automatització s'ha desactivat correctament",
|
||||
"ACTIVATION_ERROR": "No s'ha pogut activar l'automatització. Intenta-ho més tard",
|
||||
"DEACTIVATION_ERROR": "No s'ha pogut desactivar l'automatització. Intenta-ho més tard",
|
||||
"CONFIRMATION_LABEL": "Si",
|
||||
"CANCEL_LABEL": "No"
|
||||
},
|
||||
"ATTACHMENT": {
|
||||
"UPLOAD_ERROR": "Could not upload attachment, Please try again",
|
||||
"LABEL_IDLE": "Upload Attachment",
|
||||
"UPLOAD_ERROR": "No s'ha pogut carregar el fitxer adjunt. Torna-ho a provar",
|
||||
"LABEL_IDLE": "Puja fitxer adjunt",
|
||||
"LABEL_UPLOADING": "S'està carregant...",
|
||||
"LABEL_UPLOADED": "Successfully Uploaded",
|
||||
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||
"LABEL_UPLOADED": "S'ha pujat correctament",
|
||||
"LABEL_UPLOAD_FAILED": "Ha fallat la pujada"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
{
|
||||
"BULK_ACTION": {
|
||||
"CONVERSATIONS_SELECTED": "%{conversationCount} conversations selected",
|
||||
"CONVERSATIONS_SELECTED": "%{conversationCount} converses seleccionades",
|
||||
"AGENT_SELECT_LABEL": "Seleccionar Agent",
|
||||
"ASSIGN_CONFIRMATION_LABEL": "Are you sure to assign %{conversationCount} %{conversationLabel} to",
|
||||
"UNASSIGN_CONFIRMATION_LABEL": "Are you sure to unassign %{conversationCount} %{conversationLabel}?",
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_CONFIRMATION_LABEL": "Estas segur d'assignar %{conversationCount} %{conversationLabel} a",
|
||||
"UNASSIGN_CONFIRMATION_LABEL": "Estàs segur de desassignar %{conversationCount} %{conversationLabel}?",
|
||||
"GO_BACK_LABEL": "Torna",
|
||||
"ASSIGN_LABEL": "Assignar",
|
||||
"YES": "Si",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "Conversations visible on this page are only selected.",
|
||||
"AGENT_LIST_LOADING": "Loading agents",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assigna un agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assigna un equip",
|
||||
"ASSIGN_SUCCESFUL": "Les converses s'han assignat correctament.",
|
||||
"ASSIGN_FAILED": "No s'han pogut assignar les converses. Torna-ho a provar.",
|
||||
"RESOLVE_SUCCESFUL": "Les converses s'han resolt correctament.",
|
||||
"RESOLVE_FAILED": "No s'han pogut resoldre les converses. Torna-ho a provar.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "Les converses visibles en aquesta pàgina només estan seleccionades.",
|
||||
"AGENT_LIST_LOADING": "S'estan carregant els agents",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "Change status",
|
||||
"SNOOZE_UNTIL": "Snooze",
|
||||
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
"CHANGE_STATUS": "Canvia l'estat",
|
||||
"SNOOZE_UNTIL": "Posposat",
|
||||
"UPDATE_SUCCESFUL": "L'estat de les converses s'ha actualitzat correctament.",
|
||||
"UPDATE_FAILED": "No s'han pogut actualitzar les converses. Torna-ho a provar."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"NO_LABELS_FOUND": "No labels found for",
|
||||
"ASSIGN_SELECTED_LABELS": "Assign selected labels",
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
"ASSIGN_LABELS": "Assignar etiquetes",
|
||||
"NO_LABELS_FOUND": "No s'han trobat etiquetes per a",
|
||||
"ASSIGN_SELECTED_LABELS": "Assigna les etiquetes seleccionades",
|
||||
"ASSIGN_SUCCESFUL": "L'etiqueta s'ha assignat correctament.",
|
||||
"ASSIGN_FAILED": "No s'han pogut assignar les etiquetes. Torna-ho a provar."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "Selecciona equip",
|
||||
"NONE": "Ningú",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
"NO_TEAMS_AVAILABLE": "Encara no hi ha cap equip afegit a aquest compte.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assigna l'equip seleccionat.",
|
||||
"ASSIGN_SUCCESFUL": "Equips assignats correctament.",
|
||||
"ASSIGN_FAILED": "No s'han pogut assignar els equips. Torna-ho a provar."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
{
|
||||
"CAMPAIGN": {
|
||||
"HEADER": "Campaigns",
|
||||
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
|
||||
"HEADER": "Campanyes",
|
||||
"SIDEBAR_TXT": "Els missatges proactius permeten al client enviar missatges de sortida als seus contactes que desencadenarien més converses. Feu clic a <b>Afegir una campanya</b> per crear una campanya nova. També pots editar o suprimir una campanya existent fent clic al botó Edita o Suprimir.",
|
||||
"HEADER_BTN_TXT": {
|
||||
"ONE_OFF": "Create a one off campaign",
|
||||
"ONGOING": "Create a ongoing campaign"
|
||||
"ONE_OFF": "Crea una campanya única",
|
||||
"ONGOING": "Crea una campanya en curs"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Create a campaign",
|
||||
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
|
||||
"TITLE": "Crea una campanya",
|
||||
"DESC": "Els missatges proactius permeten al client enviar missatges de sortida als seus contactes que desencadenarien més converses.",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"CREATE_BUTTON_TEXT": "Crear",
|
||||
"FORM": {
|
||||
"TITLE": {
|
||||
"LABEL": "Title",
|
||||
"PLACEHOLDER": "Please enter the title of campaign",
|
||||
"ERROR": "Title is required"
|
||||
"LABEL": "Títol",
|
||||
"PLACEHOLDER": "Introduïu el títol de la campanya",
|
||||
"ERROR": "El títol és necessari"
|
||||
},
|
||||
"SCHEDULED_AT": {
|
||||
"LABEL": "Scheduled time",
|
||||
"PLACEHOLDER": "Please select the time",
|
||||
"CONFIRM": "Confirm",
|
||||
"ERROR": "Scheduled time is required"
|
||||
"LABEL": "Hora programada",
|
||||
"PLACEHOLDER": "Selecciona l'hora",
|
||||
"CONFIRM": "Confirma",
|
||||
"ERROR": "Es requereix hora programada"
|
||||
},
|
||||
"AUDIENCE": {
|
||||
"LABEL": "Audience",
|
||||
"PLACEHOLDER": "Select the customer labels",
|
||||
"ERROR": "Audience is required"
|
||||
"LABEL": "Públic",
|
||||
"PLACEHOLDER": "Selecciona les etiquetes dels clients",
|
||||
"ERROR": "L'audiència és obligatòria"
|
||||
},
|
||||
"INBOX": {
|
||||
"LABEL": "Select Inbox",
|
||||
"PLACEHOLDER": "Select Inbox",
|
||||
"ERROR": "Inbox is required"
|
||||
"LABEL": "Selecciona Safata d'entrada",
|
||||
"PLACEHOLDER": "Selecciona Safata d'entrada",
|
||||
"ERROR": "Safata d'entrada és necessària"
|
||||
},
|
||||
"MESSAGE": {
|
||||
"LABEL": "Missatge",
|
||||
"PLACEHOLDER": "Please enter the message of campaign",
|
||||
"ERROR": "Message is required"
|
||||
"PLACEHOLDER": "Introdueix el missatge de la campanya",
|
||||
"ERROR": "El missatge és obligatori"
|
||||
},
|
||||
"SENT_BY": {
|
||||
"LABEL": "Enviat per",
|
||||
"PLACEHOLDER": "Please select the the content of campaign",
|
||||
"ERROR": "Sender is required"
|
||||
"PLACEHOLDER": "Selecciona el contingut de la campanya",
|
||||
"ERROR": "El remitent és obligatori"
|
||||
},
|
||||
"END_POINT": {
|
||||
"LABEL": "URL",
|
||||
"PLACEHOLDER": "Please enter the URL",
|
||||
"PLACEHOLDER": "Introdueix la URL vàlid",
|
||||
"ERROR": "Introduïu una URL vàlid"
|
||||
},
|
||||
"TIME_ON_PAGE": {
|
||||
"LABEL": "Time on page(Seconds)",
|
||||
"PLACEHOLDER": "Please enter the time",
|
||||
"ERROR": "Time on page is required"
|
||||
"LABEL": "Temps a la pàgina (segons)",
|
||||
"PLACEHOLDER": "Introdueix l'hora",
|
||||
"ERROR": "L'hora a la pàgina és obligatori"
|
||||
},
|
||||
"ENABLED": "Enable campaign",
|
||||
"TRIGGER_ONLY_BUSINESS_HOURS": "Trigger only during business hours",
|
||||
"SUBMIT": "Add Campaign"
|
||||
"ENABLED": "Activa la campanya",
|
||||
"TRIGGER_ONLY_BUSINESS_HOURS": "Activa només durant l'horari comercial",
|
||||
"SUBMIT": "Afegeix campanya"
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Campaign created successfully",
|
||||
"ERROR_MESSAGE": "There was an error. Please try again."
|
||||
"SUCCESS_MESSAGE": "La campanya s'ha creat correctament",
|
||||
"ERROR_MESSAGE": "S'ha produït un error. Torna-ho a provar."
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
@@ -71,31 +71,31 @@
|
||||
"NO": "No, segueix "
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Campaign deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not delete the campaign. Please try again later."
|
||||
"SUCCESS_MESSAGE": "La campanya s'ha suprimit correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut esborrar la campanya. Torneu-ho a provar."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Edit campaign",
|
||||
"TITLE": "Edita la campanya",
|
||||
"UPDATE_BUTTON_TEXT": "Actualitza",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Campaign updated successfully",
|
||||
"SUCCESS_MESSAGE": "La campanya s'ha actualitzat correctament",
|
||||
"ERROR_MESSAGE": "S'ha produït un error; tornau-ho a provar"
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "Loading campaigns...",
|
||||
"404": "There are no campaigns created for this inbox.",
|
||||
"LOADING_MESSAGE": "S'estan carregant les campanyes...",
|
||||
"404": "No hi ha cap campanya creada per a aquesta safata d'entrada.",
|
||||
"TABLE_HEADER": {
|
||||
"TITLE": "Title",
|
||||
"TITLE": "Títol",
|
||||
"MESSAGE": "Missatge",
|
||||
"INBOX": "Inbox",
|
||||
"INBOX": "Safata d'entrada",
|
||||
"STATUS": "Estat",
|
||||
"SENDER": "Sender",
|
||||
"SENDER": "Remitent",
|
||||
"URL": "URL",
|
||||
"SCHEDULED_AT": "Scheduled time",
|
||||
"TIME_ON_PAGE": "Time(Seconds)",
|
||||
"CREATED_AT": "Created at"
|
||||
"SCHEDULED_AT": "Hora programada",
|
||||
"TIME_ON_PAGE": "Temps (segons)",
|
||||
"CREATED_AT": "Creat per"
|
||||
},
|
||||
"BUTTONS": {
|
||||
"ADD": "Afegir",
|
||||
@@ -105,22 +105,22 @@
|
||||
"STATUS": {
|
||||
"ENABLED": "Habilita",
|
||||
"DISABLED": "Inhabilita",
|
||||
"COMPLETED": "Completed",
|
||||
"ACTIVE": "Active"
|
||||
"COMPLETED": "Completat",
|
||||
"ACTIVE": "Actiu"
|
||||
},
|
||||
"SENDER": {
|
||||
"BOT": "Bot"
|
||||
}
|
||||
},
|
||||
"ONE_OFF": {
|
||||
"HEADER": "One off campaigns",
|
||||
"404": "There are no one off campaigns created",
|
||||
"INBOXES_NOT_FOUND": "Please create an sms inbox and start adding campaigns"
|
||||
"HEADER": "Campanyes puntuals",
|
||||
"404": "No s'han creat campanyes individuals",
|
||||
"INBOXES_NOT_FOUND": "Crea una safata d'entrada de SMS i comença a afegir campanyes"
|
||||
},
|
||||
"ONGOING": {
|
||||
"HEADER": "Ongoing campaigns",
|
||||
"404": "There are no ongoing campaigns created",
|
||||
"INBOXES_NOT_FOUND": "Please create an website inbox and start adding campaigns"
|
||||
"HEADER": "Campanyes en curs",
|
||||
"404": "No hi ha campanyes en curs creades",
|
||||
"INBOXES_NOT_FOUND": "Crea una safata d'entrada del lloc web i comença a afegir campanyes"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,22 +59,22 @@
|
||||
"TEXT": "Última activitat: La més nova primer"
|
||||
},
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
"TEXT": "Creat a: El més nou primer"
|
||||
},
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
"TEXT": "Creat a: el més antic primer"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
"TEXT": "Prioritat: primer el més alt"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
"TEXT": "Prioritat: primer el més baix"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
"TEXT": "Resposta pendent: el més llarg primer"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
"TEXT": "Resposta pendent: el més curt primer"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
@@ -98,20 +98,20 @@
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_BY_FILTER": {
|
||||
"TITLE": "Sort conversation",
|
||||
"TITLE": "Ordena la conversa",
|
||||
"DROPDOWN_TITLE": "Ordenat per",
|
||||
"ITEMS": {
|
||||
"LATEST": {
|
||||
"NAME": "Last activity at",
|
||||
"LABEL": "Last activity"
|
||||
"NAME": "Darrera activitat a les",
|
||||
"LABEL": "Darrera activitat"
|
||||
},
|
||||
"CREATED_AT": {
|
||||
"NAME": "Creat per",
|
||||
"LABEL": "Creat per"
|
||||
},
|
||||
"LAST_USER_MESSAGE_AT": {
|
||||
"NAME": "Last user message at",
|
||||
"LABEL": "Last message"
|
||||
"NAME": "Últim missatge de l'usuari a les",
|
||||
"LABEL": "Últim missatge"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -120,8 +120,8 @@
|
||||
"REPLY_TO_TWEET": "Respon a aquest tuit",
|
||||
"LINK_TO_STORY": "Ves a la història d'instagram",
|
||||
"SENT": "Enviat correctament",
|
||||
"READ": "Read successfully",
|
||||
"DELIVERED": "Delivered successfully",
|
||||
"READ": "Llegit correctament",
|
||||
"DELIVERED": "S'ha lliurat correctament",
|
||||
"NO_MESSAGES": "Cap Missatge",
|
||||
"NO_CONTENT": "No hi ha contingut disponible",
|
||||
"HIDE_QUOTED_TEXT": "Amaga text entre cometes",
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
"TITLE": "Afegir etiquetes",
|
||||
"PLACEHOLDER": "Cerca etiquetes",
|
||||
"NO_RESULT": "No s'han trobat etiquetes",
|
||||
"CREATE_LABEL": "Create new label"
|
||||
"CREATE_LABEL": "Crea una etiqueta nova"
|
||||
}
|
||||
},
|
||||
"MERGE_CONTACT": "Reagrupa contacte",
|
||||
"CONTACT_ACTIONS": "Accions de contacte",
|
||||
"MUTE_CONTACT": "Block Contact",
|
||||
"UNMUTE_CONTACT": "Unblock Contact",
|
||||
"MUTED_SUCCESS": "This contact is blocked successfully. You will not be notified of any future conversations.",
|
||||
"UNMUTED_SUCCESS": "This contact is unblocked successfully.",
|
||||
"MUTE_CONTACT": "Bloqueja el contacte",
|
||||
"UNMUTE_CONTACT": "Desbloqueja el contacte",
|
||||
"MUTED_SUCCESS": "Aquest contacte s'ha bloquejat correctament. No se us notificarà cap conversa futura.",
|
||||
"UNMUTED_SUCCESS": "Aquest contacte s'ha desbloquejat correctament.",
|
||||
"SEND_TRANSCRIPT": "Envia la transcripció",
|
||||
"EDIT_LABEL": "Edita",
|
||||
"SIDEBAR_SECTIONS": {
|
||||
@@ -72,7 +72,7 @@
|
||||
"SUBMIT": "Importa",
|
||||
"CANCEL": "Cancel·la"
|
||||
},
|
||||
"SUCCESS_MESSAGE": "You will be notified via email when the import is complete.",
|
||||
"SUCCESS_MESSAGE": "Es notificarà per correu electrònic quan s'hagi completat la importació.",
|
||||
"ERROR_MESSAGE": "S'ha produït un error; tornau-ho a provar"
|
||||
},
|
||||
"EXPORT_CONTACTS": {
|
||||
@@ -137,9 +137,9 @@
|
||||
"PLACEHOLDER": "Introdueix el número de telèfon del contacte",
|
||||
"LABEL": "Número de telèfon",
|
||||
"HELP": "Phone number should be of E.164 format eg: +1415555555 [+][country code][area code][local phone number]",
|
||||
"ERROR": "Phone number should be either empty or of E.164 format",
|
||||
"DIAL_CODE_ERROR": "Please select a dial code from the list",
|
||||
"DUPLICATE": "This phone number is in use for another contact."
|
||||
"ERROR": "El número de telèfon ha d'estar buit o en format E.164",
|
||||
"DIAL_CODE_ERROR": "Selecciona un codi de marcatge de la llista",
|
||||
"DUPLICATE": "Aquest número de telèfon està en ús per a un altre contacte."
|
||||
},
|
||||
"LOCATION": {
|
||||
"PLACEHOLDER": "Introdueix la ubicació del contacte",
|
||||
@@ -150,7 +150,7 @@
|
||||
"LABEL": "Nom de la companyia"
|
||||
},
|
||||
"COUNTRY": {
|
||||
"PLACEHOLDER": "Enter the country name",
|
||||
"PLACEHOLDER": "Introdueix el nom del país",
|
||||
"LABEL": "Nom del país",
|
||||
"SELECT_PLACEHOLDER": "Selecciona",
|
||||
"REMOVE": "Suprimeix",
|
||||
@@ -192,7 +192,7 @@
|
||||
"BUTTON_LABEL": "Inicia la conversa",
|
||||
"TITLE": "Nova conversació",
|
||||
"DESC": "Inicia una conversa nova enviant un missatge nou.",
|
||||
"NO_INBOX": "Couldn't find an inbox to initiate a new conversation with this contact.",
|
||||
"NO_INBOX": "No s'ha pogut trobar una safata d'entrada per iniciar una conversa nova amb aquest contacte.",
|
||||
"FORM": {
|
||||
"TO": {
|
||||
"LABEL": "Per"
|
||||
@@ -200,32 +200,32 @@
|
||||
"INBOX": {
|
||||
"LABEL": "Inbox",
|
||||
"PLACEHOLDER": "Trieu la safata d'entrada d'origen",
|
||||
"ERROR": "Select an inbox"
|
||||
"ERROR": "Selecciona una Safata d'entrada"
|
||||
},
|
||||
"SUBJECT": {
|
||||
"LABEL": "Assumpte",
|
||||
"PLACEHOLDER": "Assumpte",
|
||||
"ERROR": "Subject can't be empty"
|
||||
"ERROR": "L'assumpte no pot estar buit"
|
||||
},
|
||||
"MESSAGE": {
|
||||
"LABEL": "Missatge",
|
||||
"PLACEHOLDER": "Write your message here",
|
||||
"PLACEHOLDER": "Escriu el teu missatge aquí",
|
||||
"ERROR": "El missatge no pot estar buit"
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
"SELECT": "Trieu fitxers",
|
||||
"HELP_TEXT": "Arrossegueu i deixeu anar fitxers aquí o trieu fitxers per adjuntar"
|
||||
},
|
||||
"SUBMIT": "Send message",
|
||||
"SUBMIT": "Envia missatge",
|
||||
"CANCEL": "Cancel·la",
|
||||
"SUCCESS_MESSAGE": "Message sent!",
|
||||
"SUCCESS_MESSAGE": "Missatges enviat!",
|
||||
"GO_TO_CONVERSATION": "Veure",
|
||||
"ERROR_MESSAGE": "Couldn't send! try again"
|
||||
"ERROR_MESSAGE": "No s'ha pogut enviar! torna-ho a provar"
|
||||
}
|
||||
},
|
||||
"CONTACTS_PAGE": {
|
||||
"HEADER": "Contactes",
|
||||
"FIELDS": "Contact fields",
|
||||
"FIELDS": "Camps de contacte",
|
||||
"SEARCH_BUTTON": "Cercar",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "Cerca de contactes",
|
||||
"FILTER_CONTACTS": "Filtre",
|
||||
@@ -235,25 +235,25 @@
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "Carregant contactes...",
|
||||
"404": "No hi ha cap contacte que coincideixi amb la vostra cerca 🔍",
|
||||
"NO_CONTACTS": "There are no available contacts",
|
||||
"NO_CONTACTS": "No hi ha contactes disponibles",
|
||||
"TABLE_HEADER": {
|
||||
"NAME": "Nom",
|
||||
"PHONE_NUMBER": "Número de telèfon",
|
||||
"CONVERSATIONS": "Converses",
|
||||
"LAST_ACTIVITY": "Last Activity",
|
||||
"CREATED_AT": "Created At",
|
||||
"LAST_ACTIVITY": "Darrera activitat",
|
||||
"CREATED_AT": "Creat per",
|
||||
"COUNTRY": "País",
|
||||
"CITY": "Ciutat",
|
||||
"SOCIAL_PROFILES": "Social Profiles",
|
||||
"SOCIAL_PROFILES": "Perfils socials",
|
||||
"COMPANY": "Companyia",
|
||||
"EMAIL_ADDRESS": "Adreça de correu electrònic"
|
||||
},
|
||||
"VIEW_DETAILS": "View details"
|
||||
"VIEW_DETAILS": "Veure detalls"
|
||||
}
|
||||
},
|
||||
"CONTACT_PROFILE": {
|
||||
"BACK_BUTTON": "Contactes",
|
||||
"LOADING": "Loading contact profile..."
|
||||
"LOADING": "S'està carregant el perfil de contacte..."
|
||||
},
|
||||
"REMINDER": {
|
||||
"ADD_BUTTON": {
|
||||
@@ -267,7 +267,7 @@
|
||||
},
|
||||
"NOTES": {
|
||||
"FETCHING_NOTES": "S'estan obtenint notes...",
|
||||
"NOT_AVAILABLE": "There are no notes created for this contact",
|
||||
"NOT_AVAILABLE": "No s'han creat notes per a aquest contacte",
|
||||
"HEADER": {
|
||||
"TITLE": "Notes"
|
||||
},
|
||||
@@ -318,8 +318,8 @@
|
||||
"ERROR": "El nom de l'atribut personalitzat no és vàlid"
|
||||
},
|
||||
"VALUE": {
|
||||
"LABEL": "Attribute value",
|
||||
"PLACEHOLDER": "Eg: 11901 "
|
||||
"LABEL": "Valor de l'atribut",
|
||||
"PLACEHOLDER": "Ex: 11901 "
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Crear nou atribut ",
|
||||
@@ -348,27 +348,27 @@
|
||||
}
|
||||
},
|
||||
"VALIDATIONS": {
|
||||
"REQUIRED": "Valid value is required",
|
||||
"INVALID_URL": "Invalid URL",
|
||||
"INVALID_INPUT": "Invalid Input"
|
||||
"REQUIRED": "Un valor vàlid és necessari",
|
||||
"INVALID_URL": "URL no vàlid",
|
||||
"INVALID_INPUT": "Entrada incorrecta"
|
||||
}
|
||||
},
|
||||
"MERGE_CONTACTS": {
|
||||
"TITLE": "Merge contacts",
|
||||
"TITLE": "Fusiona contactes",
|
||||
"DESCRIPTION": "Merge contacts to combine two profiles into one, including all attributes and conversations. In case of conflict, the Primary contact’ s attributes will take precedence.",
|
||||
"PRIMARY": {
|
||||
"TITLE": "Primary contact",
|
||||
"HELP_LABEL": "To be deleted"
|
||||
"TITLE": "Contacte principal",
|
||||
"HELP_LABEL": "Per esborrar"
|
||||
},
|
||||
"PARENT": {
|
||||
"TITLE": "Contact to merge",
|
||||
"PLACEHOLDER": "Search for a contact",
|
||||
"HELP_LABEL": "To be kept"
|
||||
"TITLE": "Contacte per fusionar",
|
||||
"PLACEHOLDER": "Cerca un contacte",
|
||||
"HELP_LABEL": "S'ha de mantenir"
|
||||
},
|
||||
"SUMMARY": {
|
||||
"TITLE": "Resum",
|
||||
"DELETE_WARNING": "Contact of <strong>%{primaryContactName}</strong> will be deleted.",
|
||||
"ATTRIBUTE_WARNING": "Contact details of <strong>%{primaryContactName}</strong> will be copied to <strong>%{parentContactName}</strong>."
|
||||
"DELETE_WARNING": "El contacte de <strong>%{primaryContactName}</strong> es suprimirà.",
|
||||
"ATTRIBUTE_WARNING": "Les dades de contacte de <strong>%{primaryContactName}</strong> es copiaran a <strong>%{parentContactName}</strong>."
|
||||
},
|
||||
"SEARCH": {
|
||||
"ERROR": "ERROR_MESSAGE"
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"CONTACTS_FILTER": {
|
||||
"TITLE": "Filter Contacts",
|
||||
"SUBTITLE": "Add filters below and hit 'Submit' to filter contacts.",
|
||||
"EDIT_CUSTOM_SEGMENT": "Edit Segment",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your segment.",
|
||||
"TITLE": "Filtra els contactes",
|
||||
"SUBTITLE": "Afegeix filtres a continuació i prem \"Envia\" per filtrar els contactes.",
|
||||
"EDIT_CUSTOM_SEGMENT": "Edita segment",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Afegeix o elimina filtres i actualitza el teu segment.",
|
||||
"ADD_NEW_FILTER": "Afegeix filtre",
|
||||
"CLEAR_ALL_FILTERS": "Clear All Filters",
|
||||
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
|
||||
"CLEAR_ALL_FILTERS": "Esborra tots els filtres",
|
||||
"FILTER_DELETE_ERROR": "Hauries de tenir almenys un filtre per desar",
|
||||
"SUBMIT_BUTTON_LABEL": "Envia",
|
||||
"UPDATE_BUTTON_LABEL": "Update Segment",
|
||||
"UPDATE_BUTTON_LABEL": "Actualitza el segment",
|
||||
"CANCEL_BUTTON_LABEL": "Cancel·la",
|
||||
"CLEAR_BUTTON_LABEL": "Clear Filters",
|
||||
"CLEAR_BUTTON_LABEL": "Esborra els filtres",
|
||||
"EMPTY_VALUE_ERROR": "El valor és necessari",
|
||||
"SEGMENT_LABEL": "Segment Name",
|
||||
"SEGMENT_QUERY_LABEL": "Segment Query",
|
||||
"TOOLTIP_LABEL": "Filter contacts",
|
||||
"SEGMENT_LABEL": "Nom del segment",
|
||||
"SEGMENT_QUERY_LABEL": "Consulta de segments",
|
||||
"TOOLTIP_LABEL": "Filtra els contactes",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "I",
|
||||
"OR": "O"
|
||||
@@ -27,14 +27,14 @@
|
||||
"is_present": "És present",
|
||||
"is_not_present": "No és present",
|
||||
"is_greater_than": "És més gran que",
|
||||
"is_lesser_than": "Is lesser than",
|
||||
"is_lesser_than": "És més petit que",
|
||||
"days_before": "És x dies abans"
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"NAME": "Nom",
|
||||
"EMAIL": "Correu electrònic",
|
||||
"PHONE_NUMBER": "Número de telèfon",
|
||||
"IDENTIFIER": "Identifier",
|
||||
"IDENTIFIER": "Identificador",
|
||||
"CITY": "Ciutat",
|
||||
"COUNTRY": "País",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "Llista",
|
||||
@@ -42,14 +42,14 @@
|
||||
"CUSTOM_ATTRIBUTE_NUMBER": "Número",
|
||||
"CUSTOM_ATTRIBUTE_LINK": "Enllaç",
|
||||
"CUSTOM_ATTRIBUTE_CHECKBOX": "Casella de selecció",
|
||||
"CREATED_AT": "Created At",
|
||||
"LAST_ACTIVITY": "Last Activity",
|
||||
"REFERER_LINK": "Referrer link",
|
||||
"CREATED_AT": "Creat per",
|
||||
"LAST_ACTIVITY": "Darrera activitat",
|
||||
"REFERER_LINK": "Enllaç de referència",
|
||||
"BLOCKED": "Blocat"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "Standard Filters",
|
||||
"ADDITIONAL_FILTERS": "Additional Filters",
|
||||
"STANDARD_FILTERS": "Filtres estàndard",
|
||||
"ADDITIONAL_FILTERS": "Filtres addicionals",
|
||||
"CUSTOM_ATTRIBUTES": "Atributs personalitzats"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,19 +40,19 @@
|
||||
"UNKNOWN_FILE_TYPE": "Fitxer desconegut",
|
||||
"SAVE_CONTACT": "Desar",
|
||||
"UPLOADING_ATTACHMENTS": "Pujant fitxers adjunts...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"UNSUPPORTED_MESSAGE": "This message is unsupported.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
|
||||
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
|
||||
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
|
||||
"REPLIED_TO_STORY": "Va respondre a la teva història",
|
||||
"UNSUPPORTED_MESSAGE": "Aquest missatge no està suportat.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "Aquest missatge no està suportat. Pots veure aquest missatge a l'aplicació Facebook Messenger.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "Aquest missatge no està suportat. Pots veure aquest missatge a l'aplicació d'Instagram.",
|
||||
"SUCCESS_DELETE_MESSAGE": "El missatge s'ha suprimit correctament",
|
||||
"FAIL_DELETE_MESSSAGE": "No s'ha pogut suprimir el missatge! Torna-ho a provar",
|
||||
"NO_RESPONSE": "Sense resposta",
|
||||
"RATING_TITLE": "Rating",
|
||||
"FEEDBACK_TITLE": "Feedback",
|
||||
"REPLY_MESSAGE_NOT_FOUND": "Message not available",
|
||||
"RATING_TITLE": "Valoració",
|
||||
"FEEDBACK_TITLE": "Comentaris",
|
||||
"REPLY_MESSAGE_NOT_FOUND": "Missatge no disponible",
|
||||
"CARD": {
|
||||
"SHOW_LABELS": "Show labels",
|
||||
"HIDE_LABELS": "Hide labels"
|
||||
"SHOW_LABELS": "Mostra etiquetes",
|
||||
"HIDE_LABELS": "Amaga etiquetes"
|
||||
},
|
||||
"HEADER": {
|
||||
"RESOLVE_ACTION": "Resoldre",
|
||||
@@ -61,31 +61,31 @@
|
||||
"OPEN": "Més",
|
||||
"CLOSE": "Tanca",
|
||||
"DETAILS": "detalls",
|
||||
"SNOOZED_UNTIL": "Snoozed until",
|
||||
"SNOOZED_UNTIL_TOMORROW": "Snoozed until tomorrow",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "Snoozed until next week",
|
||||
"SNOOZED_UNTIL_NEXT_REPLY": "Snoozed until next reply",
|
||||
"SNOOZED_UNTIL": "Posposat fins a",
|
||||
"SNOOZED_UNTIL_TOMORROW": "Posposat fins demà",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "Posposat fins a la setmana vinent",
|
||||
"SNOOZED_UNTIL_NEXT_REPLY": "Posposat fins a la següent resposta",
|
||||
"SLA_STATUS": {
|
||||
"FRT": "FRT {status}",
|
||||
"NRT": "NRT {status}",
|
||||
"RT": "RT {status}",
|
||||
"MISSED": "missed",
|
||||
"DUE": "due"
|
||||
"MISSED": "perduda",
|
||||
"DUE": "límit"
|
||||
}
|
||||
},
|
||||
"RESOLVE_DROPDOWN": {
|
||||
"MARK_PENDING": "Mark as pending",
|
||||
"SNOOZE_UNTIL": "Snooze",
|
||||
"MARK_PENDING": "Marca com a pendent",
|
||||
"SNOOZE_UNTIL": "Posposat",
|
||||
"SNOOZE": {
|
||||
"TITLE": "Snooze until",
|
||||
"NEXT_REPLY": "Next reply",
|
||||
"TOMORROW": "Tomorrow",
|
||||
"NEXT_WEEK": "Next week"
|
||||
"TITLE": "Posposat fins a",
|
||||
"NEXT_REPLY": "Següent resposta",
|
||||
"TOMORROW": "Demà",
|
||||
"NEXT_WEEK": "Pròxima setmana"
|
||||
}
|
||||
},
|
||||
"CUSTOM_SNOOZE": {
|
||||
"TITLE": "Snooze until",
|
||||
"APPLY": "Snooze",
|
||||
"TITLE": "Posposat fins a",
|
||||
"APPLY": "Posposat",
|
||||
"CANCEL": "Cancel·la"
|
||||
},
|
||||
"PRIORITY": {
|
||||
@@ -93,92 +93,92 @@
|
||||
"OPTIONS": {
|
||||
"NONE": "Ningú",
|
||||
"URGENT": "Urgent",
|
||||
"HIGH": "High",
|
||||
"MEDIUM": "Medium",
|
||||
"LOW": "Low"
|
||||
"HIGH": "Alta",
|
||||
"MEDIUM": "Mitjana",
|
||||
"LOW": "Baixa"
|
||||
},
|
||||
"CHANGE_PRIORITY": {
|
||||
"SELECT_PLACEHOLDER": "Ningú",
|
||||
"INPUT_PLACEHOLDER": "Select priority",
|
||||
"INPUT_PLACEHOLDER": "Selecciona la prioritat",
|
||||
"NO_RESULTS": "No s'ha trobat agents",
|
||||
"SUCCESSFUL": "Changed priority of conversation id %{conversationId} to %{priority}",
|
||||
"FAILED": "Couldn't change priority. Please try again."
|
||||
"SUCCESSFUL": "S'ha canviat la prioritat de l'identificador de conversa %{conversationId} a %{priority}",
|
||||
"FAILED": "No s'ha pogut canviar la prioritat. Si us plau, torna-ho a provar."
|
||||
}
|
||||
},
|
||||
"CARD_CONTEXT_MENU": {
|
||||
"PENDING": "Mark as pending",
|
||||
"RESOLVED": "Mark as resolved",
|
||||
"MARK_AS_UNREAD": "Mark as unread",
|
||||
"PENDING": "Marca com a pendent",
|
||||
"RESOLVED": "Marca com a resolt",
|
||||
"MARK_AS_UNREAD": "Marca com a no llegit",
|
||||
"REOPEN": "Torna a obrir la conversa",
|
||||
"SNOOZE": {
|
||||
"TITLE": "Snooze",
|
||||
"NEXT_REPLY": "Until next reply",
|
||||
"TOMORROW": "Until tomorrow",
|
||||
"NEXT_WEEK": "Until next week"
|
||||
"TITLE": "Posposat",
|
||||
"NEXT_REPLY": "Fins a la propera resposta",
|
||||
"TOMORROW": "Fins demà",
|
||||
"NEXT_WEEK": "Fins a la setmana vinent"
|
||||
},
|
||||
"ASSIGN_AGENT": "Assign agent",
|
||||
"ASSIGN_LABEL": "Assign label",
|
||||
"AGENTS_LOADING": "Loading agents...",
|
||||
"ASSIGN_TEAM": "Assign team",
|
||||
"ASSIGN_AGENT": "Assigna un agent",
|
||||
"ASSIGN_LABEL": "Assigna etiqueta",
|
||||
"AGENTS_LOADING": "S'estan carregant els agents...",
|
||||
"ASSIGN_TEAM": "Assigna un equip",
|
||||
"API": {
|
||||
"AGENT_ASSIGNMENT": {
|
||||
"SUCCESFUL": "Conversation id %{conversationId} assigned to \"%{agentName}\"",
|
||||
"FAILED": "Couldn't assign agent. Please try again."
|
||||
"SUCCESFUL": "Id de conversa %{conversationId} assignat a \"%{agentName}\"",
|
||||
"FAILED": "No s'ha pogut assignar l'agent. Torna-ho a provar."
|
||||
},
|
||||
"LABEL_ASSIGNMENT": {
|
||||
"SUCCESFUL": "Assigned label #%{labelName} to conversation id %{conversationId}",
|
||||
"FAILED": "Couldn't assign label. Please try again."
|
||||
"SUCCESFUL": "S'ha assignat l'etiqueta #%{labelName} a l'id de conversa %{conversationId}",
|
||||
"FAILED": "No s'ha pogut assignar l'etiqueta. Torna-ho a provar."
|
||||
},
|
||||
"TEAM_ASSIGNMENT": {
|
||||
"SUCCESFUL": "Assigned team \"%{team}\" to conversation id %{conversationId}",
|
||||
"FAILED": "Couldn't assign team. Please try again."
|
||||
"SUCCESFUL": "S'ha assignat l'equip \"%{team}\" a l'id de conversa %{conversationId}",
|
||||
"FAILED": "No s'ha pogut assignar l'equip. Torna-ho a provar."
|
||||
}
|
||||
}
|
||||
},
|
||||
"FOOTER": {
|
||||
"MESSAGE_SIGN_TOOLTIP": "Message signature",
|
||||
"ENABLE_SIGN_TOOLTIP": "Enable signature",
|
||||
"DISABLE_SIGN_TOOLTIP": "Disable signature",
|
||||
"MESSAGE_SIGN_TOOLTIP": "Signatura del missatge",
|
||||
"ENABLE_SIGN_TOOLTIP": "Activa la signatura",
|
||||
"DISABLE_SIGN_TOOLTIP": "Desactiva la signatura",
|
||||
"MSG_INPUT": "Shift + enter per a una línia nova. Comença amb '/' per seleccionar una resposta predeterminada.",
|
||||
"PRIVATE_MSG_INPUT": "Shift + enter per una línia nova. Això serà visible només per als Agents",
|
||||
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
|
||||
"CLICK_HERE": "Click here to update"
|
||||
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "La signatura del missatge no està configurada, configura-la a la configuració del perfil.",
|
||||
"CLICK_HERE": "Fes clic aquí per actualitzar"
|
||||
},
|
||||
"REPLYBOX": {
|
||||
"REPLY": "Respon",
|
||||
"PRIVATE_NOTE": "Nota privada",
|
||||
"SEND": "Envia",
|
||||
"CREATE": "Afegeix una nota",
|
||||
"INSERT_READ_MORE": "Read more",
|
||||
"DISMISS_REPLY": "Dismiss reply",
|
||||
"REPLYING_TO": "Replying to:",
|
||||
"INSERT_READ_MORE": "Llegir més",
|
||||
"DISMISS_REPLY": "Ignora la resposta",
|
||||
"REPLYING_TO": "Responent a:",
|
||||
"TIP_FORMAT_ICON": "Mostra l'editor de text enriquit",
|
||||
"TIP_EMOJI_ICON": "Mostra la selecció d'emoticones",
|
||||
"TIP_ATTACH_ICON": "Ajuntar fitxers",
|
||||
"TIP_AUDIORECORDER_ICON": "Record audio",
|
||||
"TIP_AUDIORECORDER_PERMISSION": "Allow access to audio",
|
||||
"TIP_AUDIORECORDER_ERROR": "Could not open the audio",
|
||||
"DRAG_DROP": "Drag and drop here to attach",
|
||||
"START_AUDIO_RECORDING": "Start audio recording",
|
||||
"STOP_AUDIO_RECORDING": "Stop audio recording",
|
||||
"TIP_AUDIORECORDER_ICON": "Gravar àudio",
|
||||
"TIP_AUDIORECORDER_PERMISSION": "Permet l'accés a l'àudio",
|
||||
"TIP_AUDIORECORDER_ERROR": "No s'ha pogut obrir l'àudio",
|
||||
"DRAG_DROP": "Arrossega i deixa anar aquí per adjuntar-lo",
|
||||
"START_AUDIO_RECORDING": "Inicia la gravació d'àudio",
|
||||
"STOP_AUDIO_RECORDING": "Atura la gravació d'àudio",
|
||||
"": "",
|
||||
"EMAIL_HEAD": {
|
||||
"TO": "TO",
|
||||
"ADD_BCC": "Add bcc",
|
||||
"TO": "A",
|
||||
"ADD_BCC": "Afegeix cco",
|
||||
"CC": {
|
||||
"LABEL": "CC",
|
||||
"PLACEHOLDER": "Emails separated by commas",
|
||||
"ERROR": "Please enter valid email addresses"
|
||||
"PLACEHOLDER": "Correus electrònics separats per comes",
|
||||
"ERROR": "Introduïu adreces de correu electrònic vàlides"
|
||||
},
|
||||
"BCC": {
|
||||
"LABEL": "BCC",
|
||||
"PLACEHOLDER": "Emails separated by commas",
|
||||
"ERROR": "Please enter valid email addresses"
|
||||
"LABEL": "CCO",
|
||||
"PLACEHOLDER": "Correus electrònics separats per comes",
|
||||
"ERROR": "Introduïu adreces de correu electrònic vàlides"
|
||||
}
|
||||
},
|
||||
"UNDEFINED_VARIABLES": {
|
||||
"TITLE": "Undefined variables",
|
||||
"MESSAGE": "You have {undefinedVariablesCount} undefined variables in your message: {undefinedVariables}. Would you like to send the message anyway?",
|
||||
"TITLE": "Variables sense definir",
|
||||
"MESSAGE": "Tens {undefinedVariablesCount} variables sense definir al teu missatge: {undefinedVariables}. Vols enviar el missatge igualment?",
|
||||
"CONFIRM": {
|
||||
"YES": "Envia",
|
||||
"CANCEL": "Cancel·la"
|
||||
@@ -187,18 +187,18 @@
|
||||
},
|
||||
"VISIBLE_TO_AGENTS": "Nota privada: Només és visible per tu i el vostre equip",
|
||||
"CHANGE_STATUS": "Estat de la conversa canviat",
|
||||
"CHANGE_STATUS_FAILED": "Conversation status change failed",
|
||||
"CHANGE_STATUS_FAILED": "No s'ha pogut canviar l'estat de la conversa",
|
||||
"CHANGE_AGENT": "Assignació de la conversa canviat",
|
||||
"CHANGE_AGENT_FAILED": "Assignee change failed",
|
||||
"ASSIGN_LABEL_SUCCESFUL": "Label assigned successfully",
|
||||
"ASSIGN_LABEL_FAILED": "Label assignment failed",
|
||||
"CHANGE_TEAM": "Conversation team changed",
|
||||
"FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB attachment limit",
|
||||
"MESSAGE_ERROR": "Unable to send this message, please try again later",
|
||||
"CHANGE_AGENT_FAILED": "El canvi de l'assignat ha fallat",
|
||||
"ASSIGN_LABEL_SUCCESFUL": "L'etiqueta s'ha assignat correctament",
|
||||
"ASSIGN_LABEL_FAILED": "L'assignació d'etiquetes ha fallat",
|
||||
"CHANGE_TEAM": "L'equip de conversa ha canviat",
|
||||
"FILE_SIZE_LIMIT": "El fitxer supera el límit de {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB fitxers adjunts",
|
||||
"MESSAGE_ERROR": "No es pot enviar aquest missatge, torna-ho a provar més tard",
|
||||
"SENT_BY": "Enviat per:",
|
||||
"BOT": "Bot",
|
||||
"SEND_FAILED": "Couldn't send message! Try again",
|
||||
"TRY_AGAIN": "retry",
|
||||
"SEND_FAILED": "No s'ha pogut enviar el missatge! Torna-ho a provar",
|
||||
"TRY_AGAIN": "reintenta",
|
||||
"ASSIGNMENT": {
|
||||
"SELECT_AGENT": "Seleccionar Agent",
|
||||
"REMOVE": "Suprimeix",
|
||||
@@ -206,15 +206,15 @@
|
||||
},
|
||||
"CONTEXT_MENU": {
|
||||
"COPY": "Copia",
|
||||
"REPLY_TO": "Reply to this message",
|
||||
"REPLY_TO": "Respon a aquest missatge",
|
||||
"DELETE": "Esborrar",
|
||||
"CREATE_A_CANNED_RESPONSE": "Add to canned responses",
|
||||
"TRANSLATE": "Translate",
|
||||
"COPY_PERMALINK": "Copy link to the message",
|
||||
"LINK_COPIED": "Message URL copied to the clipboard",
|
||||
"CREATE_A_CANNED_RESPONSE": "Afegir a les respostes predeterminades",
|
||||
"TRANSLATE": "Tradueix",
|
||||
"COPY_PERMALINK": "Copia l'enllaç al missatge",
|
||||
"LINK_COPIED": "URL del missatge copiat al porta-retalls",
|
||||
"DELETE_CONFIRMATION": {
|
||||
"TITLE": "Are you sure you want to delete this message?",
|
||||
"MESSAGE": "You cannot undo this action",
|
||||
"TITLE": "Estàs segur que vols suprimir aquest missatge?",
|
||||
"MESSAGE": "No pots desfer aquesta acció",
|
||||
"DELETE": "Esborrar",
|
||||
"CANCEL": "Cancel·la"
|
||||
}
|
||||
@@ -238,48 +238,48 @@
|
||||
}
|
||||
},
|
||||
"ONBOARDING": {
|
||||
"TITLE": "Hey 👋, Welcome to %{installationName}!",
|
||||
"DESCRIPTION": "Thanks for signing up. We want you to get the most out of %{installationName}. Here are a few things you can do in %{installationName} to make the experience delightful.",
|
||||
"READ_LATEST_UPDATES": "Read our latest updates",
|
||||
"TITLE": "Hola 👋, Benvingut a %{installationName}!",
|
||||
"DESCRIPTION": "Gràcies per registrar-te. Volem que treguis el màxim profit de %{installationName}. Aquí teniu algunes coses que pots fer a %{installationName} perquè l'experiència sigui agradable.",
|
||||
"READ_LATEST_UPDATES": "Llegiu les nostres últimes actualitzacions",
|
||||
"ALL_CONVERSATION": {
|
||||
"TITLE": "All your conversations in one place",
|
||||
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status."
|
||||
"TITLE": "Totes les teves converses en un sol lloc",
|
||||
"DESCRIPTION": "Consulta totes les converses dels teus clients en un únic tauler. Podeu filtrar les converses pel canal d'entrada, l'etiqueta i l'estat."
|
||||
},
|
||||
"TEAM_MEMBERS": {
|
||||
"TITLE": "Invite your team members",
|
||||
"DESCRIPTION": "Since you are getting ready to talk to your customer, bring in your teammates to assist you. You can invite your teammates by adding their email addresses to the agent list.",
|
||||
"NEW_LINK": "Click here to invite a team member"
|
||||
"TITLE": "Convida els membres del teu equip",
|
||||
"DESCRIPTION": "Com que us esteu preparant per parlar amb el vostre client, feu venir els vostres companys d'equip per ajudar-vos. Pots convidar els teus companys d'equip afegint les seves adreces de correu electrònic a la llista d'agents.",
|
||||
"NEW_LINK": "Feu clic aquí per convidar un membre de l'equip"
|
||||
},
|
||||
"INBOXES": {
|
||||
"TITLE": "Connect Inboxes",
|
||||
"TITLE": "Connecta les safates d'entrada",
|
||||
"DESCRIPTION": "Connect various channels through which your customers would be talking to you. It can be a website live-chat, your Facebook or Twitter page or even your WhatsApp number.",
|
||||
"NEW_LINK": "Click here to create an inbox"
|
||||
"NEW_LINK": "Fes clic aquí per crear una safata d'entrada"
|
||||
},
|
||||
"LABELS": {
|
||||
"TITLE": "Organize conversations with labels",
|
||||
"DESCRIPTION": "Labels provide an easier way to categorize your conversation. Create some labels like #support-enquiry, #billing-question etc., so that you can use them in a conversation later.",
|
||||
"NEW_LINK": "Click here to create tags"
|
||||
"TITLE": "Organitza converses amb etiquetes",
|
||||
"DESCRIPTION": "Les etiquetes proporcionen una manera més fàcil de classificar la vostra conversa. Crea algunes etiquetes com #consulta-suport, #pregunta-facturació, etc., perquè les puguis utilitzar en una conversa més endavant.",
|
||||
"NEW_LINK": "Fes clic aquí per crear etiquetes"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_SIDEBAR": {
|
||||
"ASSIGNEE_LABEL": "Assigned Agent",
|
||||
"SELF_ASSIGN": "Assign to me",
|
||||
"TEAM_LABEL": "Assigned Team",
|
||||
"ASSIGNEE_LABEL": "Agent assignat",
|
||||
"SELF_ASSIGN": "Assigna-me-la",
|
||||
"TEAM_LABEL": "Assignada a un equip",
|
||||
"SELECT": {
|
||||
"PLACEHOLDER": "None"
|
||||
"PLACEHOLDER": "Ningú"
|
||||
},
|
||||
"ACCORDION": {
|
||||
"CONTACT_DETAILS": "Contact Details",
|
||||
"CONVERSATION_ACTIONS": "Conversation Actions",
|
||||
"CONTACT_DETAILS": "Detalls de contacte",
|
||||
"CONVERSATION_ACTIONS": "Accions de conversa",
|
||||
"CONVERSATION_LABELS": "Etiquetes de converses",
|
||||
"CONVERSATION_INFO": "Conversation Information",
|
||||
"CONTACT_ATTRIBUTES": "Contact Attributes",
|
||||
"CONVERSATION_INFO": "Informació de la conversa",
|
||||
"CONTACT_ATTRIBUTES": "Atributs de contacte",
|
||||
"PREVIOUS_CONVERSATION": "Converses prèvies",
|
||||
"MACROS": "Macros"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_CUSTOM_ATTRIBUTES": {
|
||||
"ADD_BUTTON_TEXT": "Create attribute",
|
||||
"ADD_BUTTON_TEXT": "Crea atribut",
|
||||
"NO_RECORDS_FOUND": "No s'han trobat atributs",
|
||||
"UPDATE": {
|
||||
"SUCCESS": "Atribut actualitzat correctament",
|
||||
@@ -301,34 +301,34 @@
|
||||
}
|
||||
},
|
||||
"EMAIL_HEADER": {
|
||||
"FROM": "From",
|
||||
"FROM": "Des de",
|
||||
"TO": "Per",
|
||||
"BCC": "Bcc",
|
||||
"BCC": "Cco",
|
||||
"CC": "Cc",
|
||||
"SUBJECT": "Subject"
|
||||
"SUBJECT": "Assumpte"
|
||||
},
|
||||
"CONVERSATION_PARTICIPANTS": {
|
||||
"SIDEBAR_MENU_TITLE": "Participating",
|
||||
"SIDEBAR_TITLE": "Conversation participants",
|
||||
"SIDEBAR_MENU_TITLE": "Participant",
|
||||
"SIDEBAR_TITLE": "Participants de la conversa",
|
||||
"NO_RECORDS_FOUND": "No s'ha trobat agents",
|
||||
"ADD_PARTICIPANTS": "Select participants",
|
||||
"REMANING_PARTICIPANTS_TEXT": "+%{count} others",
|
||||
"REMANING_PARTICIPANT_TEXT": "+%{count} other",
|
||||
"TOTAL_PARTICIPANTS_TEXT": "%{count} people are participating.",
|
||||
"TOTAL_PARTICIPANT_TEXT": "%{count} person is participating.",
|
||||
"NO_PARTICIPANTS_TEXT": "No one is participating!.",
|
||||
"WATCH_CONVERSATION": "Join conversation",
|
||||
"YOU_ARE_WATCHING": "You are participating",
|
||||
"ADD_PARTICIPANTS": "Selecciona els participants",
|
||||
"REMANING_PARTICIPANTS_TEXT": "+%{count} més",
|
||||
"REMANING_PARTICIPANT_TEXT": "+%{count} més",
|
||||
"TOTAL_PARTICIPANTS_TEXT": "%{count} persones estan participant.",
|
||||
"TOTAL_PARTICIPANT_TEXT": "%{count} persona està participant.",
|
||||
"NO_PARTICIPANTS_TEXT": "No hi participa ningú!",
|
||||
"WATCH_CONVERSATION": "Uneix-te a la conversa",
|
||||
"YOU_ARE_WATCHING": "Estàs participant",
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "Could not update, try again!",
|
||||
"SUCCESS_MESSAGE": "Participants updated!"
|
||||
"ERROR_MESSAGE": "No s'ha pogut actualitzar, torna-ho a provar!",
|
||||
"SUCCESS_MESSAGE": "Participants actualitzats!"
|
||||
}
|
||||
},
|
||||
"TRANSLATE_MODAL": {
|
||||
"TITLE": "View translated content",
|
||||
"DESC": "You can view the translated content in each langauge.",
|
||||
"ORIGINAL_CONTENT": "Original Content",
|
||||
"TRANSLATED_CONTENT": "Translated Content",
|
||||
"NO_TRANSLATIONS_AVAILABLE": "No translations are available for this content"
|
||||
"TITLE": "Veure contingut traduït",
|
||||
"DESC": "Pots veure el contingut traduït a cada idioma.",
|
||||
"ORIGINAL_CONTENT": "Contingut original",
|
||||
"TRANSLATED_CONTENT": "Contingut traduït",
|
||||
"NO_TRANSLATIONS_AVAILABLE": "No hi ha traduccions disponibles per a aquest contingut"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"CSAT": {
|
||||
"TITLE": "Rate your conversation",
|
||||
"PLACEHOLDER": "Tell us more...",
|
||||
"TITLE": "Valora la teva conversa",
|
||||
"PLACEHOLDER": "Explica'ns més...",
|
||||
"RATINGS": {
|
||||
"POOR": "😞 Poor",
|
||||
"FAIR": "😑 Fair",
|
||||
"AVERAGE": "😐 Average",
|
||||
"GOOD": "😀 Good",
|
||||
"EXCELLENT": "😍 Excellent"
|
||||
"POOR": "😞 Pobre",
|
||||
"FAIR": "😑 Just",
|
||||
"AVERAGE": "😐 Mitjana",
|
||||
"GOOD": "😀 Bé",
|
||||
"EXCELLENT": "😍 Excel·lent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user