Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4caa9b1539 | ||
|
|
8ee2419ea5 | ||
|
|
9bcc3c25e3 | ||
|
|
106352cdce | ||
|
|
e74a0e5684 | ||
|
|
de6ab10714 |
@@ -25,5 +25,13 @@ jobs:
|
||||
with:
|
||||
issue-inactive-days: '30'
|
||||
issue-lock-reason: 'resolved'
|
||||
issue-comment: >
|
||||
This issue has been automatically locked since there
|
||||
has not been any recent activity after it was closed.
|
||||
Please open a new issue for related bugs.
|
||||
pr-inactive-days: '30'
|
||||
pr-lock-reason: 'resolved'
|
||||
pr-comment: >
|
||||
This pull request has been automatically locked since there
|
||||
has not been any recent activity after it was closed.
|
||||
Please open a new issue for related bugs.
|
||||
|
||||
@@ -111,12 +111,12 @@ 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.19.0', require: false
|
||||
gem 'sentry-rails', '>= 5.18.2', require: false
|
||||
gem 'sentry-ruby', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.19.0', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.18.2', require: false
|
||||
|
||||
##-- background job processing --##
|
||||
gem 'sidekiq', '>= 7.3.1'
|
||||
gem 'sidekiq', '>= 7.3.0'
|
||||
# We want cron jobs
|
||||
gem 'sidekiq-cron', '>= 1.12.0'
|
||||
|
||||
@@ -228,7 +228,7 @@ group :development, :test do
|
||||
gem 'mock_redis'
|
||||
gem 'pry-rails'
|
||||
gem 'rspec_junit_formatter'
|
||||
gem 'rspec-rails', '>= 6.1.4'
|
||||
gem 'rspec-rails', '>= 6.1.3'
|
||||
gem 'rubocop', require: false
|
||||
gem 'rubocop-performance', require: false
|
||||
gem 'rubocop-rails', require: false
|
||||
|
||||
+11
-11
@@ -644,7 +644,7 @@ GEM
|
||||
rspec-mocks (3.13.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (6.1.4)
|
||||
rspec-rails (6.1.3)
|
||||
actionpack (>= 6.1)
|
||||
activesupport (>= 6.1)
|
||||
railties (>= 6.1)
|
||||
@@ -710,19 +710,19 @@ GEM
|
||||
activesupport (>= 4)
|
||||
selectize-rails (0.12.6)
|
||||
semantic_range (3.0.0)
|
||||
sentry-rails (5.19.0)
|
||||
sentry-rails (5.18.2)
|
||||
railties (>= 5.0)
|
||||
sentry-ruby (~> 5.19.0)
|
||||
sentry-ruby (5.19.0)
|
||||
sentry-ruby (~> 5.18.2)
|
||||
sentry-ruby (5.18.2)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
sentry-sidekiq (5.19.0)
|
||||
sentry-ruby (~> 5.19.0)
|
||||
sentry-sidekiq (5.18.2)
|
||||
sentry-ruby (~> 5.18.2)
|
||||
sidekiq (>= 3.0)
|
||||
sexp_processor (4.17.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (7.3.1)
|
||||
sidekiq (7.3.0)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
logger
|
||||
@@ -930,7 +930,7 @@ DEPENDENCIES
|
||||
responders (>= 3.1.1)
|
||||
rest-client
|
||||
reverse_markdown
|
||||
rspec-rails (>= 6.1.4)
|
||||
rspec-rails (>= 6.1.3)
|
||||
rspec_junit_formatter
|
||||
rubocop
|
||||
rubocop-performance
|
||||
@@ -939,11 +939,11 @@ DEPENDENCIES
|
||||
scout_apm
|
||||
scss_lint
|
||||
seed_dump
|
||||
sentry-rails (>= 5.19.0)
|
||||
sentry-rails (>= 5.18.2)
|
||||
sentry-ruby
|
||||
sentry-sidekiq (>= 5.19.0)
|
||||
sentry-sidekiq (>= 5.18.2)
|
||||
shoulda-matchers
|
||||
sidekiq (>= 7.3.1)
|
||||
sidekiq (>= 7.3.0)
|
||||
sidekiq-cron (>= 1.12.0)
|
||||
simplecov (= 0.17.1)
|
||||
slack-ruby-client (~> 2.2.0)
|
||||
|
||||
@@ -10,6 +10,7 @@ import PaymentPendingBanner from './components/app/PaymentPendingBanner.vue';
|
||||
import PendingEmailVerificationBanner from './components/app/PendingEmailVerificationBanner.vue';
|
||||
import vueActionCable from './helper/actionCable';
|
||||
import WootSnackbarBox from './components/SnackbarContainer.vue';
|
||||
import rtlMixin from 'shared/mixins/rtlMixin';
|
||||
import { setColorTheme } from './helper/themeHelper';
|
||||
import { isOnOnboardingView } from 'v3/helpers/RouteHelper';
|
||||
import {
|
||||
@@ -31,6 +32,9 @@ export default {
|
||||
UpgradeBanner,
|
||||
PendingEmailVerificationBanner,
|
||||
},
|
||||
|
||||
mixins: [rtlMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
showAddAccountModal: false,
|
||||
@@ -42,7 +46,6 @@ export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
getAccount: 'accounts/getAccount',
|
||||
isRTL: 'accounts/isRTL',
|
||||
currentUser: 'getCurrentUser',
|
||||
authUIFlags: 'getAuthUIFlags',
|
||||
accountUIFlags: 'accounts/getUIFlags',
|
||||
@@ -99,6 +102,7 @@ export default {
|
||||
this.getAccount(this.currentAccountId);
|
||||
const { pubsub_token: pubsubToken } = this.currentUser || {};
|
||||
this.setLocale(locale);
|
||||
this.updateRTLDirectionView(locale);
|
||||
this.latestChatwootVersion = latestChatwootVersion;
|
||||
vueActionCable.init(pubsubToken);
|
||||
this.reconnectService = new ReconnectService(this.$store, router);
|
||||
@@ -120,8 +124,8 @@ export default {
|
||||
v-if="!authUIFlags.isFetching && !accountUIFlags.isFetchingItem"
|
||||
id="app"
|
||||
class="flex-grow-0 w-full h-full min-h-0 app-wrapper"
|
||||
:class="{ 'app-rtl--wrapper': isRTL }"
|
||||
:dir="isRTL ? 'rtl' : 'ltr'"
|
||||
:class="{ 'app-rtl--wrapper': isRTLView }"
|
||||
:dir="isRTLView ? 'rtl' : 'ltr'"
|
||||
>
|
||||
<UpdateBanner :latest-chatwoot-version="latestChatwootVersion" />
|
||||
<template v-if="currentAccountId">
|
||||
|
||||
@@ -10,6 +10,7 @@ import ChatListHeader from './ChatListHeader.vue';
|
||||
import ConversationAdvancedFilter from './widgets/conversation/ConversationAdvancedFilter.vue';
|
||||
import ChatTypeTabs from './widgets/ChatTypeTabs.vue';
|
||||
import ConversationItem from './ConversationItem.vue';
|
||||
import conversationMixin from '../mixins/conversations';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import advancedFilterTypes from './widgets/conversation/advancedFilterItems';
|
||||
import filterQueryGenerator from '../helper/filterQueryGenerator.js';
|
||||
@@ -41,7 +42,7 @@ export default {
|
||||
IntersectionObserver,
|
||||
VirtualList,
|
||||
},
|
||||
mixins: [filterMixin],
|
||||
mixins: [conversationMixin, filterMixin],
|
||||
provide() {
|
||||
return {
|
||||
// Actions to be performed on virtual list item and context menu.
|
||||
@@ -905,6 +906,7 @@ export default {
|
||||
v-if="!hasAppliedFiltersOrActiveFolders"
|
||||
:items="assigneeTabItems"
|
||||
:active-tab="activeAssigneeTab"
|
||||
class="tab--chat-type"
|
||||
@chatTabChange="updateAssigneeTab"
|
||||
/>
|
||||
|
||||
@@ -992,4 +994,14 @@ export default {
|
||||
.conversations-list {
|
||||
@apply overflow-hidden hover:overflow-y-auto;
|
||||
}
|
||||
|
||||
.tab--chat-type {
|
||||
@apply py-0 px-4;
|
||||
|
||||
::v-deep {
|
||||
.tabs {
|
||||
@apply p-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { useAccount } from 'dashboard/composables/useAccount';
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
|
||||
const EMPTY_SUBSCRIPTION_INFO = {
|
||||
status: null,
|
||||
@@ -11,13 +11,10 @@ const EMPTY_SUBSCRIPTION_INFO = {
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [accountMixin],
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
|
||||
const { accountId } = useAccount();
|
||||
|
||||
return {
|
||||
accountId,
|
||||
isAdmin,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<script>
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
mixins: [accountMixin],
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'getCurrentUser',
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
<script>
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAccount } from 'dashboard/composables/useAccount';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
|
||||
export default {
|
||||
components: { Banner },
|
||||
setup() {
|
||||
const { accountId } = useAccount();
|
||||
return {
|
||||
accountId,
|
||||
};
|
||||
},
|
||||
mixins: [accountMixin],
|
||||
data() {
|
||||
return { conversationMeta: {} };
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { useConfig } from 'dashboard/composables/useConfig';
|
||||
import configMixin from 'shared/mixins/configMixin';
|
||||
import {
|
||||
getInboxClassByType,
|
||||
getInboxWarningIconClass,
|
||||
@@ -16,6 +16,7 @@ import Policy from '../../policy.vue';
|
||||
|
||||
export default {
|
||||
components: { SecondaryChildNavItem, Policy },
|
||||
mixins: [configMixin],
|
||||
props: {
|
||||
menuItem: {
|
||||
type: Object,
|
||||
@@ -24,10 +25,8 @@ export default {
|
||||
},
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
const { isEnterprise } = useConfig();
|
||||
return {
|
||||
isAdmin,
|
||||
isEnterprise,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -44,11 +44,7 @@ useKeyboardEvents(keyboardEvents, chatTypeTabsRef);
|
||||
|
||||
<template>
|
||||
<div ref="chatTypeTabsRef">
|
||||
<woot-tabs
|
||||
:index="activeTabIndex"
|
||||
class="tab--chat-type py-0 px-4 w-full"
|
||||
@change="onTabChange"
|
||||
>
|
||||
<woot-tabs :index="activeTabIndex" @change="onTabChange">
|
||||
<woot-tabs-item
|
||||
v-for="item in items"
|
||||
:key="item.key"
|
||||
@@ -58,13 +54,3 @@ useKeyboardEvents(keyboardEvents, chatTypeTabsRef);
|
||||
</woot-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tab--chat-type {
|
||||
::v-deep {
|
||||
.tabs {
|
||||
@apply p-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -116,27 +116,29 @@ export default {
|
||||
setup() {
|
||||
const { setSignatureFlagForInbox, fetchSignatureFlagFromUISettings } =
|
||||
useUISettings();
|
||||
|
||||
const uploadRef = ref(null);
|
||||
// TODO: This is really hacky, we need to replace the file picker component with
|
||||
// a custom one, where the logic and the component markup is isolated.
|
||||
// Once we have the custom component, we can remove the hacky logic below.
|
||||
const uploadRefElem = computed(() => uploadRef.value?.$el);
|
||||
const uploadTriggerButton = computed(() => {
|
||||
if (uploadRef.value) {
|
||||
return uploadRef.value.$children[1].$el;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const keyboardEvents = {
|
||||
'Alt+KeyA': {
|
||||
action: () => {
|
||||
const uploadTriggerButton = document.querySelector(
|
||||
'#conversationAttachment'
|
||||
);
|
||||
uploadTriggerButton.click();
|
||||
uploadTriggerButton.value.click();
|
||||
},
|
||||
allowOnFocusedInput: true,
|
||||
},
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
useKeyboardEvents(keyboardEvents, uploadRefElem);
|
||||
useKeyboardEvents(keyboardEvents, uploadTriggerButton);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getLastMessage } from 'dashboard/helper/conversationHelper';
|
||||
import Thumbnail from '../Thumbnail.vue';
|
||||
import MessagePreview from './MessagePreview.vue';
|
||||
import conversationMixin from '../../../mixins/conversations';
|
||||
import router from '../../../routes';
|
||||
import { frontendURL, conversationUrl } from '../../../helper/URLHelper';
|
||||
import InboxName from '../InboxName.vue';
|
||||
@@ -24,7 +24,7 @@ export default {
|
||||
PriorityMark,
|
||||
SLACardLabel,
|
||||
},
|
||||
mixins: [inboxMixin],
|
||||
mixins: [inboxMixin, conversationMixin],
|
||||
props: {
|
||||
activeLabel: {
|
||||
type: String,
|
||||
@@ -118,7 +118,7 @@ export default {
|
||||
},
|
||||
|
||||
lastMessageInChat() {
|
||||
return getLastMessage(this.chat);
|
||||
return this.lastMessage(this.chat);
|
||||
},
|
||||
|
||||
inbox() {
|
||||
@@ -316,11 +316,7 @@ export default {
|
||||
{{ unreadCount > 9 ? '9+' : unreadCount }}
|
||||
</span>
|
||||
</div>
|
||||
<CardLabels
|
||||
:conversation-id="chat.id"
|
||||
:conversation-labels="chat.labels"
|
||||
class="mt-0.5 mx-2 mb-0"
|
||||
>
|
||||
<CardLabels :conversation-id="chat.id" class="mt-0.5 mx-2 mb-0">
|
||||
<template v-if="hasSlaPolicyId" #before>
|
||||
<SLACardLabel :chat="chat" class="ltr:mr-1 rtl:ml-1" />
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAdmin } from 'dashboard/composables/useAdmin';
|
||||
import { useAccount } from 'dashboard/composables/useAccount';
|
||||
import accountMixin from 'dashboard/mixins/account';
|
||||
import OnboardingView from '../OnboardingView.vue';
|
||||
import EmptyStateMessage from './EmptyStateMessage.vue';
|
||||
|
||||
@@ -10,6 +10,7 @@ export default {
|
||||
OnboardingView,
|
||||
EmptyStateMessage,
|
||||
},
|
||||
mixins: [accountMixin],
|
||||
props: {
|
||||
isOnExpandedLayout: {
|
||||
type: Boolean,
|
||||
@@ -18,12 +19,8 @@ export default {
|
||||
},
|
||||
setup() {
|
||||
const { isAdmin } = useAdmin();
|
||||
|
||||
const { accountScopedUrl } = useAccount();
|
||||
|
||||
return {
|
||||
isAdmin,
|
||||
accountScopedUrl,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -47,7 +44,7 @@ export default {
|
||||
return this.$t('CONVERSATION.404');
|
||||
},
|
||||
newInboxURL() {
|
||||
return this.accountScopedUrl('settings/inboxes/new');
|
||||
return this.addAccountScoping('settings/inboxes/new');
|
||||
},
|
||||
emptyClassName() {
|
||||
if (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
// composable
|
||||
import { useConfig } from 'dashboard/composables/useConfig';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
|
||||
// components
|
||||
@@ -14,18 +13,17 @@ import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
// mixins
|
||||
import conversationMixin, {
|
||||
filterDuplicateSourceMessages,
|
||||
} from '../../../mixins/conversations';
|
||||
import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin';
|
||||
import configMixin from 'shared/mixins/configMixin';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
|
||||
// utils
|
||||
import { getTypingUsersText } from '../../../helper/commons';
|
||||
import { calculateScrollTop } from './helpers/scrollTopCalculationHelper';
|
||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||
import {
|
||||
filterDuplicateSourceMessages,
|
||||
getReadMessages,
|
||||
getUnreadMessages,
|
||||
} from 'dashboard/helper/conversationHelper';
|
||||
|
||||
// constants
|
||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||
@@ -40,7 +38,7 @@ export default {
|
||||
Banner,
|
||||
ConversationLabelSuggestion,
|
||||
},
|
||||
mixins: [inboxMixin, aiMixin],
|
||||
mixins: [conversationMixin, inboxMixin, configMixin, aiMixin],
|
||||
props: {
|
||||
isContactPanelOpen: {
|
||||
type: Boolean,
|
||||
@@ -54,7 +52,6 @@ export default {
|
||||
setup() {
|
||||
const conversationFooterRef = ref(null);
|
||||
const isPopOutReplyBox = ref(false);
|
||||
const { isEnterprise } = useConfig();
|
||||
|
||||
const closePopOutReplyBox = () => {
|
||||
isPopOutReplyBox.value = false;
|
||||
@@ -73,7 +70,6 @@ export default {
|
||||
useKeyboardEvents(keyboardEvents, conversationFooterRef);
|
||||
|
||||
return {
|
||||
isEnterprise,
|
||||
conversationFooterRef,
|
||||
isPopOutReplyBox,
|
||||
closePopOutReplyBox,
|
||||
@@ -142,14 +138,14 @@ export default {
|
||||
}
|
||||
return messages;
|
||||
},
|
||||
readMessages() {
|
||||
return getReadMessages(
|
||||
getReadMessages() {
|
||||
return this.readMessages(
|
||||
this.getMessages,
|
||||
this.currentChat.agent_last_seen_at
|
||||
);
|
||||
},
|
||||
unReadMessages() {
|
||||
return getUnreadMessages(
|
||||
getUnReadMessages() {
|
||||
return this.unReadMessages(
|
||||
this.getMessages,
|
||||
this.currentChat.agent_last_seen_at
|
||||
);
|
||||
@@ -472,7 +468,7 @@ export default {
|
||||
</li>
|
||||
</transition>
|
||||
<Message
|
||||
v-for="message in readMessages"
|
||||
v-for="message in getReadMessages"
|
||||
:key="message.id"
|
||||
class="message--read ph-no-capture"
|
||||
data-clarity-mask="True"
|
||||
@@ -497,7 +493,7 @@ export default {
|
||||
</span>
|
||||
</li>
|
||||
<Message
|
||||
v-for="message in unReadMessages"
|
||||
v-for="message in getUnReadMessages"
|
||||
:key="message.id"
|
||||
class="message--unread ph-no-capture"
|
||||
data-clarity-mask="True"
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
imageSrc: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
imageAlt: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
to: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
linkText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="h-full w-full bg-white dark:bg-slate-900 border border-slate-100 dark:border-white/10 rounded-lg p-4 flex flex-col"
|
||||
>
|
||||
<img :src="imageSrc" :alt="imageAlt" class="h-36 w-auto mx-auto" />
|
||||
<div class="mt-auto">
|
||||
<p
|
||||
class="text-base text-slate-800 dark:text-slate-100 font-interDisplay font-semibold tracking-[0.3px]"
|
||||
>
|
||||
{{ title }}
|
||||
</p>
|
||||
<p class="text-slate-600 dark:text-slate-400 text-sm">
|
||||
{{ description }}
|
||||
</p>
|
||||
<router-link
|
||||
v-if="to"
|
||||
:to="{ name: to }"
|
||||
class="no-underline text-woot-500 text-sm font-medium"
|
||||
>
|
||||
<span>{{ linkText }}</span>
|
||||
<span>{{ `→` }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,80 +1,159 @@
|
||||
<script setup>
|
||||
import OnboardingFeatureCard from './OnboardingFeatureCard.vue';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'dashboard/composables/useI18n';
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import accountMixin from '../../../mixins/account';
|
||||
|
||||
const getters = useStoreGetters();
|
||||
const { t } = useI18n();
|
||||
const globalConfig = computed(() => getters['globalConfig/get'].value);
|
||||
const currentUser = computed(() => getters.getCurrentUser.value);
|
||||
|
||||
const greetingMessage = computed(() => {
|
||||
const hours = new Date().getHours();
|
||||
let translationKey;
|
||||
if (hours < 12) {
|
||||
translationKey = 'ONBOARDING.GREETING_MORNING';
|
||||
} else if (hours < 18) {
|
||||
translationKey = 'ONBOARDING.GREETING_AFTERNOON';
|
||||
} else {
|
||||
translationKey = 'ONBOARDING.GREETING_EVENING';
|
||||
}
|
||||
return t(translationKey, {
|
||||
name: currentUser.value.name,
|
||||
installationName: globalConfig.value.installationName,
|
||||
});
|
||||
});
|
||||
export default {
|
||||
mixins: [accountMixin],
|
||||
computed: {
|
||||
...mapGetters({ globalConfig: 'globalConfig/get' }),
|
||||
newInboxURL() {
|
||||
return this.addAccountScoping('settings/inboxes/new');
|
||||
},
|
||||
newAgentURL() {
|
||||
return this.addAccountScoping('settings/agents/list');
|
||||
},
|
||||
newLabelsURL() {
|
||||
return this.addAccountScoping('settings/labels/list');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="min-h-screen max-w-4xl mx-auto grid grid-cols-1 xl:grid-cols-2 grid-rows-[auto_1fr_1fr] gap-4 p-8 w-full font-inter overflow-auto"
|
||||
>
|
||||
<div class="col-span-full self-start">
|
||||
<p
|
||||
class="text-xl font-semibold text-slate-900 dark:text-white font-interDisplay tracking-[0.3px]"
|
||||
>
|
||||
{{ greetingMessage }}
|
||||
</p>
|
||||
<p class="text-slate-600 dark:text-slate-400 max-w-2xl text-base">
|
||||
{{
|
||||
$t('ONBOARDING.DESCRIPTION', {
|
||||
installationName: globalConfig.installationName,
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
<div class="onboarding-wrap">
|
||||
<div class="onboarding">
|
||||
<div class="scroll-wrap">
|
||||
<div class="features-item">
|
||||
<h1 class="text-2xl text-slate-900 dark:text-slate-50">
|
||||
<span>{{
|
||||
$t('ONBOARDING.TITLE', {
|
||||
installationName: globalConfig.installationName,
|
||||
})
|
||||
}}</span>
|
||||
</h1>
|
||||
<p class="intro-body">
|
||||
{{
|
||||
$t('ONBOARDING.DESCRIPTION', {
|
||||
installationName: globalConfig.installationName,
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
<p v-if="globalConfig.installationName === 'Chatwoot'">
|
||||
<a
|
||||
href="https://www.chatwoot.com/changelog"
|
||||
target="_blank"
|
||||
rel="noopener nofollow noreferrer"
|
||||
class="onboarding--link"
|
||||
>
|
||||
{{ $t('ONBOARDING.READ_LATEST_UPDATES') }}
|
||||
</a>
|
||||
<span>🎉</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="features-item">
|
||||
<h2 class="text-lg text-black-900 dark:text-slate-200">
|
||||
<span class="emoji">💬</span>
|
||||
<span class="conversation--title">{{
|
||||
$t('ONBOARDING.ALL_CONVERSATION.TITLE')
|
||||
}}</span>
|
||||
</h2>
|
||||
<p class="intro-body">
|
||||
{{ $t('ONBOARDING.ALL_CONVERSATION.DESCRIPTION') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="features-item">
|
||||
<h2 class="text-lg text-black-900 dark:text-slate-200">
|
||||
<span class="emoji">👥</span>
|
||||
{{ $t('ONBOARDING.TEAM_MEMBERS.TITLE') }}
|
||||
</h2>
|
||||
<p class="intro-body">
|
||||
{{ $t('ONBOARDING.TEAM_MEMBERS.DESCRIPTION') }}
|
||||
</p>
|
||||
<router-link :to="newAgentURL" class="onboarding--link">
|
||||
{{ $t('ONBOARDING.TEAM_MEMBERS.NEW_LINK') }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="features-item">
|
||||
<h2 class="text-lg text-black-900 dark:text-slate-200">
|
||||
<span class="emoji">📥</span>{{ $t('ONBOARDING.INBOXES.TITLE') }}
|
||||
</h2>
|
||||
<p class="intro-body">
|
||||
{{ $t('ONBOARDING.INBOXES.DESCRIPTION') }}
|
||||
</p>
|
||||
<router-link :to="newInboxURL" class="onboarding--link">
|
||||
{{ $t('ONBOARDING.INBOXES.NEW_LINK') }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="features-item">
|
||||
<h2 class="text-lg text-black-900 dark:text-slate-200">
|
||||
<span class="emoji">🔖</span>{{ $t('ONBOARDING.LABELS.TITLE') }}
|
||||
</h2>
|
||||
<p class="intro-body">
|
||||
{{ $t('ONBOARDING.LABELS.DESCRIPTION') }}
|
||||
</p>
|
||||
<router-link :to="newLabelsURL" class="onboarding--link">
|
||||
{{ $t('ONBOARDING.LABELS.NEW_LINK') }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<OnboardingFeatureCard
|
||||
image-src="/dashboard/images/onboarding/omnichannel-inbox.png"
|
||||
image-alt="Omnichannel"
|
||||
to="settings_inbox_new"
|
||||
:title="$t('ONBOARDING.ALL_CONVERSATION.TITLE')"
|
||||
:description="$t('ONBOARDING.ALL_CONVERSATION.DESCRIPTION')"
|
||||
:link-text="$t('ONBOARDING.ALL_CONVERSATION.NEW_LINK')"
|
||||
/>
|
||||
<OnboardingFeatureCard
|
||||
image-src="/dashboard/images/onboarding/teams.png"
|
||||
image-alt="Teams"
|
||||
to="settings_teams_new"
|
||||
:title="$t('ONBOARDING.TEAM_MEMBERS.TITLE')"
|
||||
:description="$t('ONBOARDING.TEAM_MEMBERS.DESCRIPTION')"
|
||||
:link-text="$t('ONBOARDING.TEAM_MEMBERS.NEW_LINK')"
|
||||
/>
|
||||
<OnboardingFeatureCard
|
||||
image-src="/dashboard/images/onboarding/canned-responses.png"
|
||||
image-alt="Canned responses"
|
||||
to="canned_list"
|
||||
:title="$t('ONBOARDING.CANNED_RESPONSES.TITLE')"
|
||||
:description="$t('ONBOARDING.CANNED_RESPONSES.DESCRIPTION')"
|
||||
:link-text="$t('ONBOARDING.CANNED_RESPONSES.NEW_LINK')"
|
||||
/>
|
||||
<OnboardingFeatureCard
|
||||
image-src="/dashboard/images/onboarding/labels.png"
|
||||
image-alt="Labels"
|
||||
to="labels_list"
|
||||
:title="$t('ONBOARDING.LABELS.TITLE')"
|
||||
:description="$t('ONBOARDING.LABELS.DESCRIPTION')"
|
||||
:link-text="$t('ONBOARDING.LABELS.NEW_LINK')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.onboarding-wrap {
|
||||
display: flex;
|
||||
font-size: var(--font-size-small);
|
||||
justify-content: center;
|
||||
overflow: auto;
|
||||
text-align: left;
|
||||
}
|
||||
.onboarding {
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.scroll-wrap {
|
||||
padding: var(--space-larger) 8.5rem;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.features-item {
|
||||
margin-bottom: var(--space-large);
|
||||
}
|
||||
|
||||
.conversation--title {
|
||||
margin-left: var(--space-minus-smaller);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: var(--font-size-big);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-bottom: var(--space-one);
|
||||
}
|
||||
|
||||
.block-title {
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-bottom: var(--space-smaller);
|
||||
margin-left: var(--space-minus-large);
|
||||
}
|
||||
|
||||
.intro-body {
|
||||
margin-bottom: var(--space-small);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.onboarding--link {
|
||||
color: var(--w-500);
|
||||
font-weight: var(--font-weight-medium);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
width: var(--space-large);
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -31,6 +31,7 @@ import inboxMixin, { INBOX_FEATURES } from 'shared/mixins/inboxMixin';
|
||||
import { trimContent, debounce } from '@chatwoot/utils';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
import rtlMixin from 'shared/mixins/rtlMixin';
|
||||
import fileUploadMixin from 'dashboard/mixins/fileUploadMixin';
|
||||
import {
|
||||
appendSignature,
|
||||
@@ -64,6 +65,7 @@ export default {
|
||||
mixins: [
|
||||
inboxMixin,
|
||||
messageFormatterMixin,
|
||||
rtlMixin,
|
||||
fileUploadMixin,
|
||||
keyboardEventListenerMixins,
|
||||
],
|
||||
@@ -119,7 +121,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isRTL: 'accounts/isRTL',
|
||||
currentChat: 'getSelectedChat',
|
||||
messageSignature: 'getMessageSignature',
|
||||
currentUser: 'getCurrentUser',
|
||||
@@ -306,7 +307,7 @@ export default {
|
||||
if (this.isOnExpandedLayout || this.popoutReplyBox) {
|
||||
return 'emoji-dialog--expanded';
|
||||
}
|
||||
if (this.isRTL) {
|
||||
if (this.isRTLView) {
|
||||
return 'emoji-dialog--rtl';
|
||||
}
|
||||
return '';
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
import { hasPressedCommand } from 'shared/helpers/KeyboardHelpers';
|
||||
import GalleryView from '../components/GalleryView.vue';
|
||||
import { timeStampAppendedURL } from 'dashboard/helper/URLHelper';
|
||||
|
||||
const ALLOWED_FILE_TYPES = {
|
||||
IMAGE: 'image',
|
||||
@@ -43,9 +42,6 @@ export default {
|
||||
isAudio() {
|
||||
return this.attachment.file_type === ALLOWED_FILE_TYPES.AUDIO;
|
||||
},
|
||||
timeStampURL() {
|
||||
return timeStampAppendedURL(this.dataUrl);
|
||||
},
|
||||
attachmentTypeClasses() {
|
||||
return {
|
||||
image: this.isImage,
|
||||
@@ -112,7 +108,7 @@ export default {
|
||||
@click="onClick"
|
||||
/>
|
||||
<audio v-else-if="isAudio" controls class="skip-context-menu mb-0.5">
|
||||
<source :src="timeStampURL" />
|
||||
<source :src="`${dataUrl}?t=${Date.now()}`" />
|
||||
</audio>
|
||||
<GalleryView
|
||||
v-if="show"
|
||||
|
||||
+16
-19
@@ -1,26 +1,23 @@
|
||||
<script>
|
||||
import { computed } from 'vue';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
|
||||
import conversationLabelMixin from 'dashboard/mixins/conversation/labelMixin';
|
||||
export default {
|
||||
mixins: [conversationLabelMixin],
|
||||
props: {
|
||||
conversationLabels: {
|
||||
type: Array,
|
||||
// conversationId prop is used in /conversation/labelMixin,
|
||||
// remove this props when refactoring to composable if not needed
|
||||
// eslint-disable-next-line vue/no-unused-properties
|
||||
conversationId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const accountLabels = useMapGetter('labels/getLabels');
|
||||
|
||||
const activeLabels = computed(() => {
|
||||
return accountLabels.value.filter(({ title }) =>
|
||||
props.conversationLabels.includes(title)
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
activeLabels,
|
||||
};
|
||||
// conversationLabels prop is used in /conversation/labelMixin,
|
||||
// remove this props when refactoring to composable if not needed
|
||||
// eslint-disable-next-line vue/no-unused-properties
|
||||
conversationLabels: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -83,7 +80,7 @@ export default {
|
||||
<slot name="before" />
|
||||
<woot-label
|
||||
v-for="(label, index) in activeLabels"
|
||||
:key="label ? label.id : index"
|
||||
:key="label.id"
|
||||
:title="label.title"
|
||||
:description="label.description"
|
||||
:color="label.color"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { ref } from 'vue';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { useAccount } from '../useAccount';
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
vi.mock('dashboard/composables/store');
|
||||
|
||||
describe('useAccount', () => {
|
||||
beforeEach(() => {
|
||||
useStoreGetters.mockReturnValue({
|
||||
getCurrentAccountId: ref(123),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns accountId as a computed property', () => {
|
||||
const { accountId } = useAccount();
|
||||
expect(accountId.value).toBe(123);
|
||||
});
|
||||
|
||||
it('generates account-scoped URLs correctly', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const result = accountScopedUrl('settings/inbox/new');
|
||||
expect(result).toBe('/app/accounts/123/settings/inbox/new');
|
||||
});
|
||||
|
||||
it('handles URLs with leading slash', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const result = accountScopedUrl('users');
|
||||
expect(result).toBe('/app/accounts/123/users');
|
||||
});
|
||||
|
||||
it('handles empty URL', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const result = accountScopedUrl('');
|
||||
expect(result).toBe('/app/accounts/123/');
|
||||
});
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
import { useConfig } from '../useConfig';
|
||||
|
||||
describe('useConfig', () => {
|
||||
const originalChatwootConfig = window.chatwootConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
window.chatwootConfig = {
|
||||
hostURL: 'https://example.com',
|
||||
vapidPublicKey: 'vapid-key',
|
||||
enabledLanguages: ['en', 'fr'],
|
||||
isEnterprise: 'true',
|
||||
enterprisePlanName: 'enterprise',
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.chatwootConfig = originalChatwootConfig;
|
||||
});
|
||||
|
||||
it('returns the correct configuration values', () => {
|
||||
const config = useConfig();
|
||||
|
||||
expect(config.hostURL).toBe('https://example.com');
|
||||
expect(config.vapidPublicKey).toBe('vapid-key');
|
||||
expect(config.enabledLanguages).toEqual(['en', 'fr']);
|
||||
expect(config.isEnterprise).toBe(true);
|
||||
expect(config.enterprisePlanName).toBe('enterprise');
|
||||
});
|
||||
|
||||
it('handles missing configuration values', () => {
|
||||
window.chatwootConfig = {};
|
||||
const config = useConfig();
|
||||
|
||||
expect(config.hostURL).toBeUndefined();
|
||||
expect(config.vapidPublicKey).toBeUndefined();
|
||||
expect(config.enabledLanguages).toBeUndefined();
|
||||
expect(config.isEnterprise).toBe(false);
|
||||
expect(config.enterprisePlanName).toBeUndefined();
|
||||
});
|
||||
|
||||
it('handles undefined window.chatwootConfig', () => {
|
||||
window.chatwootConfig = undefined;
|
||||
const config = useConfig();
|
||||
|
||||
expect(config.hostURL).toBeUndefined();
|
||||
expect(config.vapidPublicKey).toBeUndefined();
|
||||
expect(config.enabledLanguages).toBeUndefined();
|
||||
expect(config.isEnterprise).toBe(false);
|
||||
expect(config.enterprisePlanName).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -1,87 +0,0 @@
|
||||
import { useConversationLabels } from '../useConversationLabels';
|
||||
import { useStore, useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
vi.mock('dashboard/composables/store');
|
||||
|
||||
describe('useConversationLabels', () => {
|
||||
let store;
|
||||
let getters;
|
||||
|
||||
beforeEach(() => {
|
||||
store = {
|
||||
getters: {
|
||||
'conversationLabels/getConversationLabels': vi.fn(),
|
||||
},
|
||||
dispatch: vi.fn(),
|
||||
};
|
||||
getters = {
|
||||
getSelectedChat: { value: { id: 1 } },
|
||||
'labels/getLabels': {
|
||||
value: [
|
||||
{ id: 1, title: 'Label 1' },
|
||||
{ id: 2, title: 'Label 2' },
|
||||
{ id: 3, title: 'Label 3' },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
useStore.mockReturnValue(store);
|
||||
useStoreGetters.mockReturnValue(getters);
|
||||
});
|
||||
|
||||
it('should return the correct computed properties', () => {
|
||||
store.getters['conversationLabels/getConversationLabels'].mockReturnValue([
|
||||
'Label 1',
|
||||
'Label 2',
|
||||
]);
|
||||
const { accountLabels, savedLabels, activeLabels, inactiveLabels } =
|
||||
useConversationLabels();
|
||||
|
||||
expect(accountLabels.value).toEqual(getters['labels/getLabels'].value);
|
||||
expect(savedLabels.value).toEqual(['Label 1', 'Label 2']);
|
||||
expect(activeLabels.value).toEqual([
|
||||
{ id: 1, title: 'Label 1' },
|
||||
{ id: 2, title: 'Label 2' },
|
||||
]);
|
||||
expect(inactiveLabels.value).toEqual([{ id: 3, title: 'Label 3' }]);
|
||||
});
|
||||
|
||||
it('should update labels correctly', async () => {
|
||||
const { onUpdateLabels } = useConversationLabels();
|
||||
await onUpdateLabels(['Label 1', 'Label 3']);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('conversationLabels/update', {
|
||||
conversationId: 1,
|
||||
labels: ['Label 1', 'Label 3'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a label to the conversation', () => {
|
||||
store.getters['conversationLabels/getConversationLabels'].mockReturnValue([
|
||||
'Label 1',
|
||||
]);
|
||||
const { addLabelToConversation } = useConversationLabels();
|
||||
|
||||
addLabelToConversation({ title: 'Label 2' });
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('conversationLabels/update', {
|
||||
conversationId: 1,
|
||||
labels: ['Label 1', 'Label 2'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove a label from the conversation', () => {
|
||||
store.getters['conversationLabels/getConversationLabels'].mockReturnValue([
|
||||
'Label 1',
|
||||
'Label 2',
|
||||
]);
|
||||
const { removeLabelFromConversation } = useConversationLabels();
|
||||
|
||||
removeLabelFromConversation('Label 2');
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('conversationLabels/update', {
|
||||
conversationId: 1,
|
||||
labels: ['Label 1'],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,7 @@ export const useStoreGetters = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const useMapGetter = key => {
|
||||
export const mapGetter = key => {
|
||||
const store = useStore();
|
||||
return computed(() => store.getters[key]);
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { computed } from 'vue';
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
/**
|
||||
* Composable for account-related operations.
|
||||
* @returns {Object} An object containing account-related properties and methods.
|
||||
*/
|
||||
export function useAccount() {
|
||||
const getters = useStoreGetters();
|
||||
|
||||
/**
|
||||
* Computed property for the current account ID.
|
||||
* @type {import('vue').ComputedRef<number>}
|
||||
*/
|
||||
const accountId = computed(() => getters.getCurrentAccountId.value);
|
||||
|
||||
/**
|
||||
* Generates an account-scoped URL.
|
||||
* @param {string} url - The URL to be scoped to the account.
|
||||
* @returns {string} The account-scoped URL.
|
||||
*/
|
||||
const accountScopedUrl = url => {
|
||||
return `/app/accounts/${accountId.value}/${url}`;
|
||||
};
|
||||
|
||||
return {
|
||||
accountId,
|
||||
accountScopedUrl,
|
||||
};
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* A function that provides access to various configuration values.
|
||||
* @returns {Object} An object containing configuration values.
|
||||
*/
|
||||
export function useConfig() {
|
||||
const config = window.chatwootConfig || {};
|
||||
|
||||
/**
|
||||
* The host URL of the Chatwoot instance.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
const hostURL = config.hostURL;
|
||||
|
||||
/**
|
||||
* The VAPID public key for web push notifications.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
const vapidPublicKey = config.vapidPublicKey;
|
||||
|
||||
/**
|
||||
* An array of enabled languages in the Chatwoot instance.
|
||||
* @type {string[]|undefined}
|
||||
*/
|
||||
const enabledLanguages = config.enabledLanguages;
|
||||
|
||||
/**
|
||||
* Indicates whether the current instance is an enterprise version.
|
||||
* @type {boolean}
|
||||
*/
|
||||
const isEnterprise = config.isEnterprise === 'true';
|
||||
|
||||
/**
|
||||
* The name of the enterprise plan, if applicable.
|
||||
* Returns "community" or "enterprise"
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
const enterprisePlanName = config.enterprisePlanName;
|
||||
|
||||
return {
|
||||
hostURL,
|
||||
vapidPublicKey,
|
||||
enabledLanguages,
|
||||
isEnterprise,
|
||||
enterprisePlanName,
|
||||
};
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
import { computed } from 'vue';
|
||||
import { useStore, useStoreGetters } from 'dashboard/composables/store';
|
||||
|
||||
/**
|
||||
* Composable for managing conversation labels
|
||||
* @returns {Object} An object containing methods and computed properties for conversation labels
|
||||
*/
|
||||
export function useConversationLabels() {
|
||||
const store = useStore();
|
||||
const getters = useStoreGetters();
|
||||
|
||||
/**
|
||||
* The currently selected chat
|
||||
* @type {import('vue').ComputedRef<Object>}
|
||||
*/
|
||||
const currentChat = computed(() => getters.getSelectedChat.value);
|
||||
|
||||
/**
|
||||
* The ID of the current conversation
|
||||
* @type {import('vue').ComputedRef<number|null>}
|
||||
*/
|
||||
const conversationId = computed(() => currentChat.value?.id);
|
||||
|
||||
/**
|
||||
* All labels available for the account
|
||||
* @type {import('vue').ComputedRef<Array>}
|
||||
*/
|
||||
const accountLabels = computed(() => getters['labels/getLabels'].value);
|
||||
|
||||
/**
|
||||
* Labels currently saved to the conversation
|
||||
* @type {import('vue').ComputedRef<Array>}
|
||||
*/
|
||||
const savedLabels = computed(() => {
|
||||
return store.getters['conversationLabels/getConversationLabels'](
|
||||
conversationId.value
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Labels currently active on the conversation
|
||||
* @type {import('vue').ComputedRef<Array>}
|
||||
*/
|
||||
const activeLabels = computed(() =>
|
||||
accountLabels.value.filter(({ title }) => savedLabels.value.includes(title))
|
||||
);
|
||||
|
||||
/**
|
||||
* Labels available but not active on the conversation
|
||||
* @type {import('vue').ComputedRef<Array>}
|
||||
*/
|
||||
const inactiveLabels = computed(() =>
|
||||
accountLabels.value.filter(
|
||||
({ title }) => !savedLabels.value.includes(title)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Updates the labels for the current conversation
|
||||
* @param {string[]} selectedLabels - Array of label titles to be set for the conversation
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const onUpdateLabels = async selectedLabels => {
|
||||
await store.dispatch('conversationLabels/update', {
|
||||
conversationId: conversationId.value,
|
||||
labels: selectedLabels,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a label to the current conversation
|
||||
* @param {Object} value - The label object to be added
|
||||
* @param {string} value.title - The title of the label to be added
|
||||
*/
|
||||
const addLabelToConversation = value => {
|
||||
const result = activeLabels.value.map(item => item.title);
|
||||
result.push(value.title);
|
||||
onUpdateLabels(result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a label from the current conversation
|
||||
* @param {string} value - The title of the label to be removed
|
||||
*/
|
||||
const removeLabelFromConversation = value => {
|
||||
const result = activeLabels.value
|
||||
.map(label => label.title)
|
||||
.filter(label => label !== value);
|
||||
onUpdateLabels(result);
|
||||
};
|
||||
|
||||
return {
|
||||
accountLabels,
|
||||
savedLabels,
|
||||
activeLabels,
|
||||
inactiveLabels,
|
||||
addLabelToConversation,
|
||||
removeLabelFromConversation,
|
||||
onUpdateLabels,
|
||||
};
|
||||
}
|
||||
@@ -108,12 +108,3 @@ export const hasValidAvatarUrl = avatarUrl => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const timeStampAppendedURL = dataUrl => {
|
||||
const url = new URL(dataUrl);
|
||||
if (!url.searchParams.has('t')) {
|
||||
url.searchParams.append('t', Date.now());
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
};
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Determines the last non-activity message between store and API messages.
|
||||
* @param {Object} messageInStore - The last non-activity message from the store.
|
||||
* @param {Object} messageFromAPI - The last non-activity message from the API.
|
||||
* @returns {Object} The latest non-activity message.
|
||||
*/
|
||||
const getLastNonActivityMessage = (messageInStore, messageFromAPI) => {
|
||||
// If both API value and store value for last non activity message
|
||||
// are available, then return the latest one.
|
||||
if (messageInStore && messageFromAPI) {
|
||||
return messageInStore.created_at >= messageFromAPI.created_at
|
||||
? messageInStore
|
||||
: messageFromAPI;
|
||||
}
|
||||
// Otherwise, return whichever is available
|
||||
return messageInStore || messageFromAPI;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters out duplicate source messages from an array of messages.
|
||||
* @param {Array} messages - The array of messages to filter.
|
||||
* @returns {Array} An array of messages without duplicates.
|
||||
*/
|
||||
export const filterDuplicateSourceMessages = (messages = []) => {
|
||||
const messagesWithoutDuplicates = [];
|
||||
// We cannot use Map or any short hand method as it returns the last message with the duplicate ID
|
||||
// We should return the message with smaller id when there is a duplicate
|
||||
messages.forEach(m1 => {
|
||||
if (m1.source_id) {
|
||||
const index = messagesWithoutDuplicates.findIndex(
|
||||
m2 => m1.source_id === m2.source_id
|
||||
);
|
||||
|
||||
if (index < 0) {
|
||||
messagesWithoutDuplicates.push(m1);
|
||||
}
|
||||
} else {
|
||||
messagesWithoutDuplicates.push(m1);
|
||||
}
|
||||
});
|
||||
return messagesWithoutDuplicates;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the last message from a conversation, prioritizing non-activity messages.
|
||||
* @param {Object} m - The conversation object containing messages.
|
||||
* @returns {Object} The last message of the conversation.
|
||||
*/
|
||||
export const getLastMessage = m => {
|
||||
const lastMessageIncludingActivity = m.messages[m.messages.length - 1];
|
||||
|
||||
const nonActivityMessages = m.messages.filter(
|
||||
message => message.message_type !== 2
|
||||
);
|
||||
const lastNonActivityMessageInStore =
|
||||
nonActivityMessages[nonActivityMessages.length - 1];
|
||||
|
||||
const lastNonActivityMessageFromAPI = m.last_non_activity_message;
|
||||
|
||||
// If API value and store value for last non activity message
|
||||
// is empty, then return the last activity message
|
||||
if (!lastNonActivityMessageInStore && !lastNonActivityMessageFromAPI) {
|
||||
return lastMessageIncludingActivity;
|
||||
}
|
||||
|
||||
return getLastNonActivityMessage(
|
||||
lastNonActivityMessageInStore,
|
||||
lastNonActivityMessageFromAPI
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters messages that have been read by the agent.
|
||||
* @param {Array} messages - The array of messages to filter.
|
||||
* @param {number} agentLastSeenAt - The timestamp of when the agent last saw the messages.
|
||||
* @returns {Array} An array of read messages.
|
||||
*/
|
||||
export const getReadMessages = (messages, agentLastSeenAt) => {
|
||||
return messages.filter(
|
||||
message => message.created_at * 1000 <= agentLastSeenAt * 1000
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters messages that have not been read by the agent.
|
||||
* @param {Array} messages - The array of messages to filter.
|
||||
* @param {number} agentLastSeenAt - The timestamp of when the agent last saw the messages.
|
||||
* @returns {Array} An array of unread messages.
|
||||
*/
|
||||
export const getUnreadMessages = (messages, agentLastSeenAt) => {
|
||||
return messages.filter(
|
||||
message => message.created_at * 1000 > agentLastSeenAt * 1000
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
const FEATURE_HELP_URLS = {
|
||||
agent_bots: 'https://chwt.app/hc/agent-bots',
|
||||
agents: 'https://chwt.app/hc/agents',
|
||||
audit_logs: 'https://chwt.app/hc/audit-logs',
|
||||
campaigns: 'https://chwt.app/hc/campaigns',
|
||||
canned_responses: 'https://chwt.app/hc/canned',
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
conversationListPageURL,
|
||||
getArticleSearchURL,
|
||||
hasValidAvatarUrl,
|
||||
timeStampAppendedURL,
|
||||
} from '../URLHelper';
|
||||
|
||||
describe('#URL Helpers', () => {
|
||||
@@ -191,51 +190,4 @@ describe('#URL Helpers', () => {
|
||||
expect(hasValidAvatarUrl()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('timeStampAppendedURL', () => {
|
||||
const FIXED_TIMESTAMP = 1234567890000;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.spyOn(Date, 'now').mockImplementation(() => FIXED_TIMESTAMP);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should append timestamp to a URL without query parameters', () => {
|
||||
const input = 'https://example.com/audio.mp3';
|
||||
const expected = `https://example.com/audio.mp3?t=${FIXED_TIMESTAMP}`;
|
||||
expect(timeStampAppendedURL(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should append timestamp to a URL with existing query parameters', () => {
|
||||
const input = 'https://example.com/audio.mp3?volume=50';
|
||||
const expected = `https://example.com/audio.mp3?volume=50&t=${FIXED_TIMESTAMP}`;
|
||||
expect(timeStampAppendedURL(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should not append timestamp if it already exists', () => {
|
||||
const input = 'https://example.com/audio.mp3?t=9876543210';
|
||||
expect(timeStampAppendedURL(input)).toBe(input);
|
||||
});
|
||||
|
||||
it('should handle URLs with hash fragments', () => {
|
||||
const input = 'https://example.com/audio.mp3#section1';
|
||||
const expected = `https://example.com/audio.mp3?t=${FIXED_TIMESTAMP}#section1`;
|
||||
expect(timeStampAppendedURL(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should handle complex URLs', () => {
|
||||
const input =
|
||||
'https://example.com/path/to/audio.mp3?key1=value1&key2=value2#fragment';
|
||||
const expected = `https://example.com/path/to/audio.mp3?key1=value1&key2=value2&t=${FIXED_TIMESTAMP}#fragment`;
|
||||
expect(timeStampAppendedURL(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid URLs', () => {
|
||||
const input = 'not a valid url';
|
||||
expect(() => timeStampAppendedURL(input)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
import {
|
||||
filterDuplicateSourceMessages,
|
||||
getLastMessage,
|
||||
getReadMessages,
|
||||
getUnreadMessages,
|
||||
} from '../conversationHelper';
|
||||
import {
|
||||
conversationData,
|
||||
lastMessageData,
|
||||
readMessagesData,
|
||||
unReadMessagesData,
|
||||
} from './fixtures/conversationFixtures';
|
||||
|
||||
describe('conversationHelper', () => {
|
||||
describe('#filterDuplicateSourceMessages', () => {
|
||||
it('returns messages without duplicate source_id and all messages without source_id', () => {
|
||||
const input = [
|
||||
{ source_id: null, id: 1 },
|
||||
{ source_id: '', id: 2 },
|
||||
{ id: 3 },
|
||||
{ source_id: 'wa_1', id: 4 },
|
||||
{ source_id: 'wa_1', id: 5 },
|
||||
{ source_id: 'wa_1', id: 6 },
|
||||
{ source_id: 'wa_2', id: 7 },
|
||||
{ source_id: 'wa_2', id: 8 },
|
||||
{ source_id: 'wa_3', id: 9 },
|
||||
];
|
||||
const expected = [
|
||||
{ source_id: null, id: 1 },
|
||||
{ source_id: '', id: 2 },
|
||||
{ id: 3 },
|
||||
{ source_id: 'wa_1', id: 4 },
|
||||
{ source_id: 'wa_2', id: 7 },
|
||||
{ source_id: 'wa_3', id: 9 },
|
||||
];
|
||||
expect(filterDuplicateSourceMessages(input)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#readMessages', () => {
|
||||
it('should return read messages if conversation is passed', () => {
|
||||
expect(
|
||||
getReadMessages(
|
||||
conversationData.messages,
|
||||
conversationData.agent_last_seen_at
|
||||
)
|
||||
).toEqual(readMessagesData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#unReadMessages', () => {
|
||||
it('should return unread messages if conversation is passed', () => {
|
||||
expect(
|
||||
getUnreadMessages(
|
||||
conversationData.messages,
|
||||
conversationData.agent_last_seen_at
|
||||
)
|
||||
).toEqual(unReadMessagesData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#lastMessage', () => {
|
||||
it("should return last activity message if both api and store doesn't have other messages", () => {
|
||||
const testConversation = {
|
||||
messages: [conversationData.messages[0]],
|
||||
last_non_activity_message: null,
|
||||
};
|
||||
expect(getLastMessage(testConversation)).toEqual(
|
||||
testConversation.messages[0]
|
||||
);
|
||||
});
|
||||
|
||||
it('should return message from store if store has latest message', () => {
|
||||
const testConversation = {
|
||||
messages: [],
|
||||
last_non_activity_message: lastMessageData,
|
||||
};
|
||||
expect(getLastMessage(testConversation)).toEqual(lastMessageData);
|
||||
});
|
||||
|
||||
it('should return last non activity message from store if api value is empty', () => {
|
||||
const testConversation = {
|
||||
messages: [conversationData.messages[0], conversationData.messages[1]],
|
||||
last_non_activity_message: null,
|
||||
};
|
||||
expect(getLastMessage(testConversation)).toEqual(
|
||||
testConversation.messages[1]
|
||||
);
|
||||
});
|
||||
|
||||
it("should return last non activity message from store if store doesn't have any messages", () => {
|
||||
const testConversation = {
|
||||
messages: [conversationData.messages[1], conversationData.messages[2]],
|
||||
last_non_activity_message: conversationData.messages[0],
|
||||
};
|
||||
expect(getLastMessage(testConversation)).toEqual(
|
||||
testConversation.messages[1]
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,185 +0,0 @@
|
||||
export const conversationData = {
|
||||
meta: {
|
||||
sender: {
|
||||
additional_attributes: {
|
||||
created_at_ip: '127.0.0.1',
|
||||
},
|
||||
availability_status: 'offline',
|
||||
email: null,
|
||||
id: 5017687,
|
||||
name: 'long-flower-143',
|
||||
phone_number: null,
|
||||
thumbnail: '',
|
||||
custom_attributes: {},
|
||||
},
|
||||
channel: 'Channel::WebWidget',
|
||||
assignee: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'muhsin@chatwoot.com',
|
||||
available_name: 'Muhsin Keloth',
|
||||
id: 21,
|
||||
name: 'Muhsin Keloth',
|
||||
role: 'administrator',
|
||||
thumbnail: 'http://example.com/image.png',
|
||||
},
|
||||
},
|
||||
id: 5815,
|
||||
messages: [
|
||||
{
|
||||
id: 438072,
|
||||
content: 'Campaign after 5 seconds',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5811,
|
||||
message_type: 1,
|
||||
created_at: 1620980262,
|
||||
updated_at: '2021-05-14T08:17:42.041Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: null,
|
||||
content_attributes: {},
|
||||
sender_type: 'User',
|
||||
sender_id: 1,
|
||||
external_source_ids: {},
|
||||
},
|
||||
{
|
||||
id: 4382131101,
|
||||
content: 'Hello',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5815,
|
||||
message_type: 0,
|
||||
created_at: 1621145476,
|
||||
updated_at: '2021-05-16T05:48:43.910Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: null,
|
||||
sender_id: null,
|
||||
external_source_ids: {},
|
||||
},
|
||||
{
|
||||
id: 438100,
|
||||
content: 'Hey',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5815,
|
||||
message_type: 0,
|
||||
created_at: 1621145476,
|
||||
updated_at: '2021-05-16T05:48:43.910Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: null,
|
||||
sender_id: null,
|
||||
external_source_ids: {},
|
||||
},
|
||||
],
|
||||
inbox_id: 37,
|
||||
status: 'open',
|
||||
muted: false,
|
||||
can_reply: true,
|
||||
timestamp: 1621144123,
|
||||
contact_last_seen_at: 0,
|
||||
agent_last_seen_at: 1621144123,
|
||||
unread_count: 0,
|
||||
additional_attributes: {
|
||||
browser: {
|
||||
device_name: 'Unknown',
|
||||
browser_name: 'Chrome',
|
||||
platform_name: 'macOS',
|
||||
browser_version: '90.0.4430.212',
|
||||
platform_version: '10.15.7',
|
||||
},
|
||||
widget_language: null,
|
||||
browser_language: 'en',
|
||||
},
|
||||
account_id: 1,
|
||||
labels: [],
|
||||
};
|
||||
|
||||
export const lastMessageData = {
|
||||
id: 438100,
|
||||
content: 'Hey',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5815,
|
||||
message_type: 0,
|
||||
created_at: 1621145476,
|
||||
updated_at: '2021-05-16T05:48:43.910Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: null,
|
||||
sender_id: null,
|
||||
external_source_ids: {},
|
||||
};
|
||||
|
||||
export const readMessagesData = [
|
||||
{
|
||||
id: 438072,
|
||||
content: 'Campaign after 5 seconds',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5811,
|
||||
message_type: 1,
|
||||
created_at: 1620980262,
|
||||
updated_at: '2021-05-14T08:17:42.041Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: null,
|
||||
content_attributes: {},
|
||||
sender_type: 'User',
|
||||
sender_id: 1,
|
||||
external_source_ids: {},
|
||||
},
|
||||
];
|
||||
|
||||
export const unReadMessagesData = [
|
||||
{
|
||||
id: 4382131101,
|
||||
content: 'Hello',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5815,
|
||||
message_type: 0,
|
||||
created_at: 1621145476,
|
||||
updated_at: '2021-05-16T05:48:43.910Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: null,
|
||||
sender_id: null,
|
||||
external_source_ids: {},
|
||||
},
|
||||
{
|
||||
id: 438100,
|
||||
content: 'Hey',
|
||||
account_id: 1,
|
||||
inbox_id: 37,
|
||||
conversation_id: 5815,
|
||||
message_type: 0,
|
||||
created_at: 1621145476,
|
||||
updated_at: '2021-05-16T05:48:43.910Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: null,
|
||||
sender_id: null,
|
||||
external_source_ids: {},
|
||||
},
|
||||
];
|
||||
@@ -18,7 +18,6 @@
|
||||
"AND": "AND",
|
||||
"OR": "OR"
|
||||
},
|
||||
"INPUT_PLACEHOLDER": "Enter value",
|
||||
"OPERATOR_LABELS": {
|
||||
"equal_to": "Equal to",
|
||||
"not_equal_to": "Not equal to",
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
"HEADER": "Agents",
|
||||
"HEADER_BTN_TXT": "Add Agent",
|
||||
"LOADING": "Fetching Agent List",
|
||||
"DESCRIPTION": "An agent is a member of your customer support team who can view and respond to user messages. The list below shows all the agents in your account.",
|
||||
"LEARN_MORE": "Learn about user roles",
|
||||
"SIDEBAR_TXT": "<p><b>Agents</b></p> <p> An <b>Agent</b> is a member of your Customer Support team. </p><p> Agents will be able to view and reply to messages from your users. The list shows all agents currently in your account. </p><p> Click on <b>Add Agent</b> to add a new agent. Agent you add will receive an email with a confirmation link to activate their account, after which they can access Chatwoot and respond to messages. </p><p> Access to Chatwoot's features are based on following roles. </p><p> <b>Agent</b> - Agents with this role can only access inboxes, reports and conversations. They can assign conversations to other agents or themselves and resolve conversations.</p><p> <b>Administrator</b> - Administrator will have access to all Chatwoot features enabled for your account, including settings, along with all of a normal agents' privileges.</p>",
|
||||
"AGENT_TYPES": {
|
||||
"ADMINISTRATOR": "Administrator",
|
||||
"AGENT": "Agent"
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
"HEADER": "Audit Logs",
|
||||
"HEADER_BTN_TXT": "Add Audit Logs",
|
||||
"LOADING": "Fetching Audit Logs",
|
||||
"DESCRIPTION": "Audit Logs maintain a record of activities in your account, allowing you to track and audit your account, team, or services.",
|
||||
"LEARN_MORE": "Learn more about audit logs",
|
||||
"SEARCH_404": "There are no items matching this query",
|
||||
"SIDEBAR_TXT": "<p><b>Audit Logs</b> </p><p> Audit Logs are trails for events and actions in a Chatwoot System. </p>",
|
||||
"LIST": {
|
||||
@@ -31,8 +29,7 @@
|
||||
"ADD": "%{agentName} invited %{invitee} to the account as an %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} changed their %{attributes} to %{values}",
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}",
|
||||
"DELETED": "%{agentName} changed %{attributes} of a deleted user to %{values}"
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
|
||||
@@ -93,9 +93,7 @@
|
||||
"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",
|
||||
"EMAIL_INPUT_PLACEHOLDER": "Enter email",
|
||||
"URL_INPUT_PLACEHOLDER": "Enter URL"
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||
},
|
||||
"TOGGLE": {
|
||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||
@@ -115,15 +113,6 @@
|
||||
"LABEL_UPLOADING": "Uploading...",
|
||||
"LABEL_UPLOADED": "Successfully Uploaded",
|
||||
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||
"VALUE_REQUIRED": "Value is required",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_LABEL": "Assign",
|
||||
"YES": "Yes",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "Search",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Canned Responses",
|
||||
"LEARN_MORE": "Learn more about canned responses",
|
||||
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"SEARCH_404": "There are no items matching this query.",
|
||||
"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>",
|
||||
"LIST": {
|
||||
"404": "There are no canned responses available in this account.",
|
||||
"TITLE": "Manage canned responses",
|
||||
|
||||
@@ -381,9 +381,6 @@
|
||||
},
|
||||
"SUCCESS_MESSAGE": "Contact merged successfully",
|
||||
"ERROR_MESSAGE": "Could not merge contacts, try again!"
|
||||
},
|
||||
"DROPDOWN_ITEM": {
|
||||
"ID": "(ID: {identifier})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
"MSG_INPUT": "Shift + enter for new line. Start with '/' to select a Canned Response.",
|
||||
"PRIVATE_MSG_INPUT": "Shift + enter for new line. This will be visible only to Agents",
|
||||
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
|
||||
"CLICK_HERE": "Click here to update",
|
||||
"WHATSAPP_TEMPLATES": "Whatsapp Templates"
|
||||
"CLICK_HERE": "Click here to update"
|
||||
},
|
||||
"REPLYBOX": {
|
||||
"REPLY": "Reply",
|
||||
@@ -241,29 +240,25 @@
|
||||
"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.",
|
||||
"GREETING_MORNING": "👋 Good morning, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_AFTERNOON": "👋 Good afternoon, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_EVENING": "👋 Good evening, %{name}. Welcome to %{installationName}.",
|
||||
"READ_LATEST_UPDATES": "Read our latest updates",
|
||||
"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.",
|
||||
"NEW_LINK": "Click here to create an inbox"
|
||||
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status."
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"INBOXES": {
|
||||
"TITLE": "Connect Inboxes",
|
||||
"DESCRIPTION": "Connect various channels through which your customers would be talking to you. It can be a website live-chat, your Facebook page or even your WhatsApp number.",
|
||||
"NEW_LINK": "Click here to create an inbox"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"CANNED_RESPONSES": {
|
||||
"TITLE": "Create canned responses",
|
||||
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
|
||||
"NEW_LINK": "Click here to create a canned response"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_SIDEBAR": {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"GENERAL": {
|
||||
"SHOWING_RESULTS": "Showing {firstIndex}-{lastIndex} of {totalCount} items",
|
||||
"PHONE_INPUT": {
|
||||
"PLACEHOLDER": "Search",
|
||||
"EMPTY_STATE": "No results found"
|
||||
}
|
||||
"SHOWING_RESULTS": "Showing {firstIndex}-{lastIndex} of {totalCount} items"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +481,6 @@
|
||||
"DESCRIPTION": "Use the portal as a headless CMS with third party front-end frameworks using our APIs."
|
||||
}
|
||||
}
|
||||
},
|
||||
"LOADING": "Loading..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
"DESCRIPTION": "Chatwoot integrates with multiple tools and services to improve your team's efficiency. Explore the list below to configure your favorite apps.",
|
||||
"LEARN_MORE": "Learn more about integrations",
|
||||
"LOADING": "Fetching integrations",
|
||||
"CAPTAIN": {
|
||||
"DISABLED": "Captain is not enabled on your account.",
|
||||
"CLICK_HERE_TO_CONFIGURE": "Click here to configure",
|
||||
"LOADING_CONSOLE": "Loading Captain Console...",
|
||||
"FAILED_TO_LOAD_CONSOLE": "Failed to load Captain Console. Please refresh and try again."
|
||||
},
|
||||
"WEBHOOK": {
|
||||
"SUBSCRIBED_EVENTS": "Subscribed Events",
|
||||
"FORM": {
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
"HEADER": "Labels",
|
||||
"HEADER_BTN_TXT": "Add label",
|
||||
"LOADING": "Fetching labels",
|
||||
"DESCRIPTION": "Labels help you categorize and prioritize conversations and leads. You can assign a label to a conversation or contact using the side panel.",
|
||||
"LEARN_MORE": "Learn more about labels",
|
||||
"SEARCH_404": "There are no items matching this query",
|
||||
"SIDEBAR_TXT": "<p><b>Labels</b> <p>Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel. <br /><br />Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.</p>",
|
||||
"LIST": {
|
||||
"404": "There are no labels available in this account.",
|
||||
"TITLE": "Manage labels",
|
||||
@@ -50,8 +49,7 @@
|
||||
"DISMISS": "Dismiss",
|
||||
"ADD_SELECTED_LABELS": "Add selected labels",
|
||||
"ADD_SELECTED_LABEL": "Add selected label",
|
||||
"ADD_ALL_LABELS": "Add all labels",
|
||||
"SUGGESTED_LABELS": "Suggested labels"
|
||||
"ADD_ALL_LABELS": "Add all labels"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Add label",
|
||||
|
||||
@@ -73,15 +73,6 @@
|
||||
"BUTTON_TOOLTIP": "Execute",
|
||||
"PREVIEW": "Preview Macro",
|
||||
"EXECUTED_SUCCESSFULLY": "Macro executed successfully"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||
"VALUE_REQUIRED": "Value is required",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,8 +481,7 @@
|
||||
"HEADER": "Conversation Traffic",
|
||||
"NO_CONVERSATIONS": "No conversations",
|
||||
"CONVERSATION": "%{count} conversation",
|
||||
"CONVERSATIONS": "%{count} conversations",
|
||||
"DOWNLOAD_REPORT": "Download report"
|
||||
"CONVERSATIONS": "%{count} conversations"
|
||||
},
|
||||
"AGENT_CONVERSATIONS": {
|
||||
"HEADER": "Conversations by agents",
|
||||
@@ -537,7 +536,6 @@
|
||||
"LABELS": "Label",
|
||||
"TEAMS": "Team"
|
||||
},
|
||||
"WITH": "with",
|
||||
"METRICS": {
|
||||
"HIT_RATE": {
|
||||
"LABEL": "Hit Rate",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"CONVERSATIONS": "Conversations",
|
||||
"MESSAGES": "Messages"
|
||||
},
|
||||
"SEARCHING_DATA": "Searching",
|
||||
"EMPTY_STATE": "No %{item} found for query '%{query}'",
|
||||
"EMPTY_STATE_FULL": "No results found for query '%{query}'",
|
||||
"PLACEHOLDER_KEYBINDING": "/ to focus",
|
||||
|
||||
@@ -239,7 +239,6 @@
|
||||
"REPORTS": "Reports",
|
||||
"SETTINGS": "Settings",
|
||||
"CONTACTS": "Contacts",
|
||||
"CAPTAIN": "Captain",
|
||||
"HOME": "Home",
|
||||
"AGENTS": "Agents",
|
||||
"AGENT_BOTS": "Bots",
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
"TEAMS_SETTINGS": {
|
||||
"NEW_TEAM": "Create new team",
|
||||
"HEADER": "Teams",
|
||||
"LOADING": "Fetching teams",
|
||||
"DESCRIPTION": "Teams allow you to organize agents into groups based on their responsibilities. An agent can belong to multiple teams. When working collaboratively, you can assign conversations to specific teams.",
|
||||
"LEARN_MORE": "Learn more about teams",
|
||||
"SIDEBAR_TXT": "<p><b>Teams</b></p> <p>Teams let you organize your agents into groups based on their responsibilities. <br /> An agent can be part of multiple teams. You can assign conversations to a team when you are working collaboratively. </p>",
|
||||
"LIST": {
|
||||
"404": "There are no teams created on this account.",
|
||||
"EDIT_TEAM": "Edit team",
|
||||
"NONE": "None"
|
||||
"EDIT_TEAM": "Edit team"
|
||||
},
|
||||
"CREATE_FLOW": {
|
||||
"CREATE": {
|
||||
@@ -100,7 +97,7 @@
|
||||
"ERROR_MESSAGE": "Couldn't delete the team. Try again."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Are you sure you want to delete the team?",
|
||||
"TITLE": "Are you sure want to delete - %{teamName}",
|
||||
"PLACE_HOLDER": "Please type {teamName} to confirm",
|
||||
"MESSAGE": "Deleting the team will remove the team assignment from the conversations assigned to this team.",
|
||||
"YES": "Delete ",
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"AND": "و",
|
||||
"OR": "أو"
|
||||
},
|
||||
"INPUT_PLACEHOLDER": "Enter value",
|
||||
"OPERATOR_LABELS": {
|
||||
"equal_to": "يساوي",
|
||||
"not_equal_to": "لا يساوي",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"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>",
|
||||
"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": "اسم الروبوت",
|
||||
@@ -21,52 +21,52 @@
|
||||
"SUBMIT": "التحقق والحفظ"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "اختر الروبوت",
|
||||
"DESC": "قم بتعيين روبوت لصندوق الوارد الخاص بك. يمكنهم التعامل مع المحادثات الأولية ونقلها إلى وكيل مباشر عند الضرورة.",
|
||||
"TITLE": "اختر بوت",
|
||||
"DESC": "قم بتعيين بوت لصندوق الوارد الخاص بك. يمكنهم التعامل مع المحادثات الأولية ونقلها إلى وكيل مباشر عند الضرورة.",
|
||||
"SUBMIT": "تحديث",
|
||||
"DISCONNECT": "قطع اتصال الروبوت",
|
||||
"SUCCESS_MESSAGE": "تم تحديث الروبوت بنجاح.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "تم فصل الروبوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث الروبوت. يرجى المحاولة مرة أخرى.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "تعذر فصل الروبوت. يرجى المحاولة مرة أخرى.",
|
||||
"SELECT_PLACEHOLDER": "اختر الروبوت"
|
||||
"DISCONNECT": "فصل البوت",
|
||||
"SUCCESS_MESSAGE": "تم تحديث البوت بنجاح.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "تم فصل البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث البوت. يرجى المحاولة مرة أخرى.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "تعذر فصل البوت. يرجى المحاولة مرة أخرى.",
|
||||
"SELECT_PLACEHOLDER": "اختر بوت"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "تكوين روبوت جديد",
|
||||
"TITLE": "تكوين بوت جديد",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تمت إضافة الروبوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر إضافة الروبوت. يرجى المحاولة مرة أخرى لاحقًا."
|
||||
"SUCCESS_MESSAGE": "تمت إضافة البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر إضافة البوت. يرجى المحاولة مرة أخرى لاحقًا."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "لم يتم العثور على أي روبوتات. يمكنك إنشاء الروبوت بالنقر على زر 'تكوين روبوت جديد' ↗",
|
||||
"LOADING": "جار جلب الروبوتات...",
|
||||
"TYPE": "نوع الروبوت"
|
||||
"404": "لم يتم العثور على أي بوتات. يمكنك إنشاء بوت بالنقر على زر 'تكوين بوت جديد' ↗",
|
||||
"LOADING": "جارٍ جلب البوتات...",
|
||||
"TYPE": "نوع البوت"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "حذف",
|
||||
"TITLE": "حذف الروبوت",
|
||||
"TITLE": "حذف البوت",
|
||||
"SUBMIT": "حذف",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"DESCRIPTION": "هل أنت متأكد أنك تريد حذف هذا الروبوت؟ هذا الإجراء لا يمكن التراجع عنه.",
|
||||
"DESCRIPTION": "هل أنت متأكد أنك تريد حذف هذا البوت؟ هذا الإجراء لا يمكن التراجع عنه.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم حذف الروبوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر حذف الروبوت. يرجى المحاولة مرة أخرى."
|
||||
"SUCCESS_MESSAGE": "تم حذف البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر حذف البوت. يرجى المحاولة مرة أخرى."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "تعديل",
|
||||
"LOADING": "جار جلب الروبوتات...",
|
||||
"TITLE": "تعديل الروبوت",
|
||||
"LOADING": "جارٍ جلب البوتات...",
|
||||
"TITLE": "تعديل البوت",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم تحديث الروبوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث الروبوت. يرجى المحاولة مرة أخرى."
|
||||
"SUCCESS_MESSAGE": "تم تحديث البوت بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر تحديث البوت. يرجى المحاولة مرة أخرى."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "روبوت الـWebhook",
|
||||
"WEBHOOK": "بوت Webhook",
|
||||
"CSML": "بوت CSML"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
"HEADER": "الوكلاء",
|
||||
"HEADER_BTN_TXT": "إضافة وكيل",
|
||||
"LOADING": "جار جلب قائمة الوكلاء",
|
||||
"DESCRIPTION": "An agent is a member of your customer support team who can view and respond to user messages. The list below shows all the agents in your account.",
|
||||
"LEARN_MORE": "Learn about user roles",
|
||||
"SIDEBAR_TXT": "<p><b>الموظفين</b></p> <p> موظف الدعم <b></b> هو عضو في فريق دعم العملاء الخاص بك. </p><p> يستطيع موظفو الدعم مشاهدة الرسائل الواردة من المستخدمين والرد عليها. تظهر القائمة جميع الموظفين الموجودين حاليا في حسابك. </p><p> انقر فوق <b>إضافة موظف</b> لإضافة موظف دعم فني جديد. سيتلقى الشخص الذي تضيفه رسالة بريد إلكتروني مع رابط تأكيد لتفعيل حسابه ، وبعد ذلك يمكنهم الوصول إلى Chatwoot والرد على الرسائل. </p><p> الوصول إلى ميزات Chatwoot يتوقف على الصلاحيات التالية. </p><p> <b>الموظف</b> - موظفي الدعم الذين لديهم هذه الصلاحية يمكنهم فقط الوصول إلى صناديق قنوات التواصل والتقارير والمحادثات. ويمكنهم بدء محادثات مع موظفين آخرين أو مع أنفسهم وأيضاً إغلاق المحادثات.</p><p> <b>مدير البرنامج</b> - الشخص المسؤول من الوصول إلى جميع ميزات Chatwoot المفعلة للحساب الخاص بك. بما في ذلك الإعدادات، إلى جانب جميع امتيازات الموظفين العاديين.</p>",
|
||||
"AGENT_TYPES": {
|
||||
"ADMINISTRATOR": "المدير",
|
||||
"AGENT": "وكيل الدعم"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"ATTRIBUTES_MGMT": {
|
||||
"HEADER": "صفات مخصصة",
|
||||
"HEADER_BTN_TXT": "إضافة صفة خاصة",
|
||||
"LOADING": "جلب الصفات المخصصة",
|
||||
"SIDEBAR_TXT": "<p><b>الصفات المخصصة</b> <p>صفة مخصصة تتبع الحقائق حول جهات الاتصال/المحادثة الخاصة بك - مثل خُطَّة الاشتراك. أو عندما يطلبون العنصر الأول وما إلى ذلك. <br /><br />لإنشاء صفة مخصصة، فقط انقر فوق<b>أضف صفة مخصصة.</b> يمكنك أيضا تعديل أو حذف صفة مخصصة موجودة بالنقر على زر التحرير أو الحذف.</p>",
|
||||
"HEADER": "سمات مخصصة",
|
||||
"HEADER_BTN_TXT": "إضافة سمة خاصة",
|
||||
"LOADING": "جلب سمات مخصصة",
|
||||
"SIDEBAR_TXT": "<p><b>السمات المخصصة</b> <p>سمة مخصصة تتبع الحقائق حول جهات الاتصال/المحادثة الخاصة بك - مثل خطة الاشتراك. أو عندما يطلبون العنصر الأول وما إلى ذلك. <br /><br />لإنشاء سمة مخصصة، فقط انقر فوق<b>أضف سمة مخصصة.</b> يمكنك أيضا تعديل أو حذف سمة مخصصة موجودة بالنقر على زر التحرير أو الحذف.</p>",
|
||||
"ADD": {
|
||||
"TITLE": "إضافة صفة خاصة",
|
||||
"TITLE": "إضافة سمة خاصة",
|
||||
"SUBMIT": "إنشاء",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"FORM": {
|
||||
"NAME": {
|
||||
"LABEL": "اسم العرض",
|
||||
"PLACEHOLDER": "أدخل اسم عرض الصفة",
|
||||
"PLACEHOLDER": "أدخل اسم عرض السمة",
|
||||
"ERROR": "الاسم مطلوب"
|
||||
},
|
||||
"DESC": {
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"KEY": {
|
||||
"LABEL": "المفتاح",
|
||||
"PLACEHOLDER": "أدخل مفتاح الصفة المخصصة",
|
||||
"PLACEHOLDER": "أدخل مفتاح السمة المخصصة",
|
||||
"ERROR": "المفتاح مطلوب",
|
||||
"IN_VALID": "مفتاح غير صالح"
|
||||
},
|
||||
@@ -53,26 +53,26 @@
|
||||
}
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم إضافة صفة مخصصة بنجاح!",
|
||||
"ERROR_MESSAGE": "تعذر إنشاء صفة مخصصة، الرجاء المحاولة مرة أخرى لاحقاً."
|
||||
"SUCCESS_MESSAGE": "تم إضافة سمة مخصصة بنجاح!",
|
||||
"ERROR_MESSAGE": "تعذر إنشاء سمة مخصصة، الرجاء المحاولة مرة أخرى لاحقاً."
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "حذف",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم حذف الصفة المخصصة بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر حذف الصفة المخصصة. حاول مرة أخرى."
|
||||
"SUCCESS_MESSAGE": "تم حذف السمة المخصصة بنجاح.",
|
||||
"ERROR_MESSAGE": "تعذر حذف السمة المخصصة. حاول مرة أخرى."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "هل أنت متأكد من أنك تريد حذف - %{attributeName}",
|
||||
"PLACE_HOLDER": "الرجاء كتابة {attributeName} للتأكيد",
|
||||
"MESSAGE": "الحذف سوف يزيل الصفة المخصصة",
|
||||
"MESSAGE": "حذف سوف يزيل السمة المخصصة",
|
||||
"YES": "حذف ",
|
||||
"NO": "إلغاء"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "تعديل صفة مخصصة",
|
||||
"TITLE": "تعديل سمة مخصصة",
|
||||
"UPDATE_BUTTON_TEXT": "تحديث",
|
||||
"TYPE": {
|
||||
"LIST": {
|
||||
@@ -81,12 +81,12 @@
|
||||
}
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم تحديث الصفة المخصصة بنجاح",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء تحديث الصفة المخصصة، الرجاء المحاولة مرة أخرى"
|
||||
"SUCCESS_MESSAGE": "تم تحديث السمة المخصصة بنجاح",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء تحديث السمة المخصصة، الرجاء المحاولة مرة أخرى"
|
||||
}
|
||||
},
|
||||
"TABS": {
|
||||
"HEADER": "صفات مخصصة",
|
||||
"HEADER": "سمات مخصصة",
|
||||
"CONVERSATION": "المحادثات",
|
||||
"CONTACT": "جهات الاتصال"
|
||||
},
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"REGEX_PATTERN": {
|
||||
"LABEL": "نمط Regex",
|
||||
"PLACEHOLDER": "الرجاء إدخال صفة مخصصة ريمكس (اختياري)"
|
||||
"PLACEHOLDER": "الرجاء إدخال سمة مخصصة ريمكس (اختياري)"
|
||||
},
|
||||
"REGEX_CUE": {
|
||||
"LABEL": "Regex Cue",
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
"HEADER": "سجلات التدقيق",
|
||||
"HEADER_BTN_TXT": "إضافة سجلات التدقيق",
|
||||
"LOADING": "جارٍ جلب سجلات التدقيق",
|
||||
"DESCRIPTION": "Audit Logs maintain a record of activities in your account, allowing you to track and audit your account, team, or services.",
|
||||
"LEARN_MORE": "Learn more about audit logs",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام",
|
||||
"SIDEBAR_TXT": "<p><b>سجلات التدقيق</b> </p><p> سجلات التدقيق هي مسارات للأحداث والإجراءات في نظام Chatwoot. </p>",
|
||||
"LIST": {
|
||||
@@ -31,8 +29,7 @@
|
||||
"ADD": "%{agentName} دعا %{invitee} إلى الحساب كـ %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} غير %{attributes} الخاصة به إلى %{values}",
|
||||
"OTHER": "%{agentName} غير %{attributes} لـ %{user} إلى %{values}",
|
||||
"DELETED": "%{agentName} changed %{attributes} of a deleted user to %{values}"
|
||||
"OTHER": "%{agentName} غير %{attributes} لـ %{user} إلى %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
|
||||
@@ -93,9 +93,7 @@
|
||||
"ACTION": {
|
||||
"DELETE_MESSAGE": "يجب أن يكون لديك على الأقل شرط واحد للحفظ",
|
||||
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "اكتب رسالتك هنا",
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "اختيار فريق",
|
||||
"EMAIL_INPUT_PLACEHOLDER": "Enter email",
|
||||
"URL_INPUT_PLACEHOLDER": "Enter URL"
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "اختيار فريق"
|
||||
},
|
||||
"TOGGLE": {
|
||||
"ACTIVATION_TITLE": "تفعيل قاعدة الأتمتة",
|
||||
@@ -115,15 +113,6 @@
|
||||
"LABEL_UPLOADING": "جاري الرفع...",
|
||||
"LABEL_UPLOADED": "تم الرفع بنجاح",
|
||||
"LABEL_UPLOAD_FAILED": "فشل الرفع"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "مفتاح الخاصية مطلوب",
|
||||
"FILTER_OPERATOR_REQUIRED": "عامل التصفية مطلوب",
|
||||
"VALUE_REQUIRED": "القيمة مطلوبة",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "القيمة يجب أن تكون بين 1 و 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "معلمات الإجراء مطلوبة",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "شرط واحد على الأقل مطلوب",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "إجراء واحد على الأقل مطلوب"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"GO_BACK_LABEL": "العودة للخلف",
|
||||
"ASSIGN_LABEL": "تكليف",
|
||||
"YES": "نعم",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "بحث",
|
||||
"ASSIGN_AGENT_TOOLTIP": "تعيين وكيل",
|
||||
"ASSIGN_TEAM_TOOLTIP": "تعيين فريق",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين المحادثات بنجاح.",
|
||||
|
||||
@@ -46,12 +46,12 @@
|
||||
"END_POINT": {
|
||||
"LABEL": "الرابط",
|
||||
"PLACEHOLDER": "الرجاء إدخال الرابط",
|
||||
"ERROR": "الرجاء إدخال عنوان رابط صالح"
|
||||
"ERROR": "الرجاء إدخال عنوان URL صالح"
|
||||
},
|
||||
"TIME_ON_PAGE": {
|
||||
"LABEL": "الوقت في الصفحة (ثواني)",
|
||||
"LABEL": "الوقت على الصفحة (ثواني)",
|
||||
"PLACEHOLDER": "الرجاء إدخال الوقت",
|
||||
"ERROR": "الوقت في الصفحة مطلوب"
|
||||
"ERROR": "الوقت على الصفحة مطلوب"
|
||||
},
|
||||
"ENABLED": "تفعيل الحملة",
|
||||
"TRIGGER_ONLY_BUSINESS_HOURS": "تشغيل فقط خلال ساعات العمل",
|
||||
@@ -84,7 +84,7 @@
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "جاري جلب الحملات...",
|
||||
"LOADING_MESSAGE": "جاري تحميل الحملات...",
|
||||
"404": "لا توجد حملات منشئة لهذا البريد الوارد.",
|
||||
"TABLE_HEADER": {
|
||||
"TITLE": "العنوان",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "الردود الجاهزة",
|
||||
"LEARN_MORE": "Learn more about canned responses",
|
||||
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
|
||||
"HEADER_BTN_TXT": "إضافة رد جاهز",
|
||||
"LOADING": "جاري جلب الردود الجاهزة...",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام.",
|
||||
"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": "إدارة الردود الجاهزة",
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
"DUPLICATE": "رقم الهاتف هذا مستخدم لجهة اتصال أخرى."
|
||||
},
|
||||
"LOCATION": {
|
||||
"PLACEHOLDER": "أدخل الموقع الجغرافي لجهة الاتصال",
|
||||
"PLACEHOLDER": "أدخل موقع جهة الاتصال",
|
||||
"LABEL": "الموقع الجغرافي"
|
||||
},
|
||||
"COMPANY_NAME": {
|
||||
@@ -199,7 +199,7 @@
|
||||
},
|
||||
"INBOX": {
|
||||
"LABEL": "صندوق الوارد",
|
||||
"PLACEHOLDER": "اختيار مصدر البريد الوارد",
|
||||
"PLACEHOLDER": "اختر صندوق المصدر",
|
||||
"ERROR": "حدد صندوق الوارد"
|
||||
},
|
||||
"SUBJECT": {
|
||||
@@ -228,9 +228,9 @@
|
||||
"FIELDS": "حقول جهات الاتصال",
|
||||
"SEARCH_BUTTON": "بحث",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "بحث عن جهات الاتصال",
|
||||
"FILTER_CONTACTS": "تصفية",
|
||||
"FILTER_CONTACTS_SAVE": "حفظ التصفية",
|
||||
"FILTER_CONTACTS_DELETE": "حذف التصفية",
|
||||
"FILTER_CONTACTS": "فلترة",
|
||||
"FILTER_CONTACTS_SAVE": "حفظ الفلتر",
|
||||
"FILTER_CONTACTS_DELETE": "حذف الفلتر",
|
||||
"FILTER_CONTACTS_EDIT": "تحرير الجزء",
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "جاري جلب جهات الاتصال...",
|
||||
@@ -313,30 +313,30 @@
|
||||
"CREATE": "أضف سمة",
|
||||
"CANCEL": "إلغاء",
|
||||
"NAME": {
|
||||
"LABEL": "اسم الصفة الخاصة",
|
||||
"LABEL": "اسم السمة الخاصة",
|
||||
"PLACEHOLDER": "مثال: shopify id",
|
||||
"ERROR": "اسم الصفة المخصصة غير صالح"
|
||||
"ERROR": "اسم السمة المخصصة غير صالح"
|
||||
},
|
||||
"VALUE": {
|
||||
"LABEL": "قيمة السمة",
|
||||
"PLACEHOLDER": "مثلاً: 11901 "
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "إنشاء صفة جديدة ",
|
||||
"SUCCESS": "تمت إضافة الصفة بنجاح",
|
||||
"ERROR": "غير قادر على إضافة الصفة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
"TITLE": "إنشاء سمة جديدة ",
|
||||
"SUCCESS": "تمت إضافة السمة بنجاح",
|
||||
"ERROR": "غير قادر على إضافة السمة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
},
|
||||
"UPDATE": {
|
||||
"SUCCESS": "تم تحديث الصفة المخصصة بنجاح",
|
||||
"ERROR": "غير قادر على تحديث الصفة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
"SUCCESS": "تم تحديث السمة المخصصة بنجاح",
|
||||
"ERROR": "غير قادر على تحديث السمة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
},
|
||||
"DELETE": {
|
||||
"SUCCESS": "تم حذف الصفة المخصصة بنجاح",
|
||||
"ERROR": "غير قادر على حذف الصفة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
"SUCCESS": "تم حذف السمة المخصصة بنجاح",
|
||||
"ERROR": "غير قادر على حذف السمة. الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
},
|
||||
"ATTRIBUTE_SELECT": {
|
||||
"TITLE": "أضف صفة",
|
||||
"PLACEHOLDER": "البحث عن صفات",
|
||||
"TITLE": "أضف سمة",
|
||||
"PLACEHOLDER": "البحث عن سمات",
|
||||
"NO_RESULT": "لم يتم العثور على سمات"
|
||||
},
|
||||
"ATTRIBUTE_TYPE": {
|
||||
@@ -349,7 +349,7 @@
|
||||
},
|
||||
"VALIDATIONS": {
|
||||
"REQUIRED": "القيمة الصالحة مطلوبة",
|
||||
"INVALID_URL": "عنوان الرابط غير صالح",
|
||||
"INVALID_URL": "عنوان URL غير صالح",
|
||||
"INVALID_INPUT": "مدخلات غير صالح"
|
||||
}
|
||||
},
|
||||
@@ -367,8 +367,8 @@
|
||||
},
|
||||
"SUMMARY": {
|
||||
"TITLE": "ملخص",
|
||||
"DELETE_WARNING": "سيتم حذف جهة الاتصال <strong>%{primaryContactName}</strong>.",
|
||||
"ATTRIBUTE_WARNING": "سيتم نسخ تفاصيل الاتصال من <strong>%{primaryContactName}</strong> إلى <strong>%{parentContactName}</strong>."
|
||||
"DELETE_WARNING": "سيتم حذف جهة الاتصال بـ <strong>%{primaryContactName}</strong>.",
|
||||
"ATTRIBUTE_WARNING": "سيتم نسخ تفاصيل الاتصال بـ <strong>%{primaryContactName}</strong> إلى <strong>%{parentContactName}</strong>."
|
||||
},
|
||||
"SEARCH": {
|
||||
"ERROR": "رسالة_خطأ"
|
||||
@@ -381,9 +381,6 @@
|
||||
},
|
||||
"SUCCESS_MESSAGE": "تم دمج جهة الاتصال بنجاح",
|
||||
"ERROR_MESSAGE": "تعذر دمج جهات الاتصال ، حاول مرة أخرى!"
|
||||
},
|
||||
"DROPDOWN_ITEM": {
|
||||
"ID": "(ID: {identifier})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
"MSG_INPUT": "زر Shift + Enter لإضافة سطر جديد. ابدأ بزر / للاختيار من الردود الجاهزة.",
|
||||
"PRIVATE_MSG_INPUT": "زر Shift + Enter لإضافة سطر جديد. سيكون هذا مرئياً للوكلاء فقط",
|
||||
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "لم يتم تكوين توقيع الرسالة، الرجاء تكوينه في إعدادات الملف الشخصي.",
|
||||
"CLICK_HERE": "انقر هنا للتحديث",
|
||||
"WHATSAPP_TEMPLATES": "قوالب Whatsapp"
|
||||
"CLICK_HERE": "انقر هنا للتحديث"
|
||||
},
|
||||
"REPLYBOX": {
|
||||
"REPLY": "إضافة رد",
|
||||
@@ -151,7 +150,7 @@
|
||||
"SEND": "إرسال",
|
||||
"CREATE": "إضافة ملاحظة",
|
||||
"INSERT_READ_MORE": "اقرأ المزيد",
|
||||
"DISMISS_REPLY": "استبعاد الرد",
|
||||
"DISMISS_REPLY": "تجاهل الرد",
|
||||
"REPLYING_TO": "الرد على:",
|
||||
"TIP_FORMAT_ICON": "عرض محرر النصوص",
|
||||
"TIP_EMOJI_ICON": "إظهار قائمة الرموز التعبيرية",
|
||||
@@ -168,12 +167,12 @@
|
||||
"ADD_BCC": "إضافة bcc",
|
||||
"CC": {
|
||||
"LABEL": "CC",
|
||||
"PLACEHOLDER": "عناوين البريد الإلكتروني مفصولة بفاصلة",
|
||||
"PLACEHOLDER": "البريد الإلكتروني مفصولة بفاصلة",
|
||||
"ERROR": "الرجاء إدخال عنوان بريد إلكتروني صحيح"
|
||||
},
|
||||
"BCC": {
|
||||
"LABEL": "BCC",
|
||||
"PLACEHOLDER": "عناوين البريد الإلكتروني مفصولة بفاصلة",
|
||||
"PLACEHOLDER": "البريد الإلكتروني مفصولة بفاصلة",
|
||||
"ERROR": "الرجاء إدخال عنوان بريد إلكتروني صحيح"
|
||||
}
|
||||
},
|
||||
@@ -194,7 +193,7 @@
|
||||
"ASSIGN_LABEL_SUCCESFUL": "تم تعيين الوسم بنجاح",
|
||||
"ASSIGN_LABEL_FAILED": "فشل تعيين الوسم",
|
||||
"CHANGE_TEAM": "تم تغيير فريق المحادثة",
|
||||
"FILE_SIZE_LIMIT": "حجم الملف يتجاوز حد الاقصى وهو {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE}",
|
||||
"FILE_SIZE_LIMIT": "الملف يتجاوز حد المرفق {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} ميغابايت",
|
||||
"MESSAGE_ERROR": "غير قادر على إرسال هذه الرسالة، الرجاء المحاولة مرة أخرى لاحقاً",
|
||||
"SENT_BY": "أرسلت بواسطة:",
|
||||
"BOT": "رد آلي",
|
||||
@@ -241,29 +240,25 @@
|
||||
"ONBOARDING": {
|
||||
"TITLE": "اهلاً 👋، مرحباً بك في %{installationName}!",
|
||||
"DESCRIPTION": "شكرا للتسجيل. نريدك أن تحصل على أقصى استفادة من %{installationName}. إليك بعض الأشياء التي يمكنك القيام بها في %{installationName} لجعل التجربة رائعة.",
|
||||
"GREETING_MORNING": "👋 Good morning, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_AFTERNOON": "👋 Good afternoon, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_EVENING": "👋 Good evening, %{name}. Welcome to %{installationName}.",
|
||||
"READ_LATEST_UPDATES": "اطلع على آخر التحديثات",
|
||||
"ALL_CONVERSATION": {
|
||||
"TITLE": "جميع محادثاتك في مكان واحد",
|
||||
"DESCRIPTION": "عرض جميع المحادثات من عملائك في لوحة تحكم واحدة. يمكنك تصفية المحادثات حسب القناة الواردة والتسمية والحالة.",
|
||||
"NEW_LINK": "انقر هنا لإنشاء صندوق وارد"
|
||||
"DESCRIPTION": "عرض جميع المحادثات من عملائك في لوحة تحكم واحدة. يمكنك تصفية المحادثات حسب القناة الواردة والتسمية والحالة."
|
||||
},
|
||||
"TEAM_MEMBERS": {
|
||||
"TITLE": "قم بدعوة أعضاء فريقك",
|
||||
"DESCRIPTION": "عندما تصبح جاهز للتخاطب مع عميلك، احضر زملائك في الفريق لمساعدتك. يمكنك دعوة زملائك في الفريق بإضافة عنوان البريد الإلكتروني الخاص بهم إلى قائمة الوكلاء.",
|
||||
"NEW_LINK": "انقر هنا لدعوة عضو في الفريق"
|
||||
},
|
||||
"INBOXES": {
|
||||
"TITLE": "ربط الصناديق الواردة",
|
||||
"DESCRIPTION": "قم بتوصيل مختلف القنوات التي من خلالها يتحدث عملاؤك إليك. يمكن أن تكون محادثة مباشرة على موقع الويب أو صفحة فيسبوك أو تويتر أو حتى رقم WhatsApp الخاص بك.",
|
||||
"NEW_LINK": "انقر هنا لإنشاء صندوق وارد"
|
||||
},
|
||||
"LABELS": {
|
||||
"TITLE": "تنظيم المحادثات مع التسميات",
|
||||
"DESCRIPTION": "التسميات توفر طريقة أسهل لتصنيف محادثتك. إنشاء بعض التسميات مثل #كبار_العملاء، #العملاء_المحتملون الخ، بحيث يمكنك استخدامها في محادثة لاحقا.",
|
||||
"NEW_LINK": "انقر هنا لإنشاء وسوم"
|
||||
},
|
||||
"CANNED_RESPONSES": {
|
||||
"TITLE": "Create canned responses",
|
||||
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
|
||||
"NEW_LINK": "Click here to create a canned response"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_SIDEBAR": {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"LAST_3_MONTHS": "آخر 3 أشهر",
|
||||
"LAST_6_MONTHS": "آخر 6 أشهر",
|
||||
"LAST_YEAR": "العام الماضي",
|
||||
"CUSTOM_RANGE": "تحديد نطاق التاريخ"
|
||||
"CUSTOM_RANGE": "تحديد نطاق المدة"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"GENERAL": {
|
||||
"SHOWING_RESULTS": "عرض{firstIndex}-{lastIndex} من {totalCount} إجمالي العناصر",
|
||||
"PHONE_INPUT": {
|
||||
"PLACEHOLDER": "بحث",
|
||||
"EMPTY_STATE": "لم يتم العثور على النتائج"
|
||||
}
|
||||
"SHOWING_RESULTS": "عرض{firstIndex}-{lastIndex} من {totalCount} إجماليي العناصر"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"AUTO_RESOLVE_DURATION": {
|
||||
"LABEL": "عدد الأيام للتذكرة التي يجب أن يتم حلها تلقائياً إذا لم يكن هناك أي نشاط",
|
||||
"PLACEHOLDER": "30",
|
||||
"ERROR": "الرجاء إدخال مدة صالحة للحل تلقائي (حد أدنى 1 يوم والحد الأقصى 999 يوما)"
|
||||
"ERROR": "الرجاء إدخال مدة حل تلقائي صالحة (حد أدنى 1 يوم والحد الأقصى 999 يوما)"
|
||||
},
|
||||
"FEATURES": {
|
||||
"INBOUND_EMAIL_ENABLED": "الاستمرار في المحادثة عبر رسائل البريد الإلكتروني مفعّل لحسابك.",
|
||||
@@ -64,16 +64,16 @@
|
||||
},
|
||||
"NOTIFICATIONS_PAGE": {
|
||||
"HEADER": "الإشعارات",
|
||||
"MARK_ALL_DONE": "وضع علامة منجز على الجميع",
|
||||
"MARK_ALL_DONE": "وضع علامة على جميع المنجز",
|
||||
"DELETE_TITLE": "تم الحذف",
|
||||
"UNREAD_NOTIFICATION": {
|
||||
"TITLE": "إشعارات غير مقروءة",
|
||||
"ALL_NOTIFICATIONS": "عرض جميع الإشعارات",
|
||||
"LOADING_UNREAD_MESSAGE": "جار جلب الإشعارات الغير مقروءة...",
|
||||
"LOADING_UNREAD_MESSAGE": "تحميل الإشعارات الغير مقروءة...",
|
||||
"EMPTY_MESSAGE": "ليس لديك إشعارات غير مقروءة"
|
||||
},
|
||||
"LIST": {
|
||||
"LOADING_MESSAGE": "جاري جلب الإشعارات...",
|
||||
"LOADING_MESSAGE": "جاري تحميل الإشعارات...",
|
||||
"404": "لا يوجد إشعارات",
|
||||
"TABLE_HEADER": [
|
||||
"الاسم",
|
||||
@@ -114,8 +114,8 @@
|
||||
"CHANGE_PRIORITY": "تغيير الأولوية",
|
||||
"CHANGE_TEAM": "تغيير الفريق",
|
||||
"SNOOZE_CONVERSATION": "تأجيل المحادثة",
|
||||
"ADD_LABEL": "إضافة وسم إلى المحادثة",
|
||||
"REMOVE_LABEL": "إزالة الوسم من المحادثة",
|
||||
"ADD_LABEL": "إضافة تسمية إلى المحادثة",
|
||||
"REMOVE_LABEL": "إزالة التسمية من المحادثة",
|
||||
"SETTINGS": "الإعدادات",
|
||||
"AI_ASSIST": "مساعدة AI",
|
||||
"APPEARANCE": "المظهر",
|
||||
@@ -127,26 +127,26 @@
|
||||
"GO_TO_REPORTS_OVERVIEW": "الذهاب إلى نظرة التقارير العامة",
|
||||
"GO_TO_CONVERSATION_REPORTS": "الذهاب إلى تقارير المحادثات",
|
||||
"GO_TO_AGENT_REPORTS": "الذهاب إلى تقارير الوكيل",
|
||||
"GO_TO_LABEL_REPORTS": "انتقل إلى تقارير الوسم",
|
||||
"GO_TO_LABEL_REPORTS": "انتقل إلى تقارير التسمية",
|
||||
"GO_TO_INBOX_REPORTS": "الذهاب إلى تقارير صندوق الوارد",
|
||||
"GO_TO_TEAM_REPORTS": "الذهاب إلى تقارير الفريق",
|
||||
"GO_TO_SETTINGS_AGENTS": "الذهاب إلى إعدادات الوكيل",
|
||||
"GO_TO_SETTINGS_TEAMS": "الذهاب إلى إعدادات الفريق",
|
||||
"GO_TO_SETTINGS_INBOXES": "الذهاب إلى إعدادات الصندوق الوارد",
|
||||
"GO_TO_SETTINGS_LABELS": "الذهاب إلى إعدادات الوسم",
|
||||
"GO_TO_SETTINGS_LABELS": "الذهاب إلى إعدادات التسمية",
|
||||
"GO_TO_SETTINGS_CANNED_RESPONSES": "انتقل إلى إعدادات الردود الجاهزة",
|
||||
"GO_TO_SETTINGS_APPLICATIONS": "الذهاب إلى إعدادات التطبيق",
|
||||
"GO_TO_SETTINGS_ACCOUNT": "الذهاب إلى إعدادات الحساب",
|
||||
"GO_TO_SETTINGS_PROFILE": "الذهاب إلى إعدادات الملف الشخصي",
|
||||
"GO_TO_NOTIFICATIONS": "الذهاب إلى الإشعارات",
|
||||
"ADD_LABELS_TO_CONVERSATION": "إضافة وسم إلى المحادثة",
|
||||
"ADD_LABELS_TO_CONVERSATION": "إضافة تسمية إلى المحادثة",
|
||||
"ASSIGN_AN_AGENT": "تعيين وكيل",
|
||||
"AI_ASSIST": "مساعدة AI",
|
||||
"ASSIGN_PRIORITY": "تعيين الأولوية",
|
||||
"ASSIGN_A_TEAM": "تعيين فريق",
|
||||
"MUTE_CONVERSATION": "كتم المحادثة",
|
||||
"UNMUTE_CONVERSATION": "إلغاء كتم المحادثة",
|
||||
"REMOVE_LABEL_FROM_CONVERSATION": "إزالة الوسم من المحادثة",
|
||||
"REMOVE_LABEL_FROM_CONVERSATION": "إزالة التسمية من المحادثة",
|
||||
"REOPEN_CONVERSATION": "إعادة فتح المحادثة",
|
||||
"RESOLVE_CONVERSATION": "حل المحادثة",
|
||||
"SEND_TRANSCRIPT": "إرسال نسخة نصية للبريد الإلكتروني",
|
||||
@@ -160,12 +160,12 @@
|
||||
"CHANGE_APPEARANCE": "تغيير المظهر",
|
||||
"LIGHT_MODE": "فاتح",
|
||||
"DARK_MODE": "مظلم",
|
||||
"SYSTEM_MODE": "النظام",
|
||||
"SYSTEM_MODE": "نظام",
|
||||
"SNOOZE_NOTIFICATION": "تأجيل الإشعارات"
|
||||
}
|
||||
},
|
||||
"DASHBOARD_APPS": {
|
||||
"LOADING_MESSAGE": "جاري جلب تطبيق لوحة التحكم..."
|
||||
"LOADING_MESSAGE": "تحميل تطبيق لوحة التحكم..."
|
||||
},
|
||||
"COMMON": {
|
||||
"OR": "أو",
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
"ARCHIVED": "المقالات المؤرشفة"
|
||||
},
|
||||
"LOCALE_SELECT": {
|
||||
"TITLE": "حدد اللغة",
|
||||
"PLACEHOLDER": "حدد اللغة",
|
||||
"NO_RESULT": "لا توجد لغات",
|
||||
"SEARCH_PLACEHOLDER": "البحث عن اللغة"
|
||||
"TITLE": "Select locale",
|
||||
"PLACEHOLDER": "Select locale",
|
||||
"NO_RESULT": "No locale found",
|
||||
"SEARCH_PLACEHOLDER": "Search locale"
|
||||
}
|
||||
},
|
||||
"EDIT_HEADER": {
|
||||
@@ -39,11 +39,11 @@
|
||||
"IMAGE_UPLOAD": {
|
||||
"TITLE": "رفع صورة",
|
||||
"UPLOADING": "جاري الرفع...",
|
||||
"SUCCESS": "تم رفع الصورة بنجاح",
|
||||
"ERROR": "حدث خطأ أثناء رفع الصورة",
|
||||
"ERROR_FILE_SIZE": "حجم الصورة يجب أن يكون أقل من {size}MB",
|
||||
"ERROR_FILE_FORMAT": "تنسيق الصورة يجب أن يكون jpg أو jpeg أو png",
|
||||
"ERROR_FILE_DIMENSIONS": "ينبغي أن تكون أبعاد الصورة أقل من 2000 × 2000"
|
||||
"SUCCESS": "Image uploaded successfully",
|
||||
"ERROR": "Error while uploading image",
|
||||
"ERROR_FILE_SIZE": "Image size should be less than {size}MB",
|
||||
"ERROR_FILE_FORMAT": "Image format should be jpg, jpeg or png",
|
||||
"ERROR_FILE_DIMENSIONS": "Image dimensions should be less than 2000 x 2000"
|
||||
}
|
||||
},
|
||||
"ARTICLE_SETTINGS": {
|
||||
@@ -149,102 +149,102 @@
|
||||
"NO": "No, keep portal",
|
||||
"API": {
|
||||
"DELETE_SUCCESS": "Portal deleted successfully",
|
||||
"DELETE_ERROR": "حدث خطأ أثناء حذف البوابة"
|
||||
"DELETE_ERROR": "Error while deleting portal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"HEADER_TEXT": "تعديل البوابة",
|
||||
"HEADER_TEXT": "Edit portal",
|
||||
"TABS": {
|
||||
"BASIC_SETTINGS": {
|
||||
"TITLE": "المعلومات الأساسية"
|
||||
"TITLE": "Basic information"
|
||||
},
|
||||
"CUSTOMIZATION_SETTINGS": {
|
||||
"TITLE": "تخصيص البوابة"
|
||||
"TITLE": "Portal customization"
|
||||
},
|
||||
"CATEGORY_SETTINGS": {
|
||||
"TITLE": "الفئات"
|
||||
"TITLE": "Categories"
|
||||
},
|
||||
"LOCALE_SETTINGS": {
|
||||
"TITLE": "اللغات"
|
||||
"TITLE": "Locales"
|
||||
}
|
||||
},
|
||||
"CATEGORIES": {
|
||||
"TITLE": "الفئات في",
|
||||
"NEW_CATEGORY": "فئة جديدة",
|
||||
"TITLE": "Categories in",
|
||||
"NEW_CATEGORY": "New category",
|
||||
"TABLE": {
|
||||
"NAME": "الاسم",
|
||||
"DESCRIPTION": "الوصف",
|
||||
"LOCALE": "اللغة",
|
||||
"ARTICLE_COUNT": "عدد المقالات",
|
||||
"LOCALE": "Locale",
|
||||
"ARTICLE_COUNT": "No. of articles",
|
||||
"ACTION_BUTTON": {
|
||||
"EDIT": "تعديل الفئة",
|
||||
"DELETE": "حذف الفئة"
|
||||
"EDIT": "Edit category",
|
||||
"DELETE": "Delete category"
|
||||
},
|
||||
"EMPTY_TEXT": "لم يتم العثور على الفئات"
|
||||
"EMPTY_TEXT": "لم يتم العثور على فئات"
|
||||
}
|
||||
},
|
||||
"EDIT_BASIC_INFO": {
|
||||
"BUTTON_TEXT": "تحديث الإعدادات الأساسية"
|
||||
"BUTTON_TEXT": "Update basic settings"
|
||||
}
|
||||
},
|
||||
"ADD": {
|
||||
"CREATE_FLOW": [
|
||||
{
|
||||
"title": "معلومات مركز المساعدة",
|
||||
"title": "Help center information",
|
||||
"route": "new_portal_information",
|
||||
"body": "معلومات أساسية عن البوابة",
|
||||
"CREATE_BASIC_SETTING_BUTTON": "إنشاء إعدادات البوابة الأساسية"
|
||||
"body": "Basic information about portal",
|
||||
"CREATE_BASIC_SETTING_BUTTON": "Create portal basic settings"
|
||||
},
|
||||
{
|
||||
"title": "تخصيص مركز المساعدة",
|
||||
"title": "Help center customization",
|
||||
"route": "portal_customization",
|
||||
"body": "تخصيص البوابة",
|
||||
"UPDATE_PORTAL_BUTTON": "تحديث إعدادات البوابة"
|
||||
"body": "Customize portal",
|
||||
"UPDATE_PORTAL_BUTTON": "Update portal settings"
|
||||
},
|
||||
{
|
||||
"title": "تم! 🎉",
|
||||
"title": "Voila! 🎉",
|
||||
"route": "portal_finish",
|
||||
"body": "أنت جاهز!",
|
||||
"body": "You're all set!",
|
||||
"FINISH": "إنهاء"
|
||||
}
|
||||
],
|
||||
"CREATE_FLOW_PAGE": {
|
||||
"BACK_BUTTON": "العودة",
|
||||
"BASIC_SETTINGS_PAGE": {
|
||||
"HEADER": "إنشاء بوابة",
|
||||
"TITLE": "معلومات مركز المساعدة",
|
||||
"CREATE_BASIC_SETTING_BUTTON": "إنشاء إعدادات البوابة الأساسية"
|
||||
"HEADER": "Create Portal",
|
||||
"TITLE": "Help center information",
|
||||
"CREATE_BASIC_SETTING_BUTTON": "Create portal basic settings"
|
||||
},
|
||||
"CUSTOMIZATION_PAGE": {
|
||||
"HEADER": "تخصيص البوابة",
|
||||
"TITLE": "تخصيص مركز المساعدة",
|
||||
"UPDATE_PORTAL_BUTTON": "تحديث إعدادات البوابة"
|
||||
"HEADER": "Portal customisation",
|
||||
"TITLE": "Help center customization",
|
||||
"UPDATE_PORTAL_BUTTON": "Update portal settings"
|
||||
},
|
||||
"FINISH_PAGE": {
|
||||
"TITLE": "تم!🎉 أنت جاهز!",
|
||||
"MESSAGE": "يمكنك الآن رؤية هذه البوابة في صفحة جميع البوابات.",
|
||||
"FINISH": "الذهاب إلى صفحة جميع البوابات"
|
||||
"TITLE": "Voila!🎉 You're all set up!",
|
||||
"MESSAGE": "You can now see this created portal on your all portals page.",
|
||||
"FINISH": "Go to all portals page"
|
||||
}
|
||||
},
|
||||
"LOGO": {
|
||||
"LABEL": "الشعار",
|
||||
"UPLOAD_BUTTON": "رفع الشعار",
|
||||
"HELP_TEXT": "سيتم عرض هذا الشعار على رأس البوابة.",
|
||||
"IMAGE_UPLOAD_SUCCESS": "تم رفع الشعار بنجاح",
|
||||
"IMAGE_UPLOAD_ERROR": "تم حذف الشعار بنجاح",
|
||||
"IMAGE_DELETE_ERROR": "حدث خطأ أثناء حذف الشعار"
|
||||
"LABEL": "Logo",
|
||||
"UPLOAD_BUTTON": "Upload logo",
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header.",
|
||||
"IMAGE_UPLOAD_SUCCESS": "Logo uploaded successfully",
|
||||
"IMAGE_UPLOAD_ERROR": "Logo deleted successfully",
|
||||
"IMAGE_DELETE_ERROR": "Error while deleting logo"
|
||||
},
|
||||
"NAME": {
|
||||
"LABEL": "الاسم",
|
||||
"PLACEHOLDER": "اسم البوابة",
|
||||
"HELP_TEXT": "الاسم سيتم مشاهدتة من جميع زوار الصفحة.",
|
||||
"PLACEHOLDER": "Portal name",
|
||||
"HELP_TEXT": "الاسم سيتم مشاهدتة من جميع من جميع زوار الصفحة.",
|
||||
"ERROR": "الاسم مطلوب"
|
||||
},
|
||||
"SLUG": {
|
||||
"LABEL": "الإسم المختصر",
|
||||
"PLACEHOLDER": "الإسم المختصر لرابط البوابة",
|
||||
"ERROR": "الإسم المختصر مطلوب"
|
||||
"LABEL": "وصف مختصر",
|
||||
"PLACEHOLDER": "وصف مختصر لرابط البوابة",
|
||||
"ERROR": "الوصف مطلوب"
|
||||
},
|
||||
"DOMAIN": {
|
||||
"LABEL": "نطاق مخصص",
|
||||
@@ -352,7 +352,7 @@
|
||||
"MODAL": {
|
||||
"CONFIRM": {
|
||||
"TITLE": "تأكيد الحذف",
|
||||
"MESSAGE": "هل أنت متأكد من حذف المقالة؟",
|
||||
"MESSAGE": "Are you sure to delete the article?",
|
||||
"YES": "نعم، احذف",
|
||||
"NO": "لا، احتفظ به"
|
||||
}
|
||||
@@ -481,7 +481,6 @@
|
||||
"DESCRIPTION": "Use the portal as a headless CMS with third party front-end frameworks using our APIs."
|
||||
}
|
||||
}
|
||||
},
|
||||
"LOADING": "Loading..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"INBOX": {
|
||||
"LIST": {
|
||||
"TITLE": "الصندوق الوارد",
|
||||
"TITLE": "صندوق الوارد",
|
||||
"DISPLAY_DROPDOWN": "عرض",
|
||||
"LOADING": "جار جلب الإشعارات",
|
||||
"LOADING": "جارٍ جلب الإشعارات",
|
||||
"404": "لا توجد إشعارات نشطة في هذه المجموعة.",
|
||||
"NO_NOTIFICATIONS": "لا توجد إشعارات",
|
||||
"NOTE": "الإشعارات من جميع صناديق الوارد المشترك بها",
|
||||
"NO_MESSAGES_AVAILABLE": "عذرًا! لا يمكن جلب الرسائل",
|
||||
"SNOOZED_UNTIL": "تأجيل حتى",
|
||||
"SNOOZED_UNTIL_TOMORROW": "تأجيل حتى الغد",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "تأجيل حتى الأسبوع القادم"
|
||||
"SNOOZED_UNTIL": "غفوة حتى",
|
||||
"SNOOZED_UNTIL_TOMORROW": "غفوة حتى الغد",
|
||||
"SNOOZED_UNTIL_NEXT_WEEK": "غفوة حتى الأسبوع القادم"
|
||||
},
|
||||
"ACTION_HEADER": {
|
||||
"SNOOZE": "تأجيل الإشعار",
|
||||
"SNOOZE": "غفوة الإشعار",
|
||||
"DELETE": "حذف الإشعار",
|
||||
"BACK": "العودة"
|
||||
},
|
||||
@@ -28,9 +28,9 @@
|
||||
"SLA_MISSED_RESOLUTION": "تم تجاوز الهدف النهائي للحل للمحادثة"
|
||||
},
|
||||
"MENU_ITEM": {
|
||||
"MARK_AS_READ": "تحديد كمقروء",
|
||||
"MARK_AS_UNREAD": "تحديد كغير مقروء",
|
||||
"SNOOZE": "تأجيل",
|
||||
"MARK_AS_READ": "وضع علامة كمقروء",
|
||||
"MARK_AS_UNREAD": "وضع علامة كغير مقروء",
|
||||
"SNOOZE": "غفوة",
|
||||
"DELETE": "حذف",
|
||||
"MARK_ALL_READ": "تحديد الكل كمقروء",
|
||||
"DELETE_ALL": "حذف الكل",
|
||||
@@ -45,7 +45,7 @@
|
||||
"PRIORITY": "الأولوية"
|
||||
},
|
||||
"DISPLAY_OPTIONS": {
|
||||
"SNOOZED": "مؤجل",
|
||||
"SNOOZED": "غفوة",
|
||||
"READ": "قراءة",
|
||||
"LABELS": "الوسوم",
|
||||
"CONVERSATION_ID": "معرف المحادثة"
|
||||
@@ -56,7 +56,7 @@
|
||||
"MARK_AS_UNREAD": "تم وضع علامة الإشعار كغير مقروء",
|
||||
"SNOOZE": "تم تأجيل الإشعار",
|
||||
"DELETE": "تم حذف الإشعار",
|
||||
"MARK_ALL_READ": "تم تحديد جميع الإشعارات كمقروءة",
|
||||
"MARK_ALL_READ": "تم وضع علامة كل الإشعارات كمقروء",
|
||||
"DELETE_ALL": "تم حذف كل الإشعارات",
|
||||
"DELETE_ALL_READ": "تم حذف كل الإشعارات المقروءة"
|
||||
}
|
||||
|
||||
@@ -439,7 +439,7 @@
|
||||
"DISABLED": "معطّل"
|
||||
},
|
||||
"ENABLE_HMAC": {
|
||||
"LABEL": "تفعيل"
|
||||
"LABEL": "تمكين"
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
@@ -642,7 +642,7 @@
|
||||
"PLACE_HOLDER": "كلمة المرور"
|
||||
},
|
||||
"DOMAIN": {
|
||||
"LABEL": "النطاق",
|
||||
"LABEL": "الدومين",
|
||||
"PLACE_HOLDER": "الدومين"
|
||||
},
|
||||
"ENCRYPTION": "التشفير",
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
"DESCRIPTION": "Chatwoot تتكامل مع أدوات وخدمات متعددة لتحسين كفاءة فريقك. استكشف القائمة أدناه لتكوين تطبيقاتك المفضلة.",
|
||||
"LEARN_MORE": "معرفة المزيد عن التكاملات",
|
||||
"LOADING": "جاري جلب التكاملات",
|
||||
"CAPTAIN": {
|
||||
"DISABLED": "لم يتم تمكين الكابتن على حسابك.",
|
||||
"CLICK_HERE_TO_CONFIGURE": "انقر هنا للتهيئة",
|
||||
"LOADING_CONSOLE": "جار جلب وحدة التحكم بالكابتن...",
|
||||
"FAILED_TO_LOAD_CONSOLE": "فشل أثناء جلب وحدة تحكم الكابتن. الرجاء التحديث والمحاولة مرة أخرى."
|
||||
},
|
||||
"WEBHOOK": {
|
||||
"SUBSCRIBED_EVENTS": "الأحداث المشتركة",
|
||||
"FORM": {
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
"HEADER": "الوسوم",
|
||||
"HEADER_BTN_TXT": "إضافة وسم جديد",
|
||||
"LOADING": "جار جلب الوسوم",
|
||||
"DESCRIPTION": "Labels help you categorize and prioritize conversations and leads. You can assign a label to a conversation or contact using the side panel.",
|
||||
"LEARN_MORE": "Learn more about labels",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام",
|
||||
"SIDEBAR_TXT": "<p><b>الوسوم</b> <p>تساعدك الوسو على تصنيف المحادثات وإعطائها الأولوية. يمكنك تعيين وسم إلى محادثة من القائمة الجانبية. <br /><br />الوسوم مرتبطة بالحساب ويمكن استخدامها لإنشاء سير عمل مخصص في مؤسستك. يمكنك تعيين لون مخصص للوسم، مما يسهل التعرف على الوسم. ستتمكن من عرض الوسم على الشريط الجانبي لتصفية المحادثات بسهولة.</p>",
|
||||
"LIST": {
|
||||
"404": "لا توجد وسوم متوفرة في هذا الحساب.",
|
||||
"404": "لا يوجد وسوم متوفرة في هذا الحساب.",
|
||||
"TITLE": "إدارة الوسوم",
|
||||
"DESC": "الوسوم تسمح لك بتجميع المحادثات المتشابهة معاً.",
|
||||
"TABLE_HEADER": [
|
||||
@@ -20,8 +19,8 @@
|
||||
"NAME": {
|
||||
"LABEL": "اسم الوسم",
|
||||
"PLACEHOLDER": "اسم الوسم",
|
||||
"REQUIRED_ERROR": "اسم الوسم مطلوب",
|
||||
"MINIMUM_LENGTH_ERROR": "الحد الأدنى لطول الإسم هو حرفين",
|
||||
"REQUIRED_ERROR": "اسم التسمية مطلوب",
|
||||
"MINIMUM_LENGTH_ERROR": "الحد الأدنى للطول 2 مطلوب",
|
||||
"VALID_ERROR": "مسموح فقط بالابجدية,الارقام, -, _"
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
@@ -41,17 +40,16 @@
|
||||
},
|
||||
"SUGGESTIONS": {
|
||||
"TOOLTIP": {
|
||||
"SINGLE_SUGGESTION": "إضافة وسم إلى المحادثة",
|
||||
"MULTIPLE_SUGGESTION": "حدد الوسم",
|
||||
"DESELECT": "إلغاء تحديد الوسم",
|
||||
"SINGLE_SUGGESTION": "إضافة تسمية إلى المحادثة",
|
||||
"MULTIPLE_SUGGESTION": "حدد التسمية",
|
||||
"DESELECT": "إلغاء تحديد التسمية",
|
||||
"DISMISS": "استبعاد الاقتراح"
|
||||
},
|
||||
"POWERED_BY": "Chatwoot AI",
|
||||
"DISMISS": "استبعاد",
|
||||
"ADD_SELECTED_LABELS": "إضافة الوسوم المحددة",
|
||||
"ADD_SELECTED_LABEL": "إضافة الوسوم المحددة",
|
||||
"ADD_ALL_LABELS": "إضافة جميع الأوسمة",
|
||||
"SUGGESTED_LABELS": "Suggested labels"
|
||||
"DISMISS": "تجاهل",
|
||||
"ADD_SELECTED_LABELS": "إضافة التسميات المحددة",
|
||||
"ADD_SELECTED_LABEL": "إضافة التسمية المحددة",
|
||||
"ADD_ALL_LABELS": "إضافة جميع التسميات"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "إضافة وسم جديد",
|
||||
|
||||
@@ -73,15 +73,6 @@
|
||||
"BUTTON_TOOLTIP": "تنفيذ",
|
||||
"PREVIEW": "معاينة الماكرو",
|
||||
"EXECUTED_SUCCESSFULLY": "تم تنفيذ الماكرو بنجاح"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "مفتاح الخاصية مطلوب",
|
||||
"FILTER_OPERATOR_REQUIRED": "عامل التصفية مطلوب",
|
||||
"VALUE_REQUIRED": "القيمة مطلوبة",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "القيمة يجب أن تكون بين 1 و 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "معلمات الإجراء مطلوبة",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "شرط واحد على الأقل مطلوب",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "إجراء واحد على الأقل مطلوب"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,8 +481,7 @@
|
||||
"HEADER": "Conversation Traffic",
|
||||
"NO_CONVERSATIONS": "No conversations",
|
||||
"CONVERSATION": "%{count} conversation",
|
||||
"CONVERSATIONS": "%{count} conversations",
|
||||
"DOWNLOAD_REPORT": "Download report"
|
||||
"CONVERSATIONS": "%{count} conversations"
|
||||
},
|
||||
"AGENT_CONVERSATIONS": {
|
||||
"HEADER": "المحادثات من قبل الوكلاء",
|
||||
@@ -537,7 +536,6 @@
|
||||
"LABELS": "الوسم",
|
||||
"TEAMS": "الفريق"
|
||||
},
|
||||
"WITH": "with",
|
||||
"METRICS": {
|
||||
"HIT_RATE": {
|
||||
"LABEL": "Hit Rate",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"CONVERSATIONS": "المحادثات",
|
||||
"MESSAGES": "الرسائل"
|
||||
},
|
||||
"SEARCHING_DATA": "جاري البحث",
|
||||
"EMPTY_STATE": "لم يتم العثور على %{item} للطلب '%{query}'",
|
||||
"EMPTY_STATE_FULL": "لم يتم العثور على نتائج للطلب '%{query}'",
|
||||
"PLACEHOLDER_KEYBINDING": "/ للتركيز",
|
||||
|
||||
@@ -239,7 +239,6 @@
|
||||
"REPORTS": "التقارير",
|
||||
"SETTINGS": "الإعدادات",
|
||||
"CONTACTS": "جهات الاتصال",
|
||||
"CAPTAIN": "قائد",
|
||||
"HOME": "الرئيسية",
|
||||
"AGENTS": "وكيل الدعم",
|
||||
"AGENT_BOTS": "الروبوتات",
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
"TEAMS_SETTINGS": {
|
||||
"NEW_TEAM": "إنشاء فريق جديد",
|
||||
"HEADER": "الفرق",
|
||||
"LOADING": "Fetching teams",
|
||||
"DESCRIPTION": "Teams allow you to organize agents into groups based on their responsibilities. An agent can belong to multiple teams. When working collaboratively, you can assign conversations to specific teams.",
|
||||
"LEARN_MORE": "Learn more about teams",
|
||||
"SIDEBAR_TXT": "<p><b>الفريق</b></p> <p>الفرق تسمح لك بتنظيم عملائك في مجموعات على أساس مسؤولياتهم. <br /> يمكن للمستخدم أن يكون جزءا من فرق متعددة. يمكنك تعيين محادثات مع فريق عندما تعمل بشكل تعاوني. </p>",
|
||||
"LIST": {
|
||||
"404": "لا يوجد موظفي دعم مرتبطين بهذا الحساب.",
|
||||
"EDIT_TEAM": "تعديل الفريق",
|
||||
"NONE": "لا شيء"
|
||||
"EDIT_TEAM": "تعديل الفريق"
|
||||
},
|
||||
"CREATE_FLOW": {
|
||||
"CREATE": {
|
||||
@@ -100,7 +97,7 @@
|
||||
"ERROR_MESSAGE": "تعذر حذف الفريق. حاول مرة أخرى."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Are you sure you want to delete the team?",
|
||||
"TITLE": "هل أنت متأكد من أنك تريد حذف - %{teamName}",
|
||||
"PLACE_HOLDER": "الرجاء كتابة {teamName} للتأكيد",
|
||||
"MESSAGE": "سيؤدي حذف الفريق إلى إزالة مهمة الفريق من المحادثات التي تم تعيينها لهذا الفريق.",
|
||||
"YES": "حذف ",
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"AND": "И",
|
||||
"OR": "ИЛИ"
|
||||
},
|
||||
"INPUT_PLACEHOLDER": "Enter value",
|
||||
"OPERATOR_LABELS": {
|
||||
"equal_to": "Равно на",
|
||||
"not_equal_to": "Различно от",
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
"HEADER": "Агенти",
|
||||
"HEADER_BTN_TXT": "Добави агент",
|
||||
"LOADING": "Извличане на списък с агенти",
|
||||
"DESCRIPTION": "An agent is a member of your customer support team who can view and respond to user messages. The list below shows all the agents in your account.",
|
||||
"LEARN_MORE": "Learn about user roles",
|
||||
"SIDEBAR_TXT": "<p><b>Агенти</b></p> <p> <b>Агент</b> е член на вашия екип за поддръжка на клиенти. </p><p> Агентите ще могат да преглеждат и отговарят на съобщения от вашите потребители. Списъкът показва всички агенти във вашия акаунт. </p><p> Щракнете върху <b>Добавяне на агент</b>, за да добавите нов агент. Агентът, който добавите, ще получи имейл с връзка за потвърждение, за да активира акаунта си, след което те ще имат достъп до Chatwoot и ще могат да отговарят на съобщения. </p><p> Достъпът до функциите на Chatwoot се основава на следните роли. </p><p> <b>Агент</b> – Агентите с тази роля имат достъп само до входящи кутии, отчети и разговори. Те могат да присвояват разговори на други агенти или на себе си и да ги разрешават.</p><p> <b>Администратор</b> - Администраторът ще има достъп до всички функции на Chatwoot, активирани за вашия акаунт, включително настройки, заедно с всички нормални привилегии на агентите.</p>",
|
||||
"AGENT_TYPES": {
|
||||
"ADMINISTRATOR": "Администратор",
|
||||
"AGENT": "Агент"
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
"HEADER": "Audit Logs",
|
||||
"HEADER_BTN_TXT": "Add Audit Logs",
|
||||
"LOADING": "Fetching Audit Logs",
|
||||
"DESCRIPTION": "Audit Logs maintain a record of activities in your account, allowing you to track and audit your account, team, or services.",
|
||||
"LEARN_MORE": "Learn more about audit logs",
|
||||
"SEARCH_404": "Няма резултати отговарящи на тази заявка",
|
||||
"SIDEBAR_TXT": "<p><b>Audit Logs</b> </p><p> Audit Logs are trails for events and actions in a Chatwoot System. </p>",
|
||||
"LIST": {
|
||||
@@ -31,8 +29,7 @@
|
||||
"ADD": "%{agentName} invited %{invitee} to the account as an %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} changed their %{attributes} to %{values}",
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}",
|
||||
"DELETED": "%{agentName} changed %{attributes} of a deleted user to %{values}"
|
||||
"OTHER": "%{agentName} changed %{attributes} of %{user} to %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
|
||||
@@ -93,9 +93,7 @@
|
||||
"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",
|
||||
"EMAIL_INPUT_PLACEHOLDER": "Enter email",
|
||||
"URL_INPUT_PLACEHOLDER": "Enter URL"
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Select teams"
|
||||
},
|
||||
"TOGGLE": {
|
||||
"ACTIVATION_TITLE": "Activate Automation Rule",
|
||||
@@ -115,15 +113,6 @@
|
||||
"LABEL_UPLOADING": "Качване...",
|
||||
"LABEL_UPLOADED": "Successfully Uploaded",
|
||||
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||
"VALUE_REQUIRED": "Изисква се стойност",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_LABEL": "Assign",
|
||||
"YES": "Yes",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "Търсене",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Готови отговори",
|
||||
"LEARN_MORE": "Learn more about canned responses",
|
||||
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"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>",
|
||||
"LIST": {
|
||||
"404": "Няма налични готови отговори в този акаунт.",
|
||||
"TITLE": "Управлявайте готовите отговори",
|
||||
|
||||
@@ -381,9 +381,6 @@
|
||||
},
|
||||
"SUCCESS_MESSAGE": "Успешно обединяване на контакта",
|
||||
"ERROR_MESSAGE": "Контактите не бяха обединени, опитайте отново!"
|
||||
},
|
||||
"DROPDOWN_ITEM": {
|
||||
"ID": "(ID: {identifier})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
"MSG_INPUT": "Shift + enter for new line. Start with '/' to select a Canned Response.",
|
||||
"PRIVATE_MSG_INPUT": "Shift + enter for new line. This will be visible only to Agents",
|
||||
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
|
||||
"CLICK_HERE": "Click here to update",
|
||||
"WHATSAPP_TEMPLATES": "Whatsapp Templates"
|
||||
"CLICK_HERE": "Click here to update"
|
||||
},
|
||||
"REPLYBOX": {
|
||||
"REPLY": "Reply",
|
||||
@@ -241,29 +240,25 @@
|
||||
"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.",
|
||||
"GREETING_MORNING": "👋 Good morning, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_AFTERNOON": "👋 Good afternoon, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_EVENING": "👋 Good evening, %{name}. Welcome to %{installationName}.",
|
||||
"READ_LATEST_UPDATES": "Read our latest updates",
|
||||
"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.",
|
||||
"NEW_LINK": "Click here to create an inbox"
|
||||
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status."
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"INBOXES": {
|
||||
"TITLE": "Connect Inboxes",
|
||||
"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"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"CANNED_RESPONSES": {
|
||||
"TITLE": "Create canned responses",
|
||||
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
|
||||
"NEW_LINK": "Click here to create a canned response"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_SIDEBAR": {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"GENERAL": {
|
||||
"SHOWING_RESULTS": "Showing {firstIndex}-{lastIndex} of {totalCount} items",
|
||||
"PHONE_INPUT": {
|
||||
"PLACEHOLDER": "Търсене",
|
||||
"EMPTY_STATE": "Няма намерени резултати"
|
||||
}
|
||||
"SHOWING_RESULTS": "Showing {firstIndex}-{lastIndex} of {totalCount} items"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +481,6 @@
|
||||
"DESCRIPTION": "Use the portal as a headless CMS with third party front-end frameworks using our APIs."
|
||||
}
|
||||
}
|
||||
},
|
||||
"LOADING": "Loading..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
"DESCRIPTION": "Chatwoot integrates with multiple tools and services to improve your team's efficiency. Explore the list below to configure your favorite apps.",
|
||||
"LEARN_MORE": "Learn more about integrations",
|
||||
"LOADING": "Fetching integrations",
|
||||
"CAPTAIN": {
|
||||
"DISABLED": "Captain is not enabled on your account.",
|
||||
"CLICK_HERE_TO_CONFIGURE": "Click here to configure",
|
||||
"LOADING_CONSOLE": "Loading Captain Console...",
|
||||
"FAILED_TO_LOAD_CONSOLE": "Failed to load Captain Console. Please refresh and try again."
|
||||
},
|
||||
"WEBHOOK": {
|
||||
"SUBSCRIBED_EVENTS": "Subscribed Events",
|
||||
"FORM": {
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
"HEADER": "Labels",
|
||||
"HEADER_BTN_TXT": "Add label",
|
||||
"LOADING": "Fetching labels",
|
||||
"DESCRIPTION": "Labels help you categorize and prioritize conversations and leads. You can assign a label to a conversation or contact using the side panel.",
|
||||
"LEARN_MORE": "Learn more about labels",
|
||||
"SEARCH_404": "Няма резултати отговарящи на тази заявка",
|
||||
"SIDEBAR_TXT": "<p><b>Labels</b> <p>Labels help you to categorize conversations and prioritize them. You can assign label to a conversation from the sidepanel. <br /><br />Labels are tied to the account and can be used to create custom workflows in your organization. You can assign custom color to a label, it makes it easier to identify the label. You will be able to display the label on the sidebar to filter the conversations easily.</p>",
|
||||
"LIST": {
|
||||
"404": "There are no labels available in this account.",
|
||||
"TITLE": "Manage labels",
|
||||
@@ -50,8 +49,7 @@
|
||||
"DISMISS": "Dismiss",
|
||||
"ADD_SELECTED_LABELS": "Add selected labels",
|
||||
"ADD_SELECTED_LABEL": "Add selected label",
|
||||
"ADD_ALL_LABELS": "Add all labels",
|
||||
"SUGGESTED_LABELS": "Suggested labels"
|
||||
"ADD_ALL_LABELS": "Add all labels"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Add label",
|
||||
|
||||
@@ -73,15 +73,6 @@
|
||||
"BUTTON_TOOLTIP": "Execute",
|
||||
"PREVIEW": "Preview Macro",
|
||||
"EXECUTED_SUCCESSFULLY": "Macro executed successfully"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||
"VALUE_REQUIRED": "Изисква се стойност",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,8 +481,7 @@
|
||||
"HEADER": "Conversation Traffic",
|
||||
"NO_CONVERSATIONS": "No conversations",
|
||||
"CONVERSATION": "%{count} conversation",
|
||||
"CONVERSATIONS": "%{count} conversations",
|
||||
"DOWNLOAD_REPORT": "Download report"
|
||||
"CONVERSATIONS": "%{count} conversations"
|
||||
},
|
||||
"AGENT_CONVERSATIONS": {
|
||||
"HEADER": "Conversations by agents",
|
||||
@@ -537,7 +536,6 @@
|
||||
"LABELS": "Label",
|
||||
"TEAMS": "Team"
|
||||
},
|
||||
"WITH": "with",
|
||||
"METRICS": {
|
||||
"HIT_RATE": {
|
||||
"LABEL": "Hit Rate",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"CONVERSATIONS": "Разговори",
|
||||
"MESSAGES": "Messages"
|
||||
},
|
||||
"SEARCHING_DATA": "Searching",
|
||||
"EMPTY_STATE": "No %{item} found for query '%{query}'",
|
||||
"EMPTY_STATE_FULL": "No results found for query '%{query}'",
|
||||
"PLACEHOLDER_KEYBINDING": "/ to focus",
|
||||
|
||||
@@ -239,7 +239,6 @@
|
||||
"REPORTS": "Reports",
|
||||
"SETTINGS": "Settings",
|
||||
"CONTACTS": "Контакти",
|
||||
"CAPTAIN": "Captain",
|
||||
"HOME": "Home",
|
||||
"AGENTS": "Агенти",
|
||||
"AGENT_BOTS": "Bots",
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
"TEAMS_SETTINGS": {
|
||||
"NEW_TEAM": "Create new team",
|
||||
"HEADER": "Teams",
|
||||
"LOADING": "Fetching teams",
|
||||
"DESCRIPTION": "Teams allow you to organize agents into groups based on their responsibilities. An agent can belong to multiple teams. When working collaboratively, you can assign conversations to specific teams.",
|
||||
"LEARN_MORE": "Learn more about teams",
|
||||
"SIDEBAR_TXT": "<p><b>Teams</b></p> <p>Teams let you organize your agents into groups based on their responsibilities. <br /> An agent can be part of multiple teams. You can assign conversations to a team when you are working collaboratively. </p>",
|
||||
"LIST": {
|
||||
"404": "There are no teams created on this account.",
|
||||
"EDIT_TEAM": "Edit team",
|
||||
"NONE": "Нито един"
|
||||
"EDIT_TEAM": "Edit team"
|
||||
},
|
||||
"CREATE_FLOW": {
|
||||
"CREATE": {
|
||||
@@ -100,7 +97,7 @@
|
||||
"ERROR_MESSAGE": "Couldn't delete the team. Try again."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Are you sure you want to delete the team?",
|
||||
"TITLE": "Are you sure want to delete - %{teamName}",
|
||||
"PLACE_HOLDER": "Please type {teamName} to confirm",
|
||||
"MESSAGE": "Deleting the team will remove the team assignment from the conversations assigned to this team.",
|
||||
"YES": "Delete ",
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"AND": "I",
|
||||
"OR": "O"
|
||||
},
|
||||
"INPUT_PLACEHOLDER": "Enter value",
|
||||
"OPERATOR_LABELS": {
|
||||
"equal_to": "Igual a",
|
||||
"not_equal_to": "No és igual a",
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
"HEADER": "Agents",
|
||||
"HEADER_BTN_TXT": "Afegir Agent",
|
||||
"LOADING": "S'està recollint la llista d'agents",
|
||||
"DESCRIPTION": "An agent is a member of your customer support team who can view and respond to user messages. The list below shows all the agents in your account.",
|
||||
"LEARN_MORE": "Learn about user roles",
|
||||
"SIDEBAR_TXT": "<p><b>Agents</b></p> <p> Un <b>Agent</b> és membre del vostre equip d’atenció al client. </p><p> Els agents podran veure i respondre missatges dels teus usuaris. La llista mostra tots els agents que hi ha actualment al teu compte.</p><p> Fer clic a <b>Afegeix Agent</b> per afegir un agent nou. L´agent que afegeixes rebrà un correu electrònic amb un enllaç de confirmació per activar el seu compte, després del qual podrà accedir a Chatwoot i respondre als missatges. </p><p> L´accés a les funcions de Chatwoot es basa en els següents rols.</p><p> <b>Agent</b> - Els agents amb aquesta funció només poden accedir a les bústies d´entrada, als informes i a les converses. Poden assignar converses a altres agents o a ells mateixos i resoldre converses.</p><p> <b>Administrador</b> - L´administrador tindrà accés a totes les funcions de Chatwoot habilitades per al teu compte, inclosa la configuració, juntament amb tots els privilegis dels agents normals.</p>",
|
||||
"AGENT_TYPES": {
|
||||
"ADMINISTRATOR": "Administrador/a",
|
||||
"AGENT": "Agent"
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
"HEADER": "Registres d'auditoria",
|
||||
"HEADER_BTN_TXT": "Afegeix registres d'auditoria",
|
||||
"LOADING": "S'estan recollint registres d'auditoria",
|
||||
"DESCRIPTION": "Audit Logs maintain a record of activities in your account, allowing you to track and audit your account, team, or services.",
|
||||
"LEARN_MORE": "Learn more about audit logs",
|
||||
"SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta",
|
||||
"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": {
|
||||
@@ -31,8 +29,7 @@
|
||||
"ADD": "%{agentName} ha convidat %{invitee} al compte com a %{role}",
|
||||
"EDIT": {
|
||||
"SELF": "%{agentName} ha canviat els seus %{attributes} a %{values}",
|
||||
"OTHER": "%{agentName} ha canviat %{attributes} de %{user} a %{values}",
|
||||
"DELETED": "%{agentName} changed %{attributes} of a deleted user to %{values}"
|
||||
"OTHER": "%{agentName} ha canviat %{attributes} de %{user} a %{values}"
|
||||
}
|
||||
},
|
||||
"INBOX": {
|
||||
|
||||
@@ -93,9 +93,7 @@
|
||||
"ACTION": {
|
||||
"DELETE_MESSAGE": "Necessites almenys una acció per desar",
|
||||
"TEAM_MESSAGE_INPUT_PLACEHOLDER": "Introdueix el teu missatge aquí",
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Selecciona els equips",
|
||||
"EMAIL_INPUT_PLACEHOLDER": "Enter email",
|
||||
"URL_INPUT_PLACEHOLDER": "Enter URL"
|
||||
"TEAM_DROPDOWN_PLACEHOLDER": "Selecciona els equips"
|
||||
},
|
||||
"TOGGLE": {
|
||||
"ACTIVATION_TITLE": "Activa la regla d'automatització",
|
||||
@@ -115,15 +113,6 @@
|
||||
"LABEL_UPLOADING": "S'està carregant...",
|
||||
"LABEL_UPLOADED": "S'ha pujat correctament",
|
||||
"LABEL_UPLOAD_FAILED": "Ha fallat la pujada"
|
||||
},
|
||||
"ERRORS": {
|
||||
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||
"VALUE_REQUIRED": "El valor és necessari",
|
||||
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"GO_BACK_LABEL": "Torna",
|
||||
"ASSIGN_LABEL": "Assignar",
|
||||
"YES": "Si",
|
||||
"SEARCH_INPUT_PLACEHOLDER": "Cercar",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assigna un agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assigna un equip",
|
||||
"ASSIGN_SUCCESFUL": "Les converses s'han assignat correctament.",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Respostes predeterminades",
|
||||
"LEARN_MORE": "Learn more about canned responses",
|
||||
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
|
||||
"HEADER_BTN_TXT": "Afegir resposta predeterminada",
|
||||
"LOADING": "S'estan recollint les respostes predeterminades...",
|
||||
"SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta.",
|
||||
"SIDEBAR_TXT": "<p><b>Respostes predeterminades</b> </p><p> Les respostes predeterminades són plantilles de respostes escrites prèviament que us ajuden a respondre ràpidament a una conversa. Per inserir una resposta predefinida durant un xat, els agents poden escriure un codi curt precedit d'un caràcter '/'. </p><p> Pots gestionar les teves respostes predefinides des d'aquesta pàgina o crear-ne de noves mitjançant el botó \"Afegeix una resposta predefinida\".</p><p>Obre el <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\">Manual de respostes llaunes</a> en una altra pestanya per ajudar-te.</p><p>També, fes una ullada al nou <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank \">Biblioteca de respostes predeterminades</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "No hi ha respostes predeterminades disponibles en aquest compte.",
|
||||
"TITLE": "Gestiona les respostes predeterminades",
|
||||
|
||||
@@ -381,9 +381,6 @@
|
||||
},
|
||||
"SUCCESS_MESSAGE": "Contacte fusionat correctament",
|
||||
"ERROR_MESSAGE": "No s'ha pogut fusionar els contactes, torna-ho a provar!"
|
||||
},
|
||||
"DROPDOWN_ITEM": {
|
||||
"ID": "(ID: {identifier})"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
"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": "La signatura del missatge no està configurada, configura-la a la configuració del perfil.",
|
||||
"CLICK_HERE": "Fes clic aquí per actualitzar",
|
||||
"WHATSAPP_TEMPLATES": "Plantilles de Whatsapp"
|
||||
"CLICK_HERE": "Fes clic aquí per actualitzar"
|
||||
},
|
||||
"REPLYBOX": {
|
||||
"REPLY": "Respon",
|
||||
@@ -241,29 +240,25 @@
|
||||
"ONBOARDING": {
|
||||
"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.",
|
||||
"GREETING_MORNING": "👋 Good morning, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_AFTERNOON": "👋 Good afternoon, %{name}. Welcome to %{installationName}.",
|
||||
"GREETING_EVENING": "👋 Good evening, %{name}. Welcome to %{installationName}.",
|
||||
"READ_LATEST_UPDATES": "Llegiu les nostres últimes actualitzacions",
|
||||
"ALL_CONVERSATION": {
|
||||
"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.",
|
||||
"NEW_LINK": "Fes clic aquí per crear una safata d'entrada"
|
||||
"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": "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": "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": "Fes clic aquí per crear una safata d'entrada"
|
||||
},
|
||||
"LABELS": {
|
||||
"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"
|
||||
},
|
||||
"CANNED_RESPONSES": {
|
||||
"TITLE": "Create canned responses",
|
||||
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
|
||||
"NEW_LINK": "Click here to create a canned response"
|
||||
}
|
||||
},
|
||||
"CONVERSATION_SIDEBAR": {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"GENERAL": {
|
||||
"SHOWING_RESULTS": "Es mostren {firstIndex}-{lastIndex} de {totalCount} elements",
|
||||
"PHONE_INPUT": {
|
||||
"PLACEHOLDER": "Cercar",
|
||||
"EMPTY_STATE": "No s'ha trobat agents"
|
||||
}
|
||||
"SHOWING_RESULTS": "Es mostren {firstIndex}-{lastIndex} de {totalCount} elements"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +481,6 @@
|
||||
"DESCRIPTION": "Utilitza el portal com a CMS sense cap amb marcs de front-end de tercers mitjançant les nostres API."
|
||||
}
|
||||
}
|
||||
},
|
||||
"LOADING": "Loading..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user