{
- return option.name.toLowerCase().includes(this.search.toLowerCase());
+ return (option.name || '')
+ .toLowerCase()
+ .includes(this.search.toLowerCase());
});
},
noResult() {
diff --git a/app/javascript/shared/composables/specs/useBranding.spec.js b/app/javascript/shared/composables/specs/useBranding.spec.js
index 6f3f06b67..4477ac052 100644
--- a/app/javascript/shared/composables/specs/useBranding.spec.js
+++ b/app/javascript/shared/composables/specs/useBranding.spec.js
@@ -73,13 +73,13 @@ describe('useBranding', () => {
expect(result).toBe('Welcome to our platform');
});
- it('should be case-sensitive for "Chatwoot"', () => {
+ it('should replace "Chatwoot" regardless of casing', () => {
const { replaceInstallationName } = useBranding();
const result = replaceInstallationName(
- 'Welcome to chatwoot and CHATWOOT'
+ 'Welcome to chatwoot, Chatwoot and CHATWOOT'
);
- expect(result).toBe('Welcome to chatwoot and CHATWOOT');
+ expect(result).toBe('Welcome to MyCompany, MyCompany and MyCompany');
});
it('should handle special characters in installation name', () => {
diff --git a/app/javascript/shared/composables/useBranding.js b/app/javascript/shared/composables/useBranding.js
index fccdcd32b..d9be3e696 100644
--- a/app/javascript/shared/composables/useBranding.js
+++ b/app/javascript/shared/composables/useBranding.js
@@ -7,7 +7,8 @@ import { useMapGetter } from 'dashboard/composables/store.js';
export function useBranding() {
const globalConfig = useMapGetter('globalConfig/get');
/**
- * Replaces "Chatwoot" in text with the installation name from global config
+ * Replaces "Chatwoot" (any casing) in text with the installation name from
+ * global config
* @param {string} text - The text to process
* @returns {string} - Text with "Chatwoot" replaced by installation name
*/
@@ -17,7 +18,7 @@ export function useBranding() {
const installationName = globalConfig.value?.installationName;
if (!installationName) return text;
- return text.replace(/Chatwoot/g, installationName);
+ return text.replace(/chatwoot/gi, installationName);
};
return {
diff --git a/app/javascript/shared/helpers/specs/timeHelper.spec.js b/app/javascript/shared/helpers/specs/timeHelper.spec.js
index d12a42bc8..8a4b50b17 100644
--- a/app/javascript/shared/helpers/specs/timeHelper.spec.js
+++ b/app/javascript/shared/helpers/specs/timeHelper.spec.js
@@ -1,11 +1,12 @@
import {
- messageStamp,
- messageTimestamp,
- dynamicTime,
dateFormat,
- shortTimestamp,
+ dynamicTime,
getDayDifferenceFromNow,
hasOneDayPassed,
+ messageStamp,
+ messageTimestamp,
+ relativeDayTimestamp,
+ shortTimestamp,
} from 'shared/helpers/timeHelper';
beforeEach(() => {
@@ -37,6 +38,33 @@ describe('#messageTimestamp', () => {
});
});
+describe('#relativeDayTimestamp', () => {
+ // System time is mocked to May 5, 2023 00:00 UTC.
+ const toUnix = date => Math.floor(date / 1000);
+
+ it('returns the time for timestamps from today', () => {
+ const today = toUnix(Date.UTC(2023, 4, 5, 15, 35, 0));
+ expect(relativeDayTimestamp(today, 'Yesterday')).toEqual('3:35 PM');
+ });
+
+ it('returns the supplied label for timestamps from yesterday', () => {
+ const yesterday = toUnix(Date.UTC(2023, 4, 4, 9, 0, 0));
+ expect(relativeDayTimestamp(yesterday, 'Yesterday')).toEqual('Yesterday');
+ });
+
+ it('returns a day and month for older timestamps in the current year', () => {
+ const earlierThisYear = toUnix(Date.UTC(2023, 1, 10, 12, 0, 0));
+ expect(relativeDayTimestamp(earlierThisYear, 'Yesterday')).toEqual(
+ 'Feb 10'
+ );
+ });
+
+ it('returns a full date for timestamps from a previous year', () => {
+ const lastYear = toUnix(Date.UTC(2021, 1, 10, 12, 0, 0));
+ expect(relativeDayTimestamp(lastYear, 'Yesterday')).toEqual('Feb 10, 2021');
+ });
+});
+
describe('#dynamicTime', () => {
it('returns correct value', () => {
Date.now = vi.fn(() => new Date(Date.UTC(2023, 1, 14)).valueOf());
diff --git a/app/javascript/shared/helpers/timeHelper.js b/app/javascript/shared/helpers/timeHelper.js
index db5609d89..cde5ccf89 100644
--- a/app/javascript/shared/helpers/timeHelper.js
+++ b/app/javascript/shared/helpers/timeHelper.js
@@ -1,6 +1,9 @@
import {
format,
isSameYear,
+ isThisYear,
+ isToday,
+ isYesterday,
fromUnixTime,
formatDistanceToNow,
differenceInDays,
@@ -33,6 +36,22 @@ export const messageTimestamp = (time, dateFormat = 'MMM d, yyyy') => {
return messageDate;
};
+/**
+ * Formats a Unix timestamp relative to today: the time for today, a caller-
+ * supplied label for yesterday, and a date otherwise. The yesterday label is
+ * passed in so the caller keeps ownership of translation.
+ * @param {number} time - Unix timestamp.
+ * @param {string} yesterdayLabel - Localized label shown for yesterday.
+ * @returns {string} Formatted timestamp string.
+ */
+export const relativeDayTimestamp = (time, yesterdayLabel) => {
+ const date = fromUnixTime(time);
+ if (isToday(date)) return format(date, 'h:mm a');
+ if (isYesterday(date)) return yesterdayLabel;
+ if (isThisYear(date)) return format(date, 'MMM d');
+ return format(date, 'MMM d, yyyy');
+};
+
/**
* Converts a Unix timestamp to a relative time string (e.g., 3 hours ago).
* @param {number} time - Unix timestamp.
diff --git a/app/javascript/survey/i18n/index.js b/app/javascript/survey/i18n/index.js
index 1a9ea1a59..908d3e628 100644
--- a/app/javascript/survey/i18n/index.js
+++ b/app/javascript/survey/i18n/index.js
@@ -35,6 +35,7 @@ import ta from './locale/ta.json';
import th from './locale/th.json';
import tr from './locale/tr.json';
import uk from './locale/uk.json';
+import uz from './locale/uz.json';
import vi from './locale/vi.json';
import zh_CN from './locale/zh_CN.json';
import zh_TW from './locale/zh_TW.json';
@@ -77,6 +78,7 @@ export default {
th,
tr,
uk,
+ uz,
vi,
zh_CN,
zh_TW,
diff --git a/app/javascript/survey/i18n/locale/uz.json b/app/javascript/survey/i18n/locale/uz.json
new file mode 100644
index 000000000..2d8359d79
--- /dev/null
+++ b/app/javascript/survey/i18n/locale/uz.json
@@ -0,0 +1,19 @@
+{
+ "SURVEY": {
+ "DESCRIPTION": "Hurmatli mijoz 👋, {inboxName} bilan bo'lgan suhbatingiz haqida fikr bildirish uchun bir necha daqiqa vaqt ajrating.",
+ "RATING": {
+ "LABEL": "Suhbatingizni baholang",
+ "SUCCESS_MESSAGE": "Baho berganingiz uchun rahmat"
+ },
+ "FEEDBACK": {
+ "LABEL": "Bildirmoqchi bo'lgan fikr-mulohazalaringiz bormi?",
+ "PLACEHOLDER": "Fikringiz (ixtiyoriy)",
+ "BUTTON_TEXT": "Fikrni yuborish"
+ },
+ "API": {
+ "SUCCESS_MESSAGE": "So'rovnoma muvaffaqiyatli yangilandi",
+ "ERROR_MESSAGE": "Woot serveriga ulanib bo'lmadi, iltimos, keyinroq qayta urinib ko'ring"
+ }
+ },
+ "POWERED_BY": "Chatwoot yordamida ishlaydi"
+}
diff --git a/app/javascript/widget/components/ChatFooter.vue b/app/javascript/widget/components/ChatFooter.vue
index c85727a2b..2cad4d177 100755
--- a/app/javascript/widget/components/ChatFooter.vue
+++ b/app/javascript/widget/components/ChatFooter.vue
@@ -11,6 +11,8 @@ import { IFrameHelper } from '../helpers/utils';
import { CHATWOOT_ON_START_CONVERSATION } from '../constants/sdkEvents';
import { emitter } from 'shared/helpers/mitt';
+const TRANSCRIPT_COOLDOWN_MS = 15000;
+
export default {
components: {
ChatInputWrap,
@@ -24,6 +26,9 @@ export default {
data() {
return {
inReplyTo: null,
+ isSendingTranscript: false,
+ transcriptCooldown: false,
+ transcriptCooldownTimer: null,
};
},
computed: {
@@ -57,6 +62,9 @@ export default {
mounted() {
emitter.on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.toggleReplyTo);
},
+ beforeUnmount() {
+ clearTimeout(this.transcriptCooldownTimer);
+ },
methods: {
...mapActions('conversation', ['sendMessage', 'sendAttachment']),
...mapActions('conversationAttributes', ['getAttributes']),
@@ -90,19 +98,35 @@ export default {
toggleReplyTo(message) {
this.inReplyTo = message;
},
+ startTranscriptCooldown() {
+ this.transcriptCooldown = true;
+ clearTimeout(this.transcriptCooldownTimer);
+ this.transcriptCooldownTimer = setTimeout(() => {
+ this.transcriptCooldown = false;
+ }, TRANSCRIPT_COOLDOWN_MS);
+ },
async sendTranscript() {
- if (this.hasEmail) {
- try {
- await sendEmailTranscript();
- emitter.emit(BUS_EVENTS.SHOW_ALERT, {
- message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'),
- type: 'success',
- });
- } catch (error) {
- emitter.$emit(BUS_EVENTS.SHOW_ALERT, {
- message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'),
- });
- }
+ if (
+ !this.hasEmail ||
+ this.isSendingTranscript ||
+ this.transcriptCooldown
+ ) {
+ return;
+ }
+ this.isSendingTranscript = true;
+ try {
+ await sendEmailTranscript();
+ this.startTranscriptCooldown();
+ emitter.emit(BUS_EVENTS.SHOW_ALERT, {
+ message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'),
+ type: 'success',
+ });
+ } catch (error) {
+ emitter.emit(BUS_EVENTS.SHOW_ALERT, {
+ message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'),
+ });
+ } finally {
+ this.isSendingTranscript = false;
}
},
},
@@ -144,6 +168,7 @@ export default {
v-if="showEmailTranscriptButton"
type="clear"
class="font-normal"
+ :disabled="isSendingTranscript || transcriptCooldown"
@click="sendTranscript"
>
{{ $t('EMAIL_TRANSCRIPT.BUTTON_TEXT') }}
diff --git a/app/javascript/widget/i18n/index.js b/app/javascript/widget/i18n/index.js
index 93a371391..ee7d355cf 100644
--- a/app/javascript/widget/i18n/index.js
+++ b/app/javascript/widget/i18n/index.js
@@ -35,6 +35,7 @@ import ta from './locale/ta.json';
import th from './locale/th.json';
import tr from './locale/tr.json';
import uk from './locale/uk.json';
+import uz from './locale/uz.json';
import vi from './locale/vi.json';
import zh_CN from './locale/zh_CN.json';
import zh_TW from './locale/zh_TW.json';
@@ -77,6 +78,7 @@ export default {
th,
tr,
uk,
+ uz,
vi,
zh_CN,
zh_TW,
diff --git a/app/javascript/widget/i18n/locale/am.json b/app/javascript/widget/i18n/locale/am.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/am.json
+++ b/app/javascript/widget/i18n/locale/am.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/ar.json b/app/javascript/widget/i18n/locale/ar.json
index 1424b7418..9d7e7daa1 100644
--- a/app/javascript/widget/i18n/locale/ar.json
+++ b/app/javascript/widget/i18n/locale/ar.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "لا يوجد إيموجي يطابق بحثك",
"ARIA_LABEL": "أداة اختيار الايموجي"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "لا يوجد إيموجي يطابق بحثك"
+ },
"CSAT": {
"TITLE": "قيم محادثتك",
"SUBMITTED_TITLE": "شكرا لك على تقييم المحادثة",
diff --git a/app/javascript/widget/i18n/locale/az.json b/app/javascript/widget/i18n/locale/az.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/az.json
+++ b/app/javascript/widget/i18n/locale/az.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/bg.json b/app/javascript/widget/i18n/locale/bg.json
index 369caa46a..ccaf944f5 100644
--- a/app/javascript/widget/i18n/locale/bg.json
+++ b/app/javascript/widget/i18n/locale/bg.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Няма намерени емотикони",
"ARIA_LABEL": "Избор на емотикони"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Оценете този разговор",
"SUBMITTED_TITLE": "Благодарим ви, че оценихте разговора",
diff --git a/app/javascript/widget/i18n/locale/bn.json b/app/javascript/widget/i18n/locale/bn.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/bn.json
+++ b/app/javascript/widget/i18n/locale/bn.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/ca.json b/app/javascript/widget/i18n/locale/ca.json
index ce3b99da7..4553c4c6b 100644
--- a/app/javascript/widget/i18n/locale/ca.json
+++ b/app/javascript/widget/i18n/locale/ca.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Cap emoji coincideix amb la teva cerca",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Cap emoji coincideix amb la teva cerca"
+ },
"CSAT": {
"TITLE": "Valora la teva conversa",
"SUBMITTED_TITLE": "Gràcies per enviar la qualificació",
diff --git a/app/javascript/widget/i18n/locale/cs.json b/app/javascript/widget/i18n/locale/cs.json
index 61bebf777..e2aa28472 100644
--- a/app/javascript/widget/i18n/locale/cs.json
+++ b/app/javascript/widget/i18n/locale/cs.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Žádné emoji neodpovídají vašemu hledání",
"ARIA_LABEL": "Výběr emoji"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Ohodnoťte svou konverzaci",
"SUBMITTED_TITLE": "Děkujeme Vám za odeslání hodnocení",
diff --git a/app/javascript/widget/i18n/locale/da.json b/app/javascript/widget/i18n/locale/da.json
index ef7adfc51..b663ee089 100644
--- a/app/javascript/widget/i18n/locale/da.json
+++ b/app/javascript/widget/i18n/locale/da.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Ingen emoji matcher din søgning",
"ARIA_LABEL": "Emoji vælger"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Ingen emoji matcher din søgning"
+ },
"CSAT": {
"TITLE": "Bedøm din samtale",
"SUBMITTED_TITLE": "Tak for din bedømmelse",
diff --git a/app/javascript/widget/i18n/locale/de.json b/app/javascript/widget/i18n/locale/de.json
index fd6de1f2e..b51f879af 100644
--- a/app/javascript/widget/i18n/locale/de.json
+++ b/app/javascript/widget/i18n/locale/de.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Kein Emoji entspricht Ihrer Suche",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Kein Emoji entspricht deiner Suche"
+ },
"CSAT": {
"TITLE": "Bewerten Sie Ihre Konversation",
"SUBMITTED_TITLE": "Danke, dass Sie die Bewertung eingereicht haben",
diff --git a/app/javascript/widget/i18n/locale/el.json b/app/javascript/widget/i18n/locale/el.json
index 64bb71e74..c3613fe58 100644
--- a/app/javascript/widget/i18n/locale/el.json
+++ b/app/javascript/widget/i18n/locale/el.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Κανένα emoji δεν ταιριάζει με την αναζήτησή σας",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Κανένα emoji δεν ταιριάζει με την αναζήτησή σας"
+ },
"CSAT": {
"TITLE": "Αξιολογήστε τη συνομιλία σας",
"SUBMITTED_TITLE": "Ευχαριστούμε για την υποβολή της αξιολόγησης",
diff --git a/app/javascript/widget/i18n/locale/es.json b/app/javascript/widget/i18n/locale/es.json
index 3ced9aeab..8119a674a 100644
--- a/app/javascript/widget/i18n/locale/es.json
+++ b/app/javascript/widget/i18n/locale/es.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Ningún emoji coincide con tu búsqueda",
"ARIA_LABEL": "Selector de emoji"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Buscar emoji…",
+ "FREQUENTLY_USED": "Usado con frecuencia",
+ "NO_EMOJI": "Ningún emoji coincide con tu búsqueda"
+ },
"CSAT": {
"TITLE": "Califica tu conversación",
"SUBMITTED_TITLE": "Gracias por enviar la valoración",
diff --git a/app/javascript/widget/i18n/locale/et.json b/app/javascript/widget/i18n/locale/et.json
index e4a1f135f..e856e3f89 100644
--- a/app/javascript/widget/i18n/locale/et.json
+++ b/app/javascript/widget/i18n/locale/et.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Ühtegi emotikoni ei leitud",
"ARIA_LABEL": "Emotikonide valija"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Hinda oma vestlust",
"SUBMITTED_TITLE": "Täname hinnangu eest",
diff --git a/app/javascript/widget/i18n/locale/fa.json b/app/javascript/widget/i18n/locale/fa.json
index c4d1bcc1c..17eac8c8e 100644
--- a/app/javascript/widget/i18n/locale/fa.json
+++ b/app/javascript/widget/i18n/locale/fa.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "هیچ اموجی با جستجوی شما مطابقت ندارد",
"ARIA_LABEL": "انتخاب اموجی"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "هیچ اموجی با جستجوی شما مطابقت ندارد"
+ },
"CSAT": {
"TITLE": "به گفتگوی خود امتیاز دهید",
"SUBMITTED_TITLE": "با تشکر از شما برای ثبت امتیاز",
diff --git a/app/javascript/widget/i18n/locale/fi.json b/app/javascript/widget/i18n/locale/fi.json
index b11170020..c7655af29 100644
--- a/app/javascript/widget/i18n/locale/fi.json
+++ b/app/javascript/widget/i18n/locale/fi.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Yksikään emoji ei vastaa hakuasi",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Anna arvio palvelusta",
"SUBMITTED_TITLE": "Kiitos, että lähetit arvion",
diff --git a/app/javascript/widget/i18n/locale/fr.json b/app/javascript/widget/i18n/locale/fr.json
index 90275e02a..9f6a649f1 100644
--- a/app/javascript/widget/i18n/locale/fr.json
+++ b/app/javascript/widget/i18n/locale/fr.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Aucun émoji ne correspond à votre recherche",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Aucun émoji ne correspond à votre recherche"
+ },
"CSAT": {
"TITLE": "Évaluer votre conversation",
"SUBMITTED_TITLE": "Merci d'avoir soumis votre évaluation",
diff --git a/app/javascript/widget/i18n/locale/he.json b/app/javascript/widget/i18n/locale/he.json
index 70ea66e83..0fdfa0fd3 100644
--- a/app/javascript/widget/i18n/locale/he.json
+++ b/app/javascript/widget/i18n/locale/he.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "אין אמוג'י שתואם את החיפוש שלך",
"ARIA_LABEL": "בוחר אימוג'י"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "אין אמוג'י שתואם את החיפוש שלך"
+ },
"CSAT": {
"TITLE": "דרג את השיחה שלך",
"SUBMITTED_TITLE": "תודה על שליחת הדירוג",
diff --git a/app/javascript/widget/i18n/locale/hi.json b/app/javascript/widget/i18n/locale/hi.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/hi.json
+++ b/app/javascript/widget/i18n/locale/hi.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/hr.json b/app/javascript/widget/i18n/locale/hr.json
index 1ae76f16f..f10e4eef4 100644
--- a/app/javascript/widget/i18n/locale/hr.json
+++ b/app/javascript/widget/i18n/locale/hr.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nema emojija koji odgovaraju vašoj pretrazi",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Ocijenite vaš razgovor",
"SUBMITTED_TITLE": "Hvala vam na ocjeni",
diff --git a/app/javascript/widget/i18n/locale/hu.json b/app/javascript/widget/i18n/locale/hu.json
index 5ea7c095a..2bca22079 100644
--- a/app/javascript/widget/i18n/locale/hu.json
+++ b/app/javascript/widget/i18n/locale/hu.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nem található emoji",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Nem található emoji"
+ },
"CSAT": {
"TITLE": "Értékeld a beszélgetést",
"SUBMITTED_TITLE": "Köszönjük, hogy elküldted az értékelést",
diff --git a/app/javascript/widget/i18n/locale/hy.json b/app/javascript/widget/i18n/locale/hy.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/hy.json
+++ b/app/javascript/widget/i18n/locale/hy.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/id.json b/app/javascript/widget/i18n/locale/id.json
index 59f86956f..d65558010 100644
--- a/app/javascript/widget/i18n/locale/id.json
+++ b/app/javascript/widget/i18n/locale/id.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Tidak ada emoji yang cocok dengan penelusuran anda",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Tidak ditemukan emoji yang sesuai dengan pencarian Anda"
+ },
"CSAT": {
"TITLE": "Nilai percakapan anda",
"SUBMITTED_TITLE": "Terima kasih telah mengirimkan penilaian",
diff --git a/app/javascript/widget/i18n/locale/is.json b/app/javascript/widget/i18n/locale/is.json
index 0ab53118a..14d5e585b 100644
--- a/app/javascript/widget/i18n/locale/is.json
+++ b/app/javascript/widget/i18n/locale/is.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Enginn emoji fannst",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Gefðu samtalinu einkunn",
"SUBMITTED_TITLE": "Takk fyrir að gefa samtalinu einkunn",
diff --git a/app/javascript/widget/i18n/locale/it.json b/app/javascript/widget/i18n/locale/it.json
index d5ec381d2..5d3c37acd 100644
--- a/app/javascript/widget/i18n/locale/it.json
+++ b/app/javascript/widget/i18n/locale/it.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nessuna emoji corrisponde alla tua ricerca",
"ARIA_LABEL": "Selettore emoji"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Nessuna emoji corrisponde alla tua ricerca"
+ },
"CSAT": {
"TITLE": "Valuta la conversazione",
"SUBMITTED_TITLE": "Grazie per aver inviato la valutazione",
diff --git a/app/javascript/widget/i18n/locale/ja.json b/app/javascript/widget/i18n/locale/ja.json
index b8300fbab..a915271f9 100644
--- a/app/javascript/widget/i18n/locale/ja.json
+++ b/app/javascript/widget/i18n/locale/ja.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "検索条件に一致する絵文字がありません",
"ARIA_LABEL": "絵文字選択"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "検索条件に一致する絵文字が見つかりません"
+ },
"CSAT": {
"TITLE": "会話の評価",
"SUBMITTED_TITLE": "評価を送信いただきありがとうございます",
diff --git a/app/javascript/widget/i18n/locale/ka.json b/app/javascript/widget/i18n/locale/ka.json
index ce5f10c07..e9ec1ea08 100644
--- a/app/javascript/widget/i18n/locale/ka.json
+++ b/app/javascript/widget/i18n/locale/ka.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/ko.json b/app/javascript/widget/i18n/locale/ko.json
index d9f213da4..379cba948 100644
--- a/app/javascript/widget/i18n/locale/ko.json
+++ b/app/javascript/widget/i18n/locale/ko.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "검색과 일치하는 이모지 없음",
"ARIA_LABEL": "이모지 선택기"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "검색과 일치하는 이모지가 없습니다"
+ },
"CSAT": {
"TITLE": "대화를 평가해주세요.",
"SUBMITTED_TITLE": "평가해주셔서 감사합니다!",
diff --git a/app/javascript/widget/i18n/locale/lt.json b/app/javascript/widget/i18n/locale/lt.json
index a11db6919..5d07721e5 100644
--- a/app/javascript/widget/i18n/locale/lt.json
+++ b/app/javascript/widget/i18n/locale/lt.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Jūsų paieška neatitinka jokių jaustukų",
"ARIA_LABEL": "Jaustukų pasirinkimas"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Jūsų paieška neatitinka jokių emodži"
+ },
"CSAT": {
"TITLE": "Įvertinkite savo pokalbį",
"SUBMITTED_TITLE": "Dėkojame, kad pateikėte įvertinimą",
diff --git a/app/javascript/widget/i18n/locale/lv.json b/app/javascript/widget/i18n/locale/lv.json
index 702fb041f..8d5b93417 100644
--- a/app/javascript/widget/i18n/locale/lv.json
+++ b/app/javascript/widget/i18n/locale/lv.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Neviena emocijzīme neatbilst jūsu meklēšanas vaicājumam",
"ARIA_LABEL": "Emocijzīmju atlasītājs"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Neviena emocijzīme neatbilst jūsu meklēšanas vaicājumam"
+ },
"CSAT": {
"TITLE": "Novērtējiet Jūsu sarunu",
"SUBMITTED_TITLE": "Paldies, ka iesniedzāt novērtējumu",
diff --git a/app/javascript/widget/i18n/locale/ml.json b/app/javascript/widget/i18n/locale/ml.json
index 96a650cb4..5fecfb403 100644
--- a/app/javascript/widget/i18n/locale/ml.json
+++ b/app/javascript/widget/i18n/locale/ml.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "നിങ്ങളുടെ സംഭാഷണം റേറ്റുചെയ്യുക",
"SUBMITTED_TITLE": "റേറ്റിംഗ് സമർപ്പിച്ചതിന് നന്ദി",
diff --git a/app/javascript/widget/i18n/locale/ms.json b/app/javascript/widget/i18n/locale/ms.json
index d813e4eb1..3fd8aa653 100644
--- a/app/javascript/widget/i18n/locale/ms.json
+++ b/app/javascript/widget/i18n/locale/ms.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/ne.json b/app/javascript/widget/i18n/locale/ne.json
index 20120afd9..f1959ec1e 100644
--- a/app/javascript/widget/i18n/locale/ne.json
+++ b/app/javascript/widget/i18n/locale/ne.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/nl.json b/app/javascript/widget/i18n/locale/nl.json
index 2f123f80a..271d9feed 100644
--- a/app/javascript/widget/i18n/locale/nl.json
+++ b/app/javascript/widget/i18n/locale/nl.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Er zijn geen overeenkomende emoji's gevonden",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Er zijn geen overeenkomende emoji's gevonden"
+ },
"CSAT": {
"TITLE": "Beoordeel uw gesprek",
"SUBMITTED_TITLE": "Bedankt voor het indienen van een beoordeling",
diff --git a/app/javascript/widget/i18n/locale/no.json b/app/javascript/widget/i18n/locale/no.json
index 9034df45b..92742d443 100644
--- a/app/javascript/widget/i18n/locale/no.json
+++ b/app/javascript/widget/i18n/locale/no.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Ingen emojier samsvarer søket ditt",
"ARIA_LABEL": "Emoji velger"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Vurder samtalen din",
"SUBMITTED_TITLE": "Takk for at du ga din vurdering",
diff --git a/app/javascript/widget/i18n/locale/pl.json b/app/javascript/widget/i18n/locale/pl.json
index c2095692f..7677a5ea2 100644
--- a/app/javascript/widget/i18n/locale/pl.json
+++ b/app/javascript/widget/i18n/locale/pl.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nie znaleziono emoji pasującego do wyszukiwania",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Nie znaleziono emoji pasującego do wyszukiwania"
+ },
"CSAT": {
"TITLE": "Oceń udzielone Ci wsparcie",
"SUBMITTED_TITLE": "Dziękujemy za przesłanie oceny",
diff --git a/app/javascript/widget/i18n/locale/pt.json b/app/javascript/widget/i18n/locale/pt.json
index 300ffb59f..0dfebb81e 100644
--- a/app/javascript/widget/i18n/locale/pt.json
+++ b/app/javascript/widget/i18n/locale/pt.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nenhum emoji corresponde à sua pesquisa",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Nenhum emoji corresponde à sua pesquisa"
+ },
"CSAT": {
"TITLE": "Avalie a sua conversa",
"SUBMITTED_TITLE": "Obrigado pela sua avaliação",
diff --git a/app/javascript/widget/i18n/locale/pt_BR.json b/app/javascript/widget/i18n/locale/pt_BR.json
index c5c85a251..7c9422df9 100644
--- a/app/javascript/widget/i18n/locale/pt_BR.json
+++ b/app/javascript/widget/i18n/locale/pt_BR.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Nenhum emoji corresponde à sua pesquisa",
"ARIA_LABEL": "Seletor de emoji"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Pesquisar emoji…",
+ "FREQUENTLY_USED": "Usados com frequência",
+ "NO_EMOJI": "Nenhum emoji corresponde à sua pesquisa"
+ },
"CSAT": {
"TITLE": "Avalie sua conversa",
"SUBMITTED_TITLE": "Obrigado por enviar a classificação",
diff --git a/app/javascript/widget/i18n/locale/ro.json b/app/javascript/widget/i18n/locale/ro.json
index cd77700b8..bfd5ca849 100644
--- a/app/javascript/widget/i18n/locale/ro.json
+++ b/app/javascript/widget/i18n/locale/ro.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Niciun emoji nu corespunde căutării tale",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Niciun emoji nu corespunde căutării tale"
+ },
"CSAT": {
"TITLE": "Evaluează conversația ta",
"SUBMITTED_TITLE": "Vă mulțumim pentru trimiterea de rating",
diff --git a/app/javascript/widget/i18n/locale/ru.json b/app/javascript/widget/i18n/locale/ru.json
index a2d1005c1..397088273 100644
--- a/app/javascript/widget/i18n/locale/ru.json
+++ b/app/javascript/widget/i18n/locale/ru.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "По Вашему запросу не было найдено эмодзи",
"ARIA_LABEL": "Выбор эмодзи"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Эмодзи не соответствуют вашему запросу"
+ },
"CSAT": {
"TITLE": "Оцените разговор",
"SUBMITTED_TITLE": "Спасибо за оценку",
diff --git a/app/javascript/widget/i18n/locale/sh.json b/app/javascript/widget/i18n/locale/sh.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/sh.json
+++ b/app/javascript/widget/i18n/locale/sh.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/sk.json b/app/javascript/widget/i18n/locale/sk.json
index b7ac2a763..49865cd03 100644
--- a/app/javascript/widget/i18n/locale/sk.json
+++ b/app/javascript/widget/i18n/locale/sk.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Ohodnoťte konverzáciu",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/sl.json b/app/javascript/widget/i18n/locale/sl.json
index 0c95f1268..b06eaeeaf 100644
--- a/app/javascript/widget/i18n/locale/sl.json
+++ b/app/javascript/widget/i18n/locale/sl.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Noben emoji ne ustreza vašemu iskanju",
"ARIA_LABEL": "Iskalnik emoji-jev"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Z vašim iskanjem se ne ujema noben emoji"
+ },
"CSAT": {
"TITLE": "Ocenite svoj pogovor",
"SUBMITTED_TITLE": "Hvala za oddano oceno",
diff --git a/app/javascript/widget/i18n/locale/sq.json b/app/javascript/widget/i18n/locale/sq.json
index 3efbe543e..299cf6999 100644
--- a/app/javascript/widget/i18n/locale/sq.json
+++ b/app/javascript/widget/i18n/locale/sq.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/sr.json b/app/javascript/widget/i18n/locale/sr.json
index c0eae2c59..b0e1e8205 100644
--- a/app/javascript/widget/i18n/locale/sr.json
+++ b/app/javascript/widget/i18n/locale/sr.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Ocenite razgovor",
"SUBMITTED_TITLE": "Hvala vam na dostavljenoj oceni",
diff --git a/app/javascript/widget/i18n/locale/sv.json b/app/javascript/widget/i18n/locale/sv.json
index 4d6e1723c..3ee701e1d 100644
--- a/app/javascript/widget/i18n/locale/sv.json
+++ b/app/javascript/widget/i18n/locale/sv.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Ingen emoji matchar din sökning",
"ARIA_LABEL": "Emoji-väljare"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Ingen emoji matchar din sökning"
+ },
"CSAT": {
"TITLE": "Betygsätt din konversation",
"SUBMITTED_TITLE": "Tack för att du lämnat in omdömet",
diff --git a/app/javascript/widget/i18n/locale/ta.json b/app/javascript/widget/i18n/locale/ta.json
index 91ccddf96..922f50d91 100644
--- a/app/javascript/widget/i18n/locale/ta.json
+++ b/app/javascript/widget/i18n/locale/ta.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/th.json b/app/javascript/widget/i18n/locale/th.json
index fcfed1fde..1c4781380 100644
--- a/app/javascript/widget/i18n/locale/th.json
+++ b/app/javascript/widget/i18n/locale/th.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "ให้คะแนนการสนทนาครั้งนี้",
"SUBMITTED_TITLE": "ขอบคุณที่ร่วมมือให้คะแนนการสนทนากับเรา",
diff --git a/app/javascript/widget/i18n/locale/tl.json b/app/javascript/widget/i18n/locale/tl.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/tl.json
+++ b/app/javascript/widget/i18n/locale/tl.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/tr.json b/app/javascript/widget/i18n/locale/tr.json
index 7c552eac5..d3f716523 100644
--- a/app/javascript/widget/i18n/locale/tr.json
+++ b/app/javascript/widget/i18n/locale/tr.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "İfade bulunamadı",
"ARIA_LABEL": "Emoji seçimi"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Aramanızla eşleşen emoji yok"
+ },
"CSAT": {
"TITLE": "Görüşmenizi değerlendirin",
"SUBMITTED_TITLE": "Değerlendirmeniz için teşekkürler",
diff --git a/app/javascript/widget/i18n/locale/uk.json b/app/javascript/widget/i18n/locale/uk.json
index d31df8ab0..4c028be58 100644
--- a/app/javascript/widget/i18n/locale/uk.json
+++ b/app/javascript/widget/i18n/locale/uk.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Немає емодзі, що відповідають пошуковому запиту",
"ARIA_LABEL": "Вибір емодзі"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "Немає смайликів, які відповідають вашому запиту"
+ },
"CSAT": {
"TITLE": "Оцініть вашу бесіду",
"SUBMITTED_TITLE": "Дякуємо за оцінку",
diff --git a/app/javascript/widget/i18n/locale/ur.json b/app/javascript/widget/i18n/locale/ur.json
index 7b03483a4..16cf1968f 100644
--- a/app/javascript/widget/i18n/locale/ur.json
+++ b/app/javascript/widget/i18n/locale/ur.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/ur_IN.json b/app/javascript/widget/i18n/locale/ur_IN.json
index c3d6ddfc1..82271f4de 100644
--- a/app/javascript/widget/i18n/locale/ur_IN.json
+++ b/app/javascript/widget/i18n/locale/ur_IN.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "No emoji match your search",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
diff --git a/app/javascript/widget/i18n/locale/uz.json b/app/javascript/widget/i18n/locale/uz.json
new file mode 100644
index 000000000..3e0b06a5d
--- /dev/null
+++ b/app/javascript/widget/i18n/locale/uz.json
@@ -0,0 +1,158 @@
+{
+ "COMPONENTS": {
+ "FILE_BUBBLE": {
+ "DOWNLOAD": "Yuklab olish",
+ "UPLOADING": "Yuklanmoqda..."
+ },
+ "FORM_BUBBLE": {
+ "SUBMIT": "Yuborish"
+ },
+ "MESSAGE_BUBBLE": {
+ "RETRY": "Xabarni qayta yuborish",
+ "ERROR_MESSAGE": "Yuborib bo'lmadi, qayta urinib ko'ring"
+ }
+ },
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Mavjud emas"
+ }
+ },
+ "TEAM_AVAILABILITY": {
+ "ONLINE": "Biz onlaynmiz",
+ "OFFLINE": "Hozircha javob bera olmaymiz",
+ "BACK_AS_SOON_AS_POSSIBLE": "Imkon qadar tezroq qaytamiz"
+ },
+ "REPLY_TIME": {
+ "IN_A_FEW_MINUTES": "Odatda bir necha daqiqada javob beramiz",
+ "IN_A_FEW_HOURS": "Odatda bir necha soatda javob beramiz",
+ "IN_A_DAY": "Odatda bir kun ichida javob beramiz",
+ "BACK_IN_HOURS": "{n} soatdan keyin onlayn bo'lamiz | {n} soatdan keyin onlayn bo'lamiz",
+ "BACK_IN_MINUTES": "{time} daqiqadan keyin onlayn bo'lamiz",
+ "BACK_AT_TIME": "Soat {time} da onlayn bo'lamiz",
+ "BACK_ON_DAY": "{day} kuni onlayn bo'lamiz",
+ "BACK_TOMORROW": "Ertaga onlayn bo'lamiz",
+ "BACK_IN_SOME_TIME": "Birozdan keyin onlayn bo'lamiz"
+ },
+ "DAY_NAMES": {
+ "SUNDAY": "Yakshanba",
+ "MONDAY": "Dushanba",
+ "TUESDAY": "Seshanba",
+ "WEDNESDAY": "Chorshanba",
+ "THURSDAY": "Payshanba",
+ "FRIDAY": "Juma",
+ "SATURDAY": "Shanba"
+ },
+ "START_CONVERSATION": "Suhbatni boshlash",
+ "END_CONVERSATION": "Suhbatni tugatish",
+ "CONTINUE_CONVERSATION": "Suhbatni davom ettirish",
+ "YOU": "Siz",
+ "START_NEW_CONVERSATION": "Yangi suhbatni boshlash",
+ "VIEW_UNREAD_MESSAGES": "Sizda o'qilmagan xabarlar bor",
+ "UNREAD_VIEW": {
+ "VIEW_MESSAGES_BUTTON": "Yangi xabarlarni ko'rish",
+ "CLOSE_MESSAGES_BUTTON": "Yopish",
+ "COMPANY_FROM": "tomonidan",
+ "BOT": "Bot"
+ },
+ "BUBBLE": {
+ "LABEL": "Biz bilan suhbatlashing"
+ },
+ "POWERED_BY": "Chatwoot yordamida ishlaydi",
+ "EMAIL_PLACEHOLDER": "Iltimos, emailingizni kiriting",
+ "CHAT_PLACEHOLDER": "Xabaringizni yozing",
+ "TODAY": "Bugun",
+ "YESTERDAY": "Kecha",
+ "PRE_CHAT_FORM": {
+ "FIELDS": {
+ "FULL_NAME": {
+ "LABEL": "To'liq ism",
+ "PLACEHOLDER": "Iltimos, to'liq ismingizni kiriting",
+ "REQUIRED_ERROR": "To'liq ism kiritilishi shart"
+ },
+ "EMAIL_ADDRESS": {
+ "LABEL": "Email manzili",
+ "PLACEHOLDER": "Iltimos, email manzilingizni kiriting",
+ "REQUIRED_ERROR": "Email manzilini kiritish shart",
+ "VALID_ERROR": "Iltimos, to'g'ri email manzilini kiriting"
+ },
+ "PHONE_NUMBER": {
+ "LABEL": "Telefon raqami",
+ "PLACEHOLDER": "Iltimos, telefon raqamingizni kiriting",
+ "REQUIRED_ERROR": "Telefon raqami kiritilishi shart",
+ "DIAL_CODE_VALID_ERROR": "Iltimos, mamlakat kodini tanlang",
+ "VALID_ERROR": "Iltimos, to'g'ri telefon raqamini kiriting",
+ "DROPDOWN_EMPTY": "Natija topilmadi",
+ "DROPDOWN_SEARCH": "Mamlakatni qidirish"
+ },
+ "MESSAGE": {
+ "LABEL": "Xabar",
+ "PLACEHOLDER": "Iltimos, xabaringizni kiriting",
+ "ERROR": "Xabar juda qisqa"
+ }
+ },
+ "CAMPAIGN_HEADER": "Suhbatni boshlashdan oldin ism va emailingizni kiriting",
+ "IS_REQUIRED": "kiritilishi shart",
+ "REQUIRED": "Majburiy",
+ "REGEX_ERROR": "Iltimos, to'g'ri ma'lumot kiriting"
+ },
+ "FILE_SIZE_LIMIT": "Fayl {MAXIMUM_FILE_UPLOAD_SIZE} biriktirma chegarasidan oshib ketdi",
+ "CHAT_FORM": {
+ "INVALID": {
+ "FIELD": "Noto'g'ri maydon"
+ }
+ },
+ "EMOJI": {
+ "PLACEHOLDER": "Emoji qidirish",
+ "NOT_FOUND": "Qidiruvga mos emoji topilmadi",
+ "ARIA_LABEL": "Emoji tanlagich"
+ },
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Emojilarni qidirish…",
+ "FREQUENTLY_USED": "Ko'p ishlatiladiganlar",
+ "NO_EMOJI": "Qidiruvga mos emoji topilmadi"
+ },
+ "CSAT": {
+ "TITLE": "Suhbatingizni baholang",
+ "SUBMITTED_TITLE": "Baho berganingiz uchun rahmat",
+ "PLACEHOLDER": "Batafsil aytib bering..."
+ },
+ "EMAIL_TRANSCRIPT": {
+ "BUTTON_TEXT": "Suhbat tarixini so'rash",
+ "SEND_EMAIL_SUCCESS": "Suhbat tarixi muvaffaqiyatli yuborildi",
+ "SEND_EMAIL_ERROR": "Xatolik yuz berdi, qayta urinib ko'ring"
+ },
+ "INTEGRATIONS": {
+ "DYTE": {
+ "CLICK_HERE_TO_JOIN": "Qo'shilish uchun shu yerni bosing",
+ "LEAVE_THE_ROOM": "Qo'ng'iroqni tark etish"
+ }
+ },
+ "PORTAL": {
+ "POPULAR_ARTICLES": "Ommabop maqolalar",
+ "VIEW_ALL_ARTICLES": "Barcha maqolalarni ko'rish",
+ "IFRAME_LOAD_ERROR": "Maqolani yuklashda xatolik yuz berdi, sahifani yangilab qayta urinib ko'ring."
+ },
+ "ATTACHMENTS": {
+ "image": {
+ "CONTENT": "Rasmli xabar"
+ },
+ "audio": {
+ "CONTENT": "Audio xabar"
+ },
+ "video": {
+ "CONTENT": "Video xabar"
+ },
+ "file": {
+ "CONTENT": "Fayl biriktirmasi"
+ },
+ "location": {
+ "CONTENT": "Joylashuv"
+ },
+ "fallback": {
+ "CONTENT": "havola ulashdi"
+ }
+ },
+ "FOOTER_REPLY_TO": {
+ "REPLY_TO": "Javob berilmoqda:"
+ }
+}
diff --git a/app/javascript/widget/i18n/locale/vi.json b/app/javascript/widget/i18n/locale/vi.json
index 312883388..318316f3f 100644
--- a/app/javascript/widget/i18n/locale/vi.json
+++ b/app/javascript/widget/i18n/locale/vi.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "Không có biểu tượng cảm xúc nào phù hợp với tìm kiếm của bạn",
"ARIA_LABEL": "Emoji picker"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "No emoji match your search"
+ },
"CSAT": {
"TITLE": "Đánh giá hội thoại",
"SUBMITTED_TITLE": "Cảm ơn vì đã đánh giá",
diff --git a/app/javascript/widget/i18n/locale/zh_CN.json b/app/javascript/widget/i18n/locale/zh_CN.json
index dc4a1cebe..ac30579e8 100644
--- a/app/javascript/widget/i18n/locale/zh_CN.json
+++ b/app/javascript/widget/i18n/locale/zh_CN.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "没有适合你的搜索结果",
"ARIA_LABEL": "Emoji选择器"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "没有适合你的搜索结果"
+ },
"CSAT": {
"TITLE": "评价您的对话",
"SUBMITTED_TITLE": "感谢您提交评分",
diff --git a/app/javascript/widget/i18n/locale/zh_TW.json b/app/javascript/widget/i18n/locale/zh_TW.json
index bd401a8ca..bfc737d91 100644
--- a/app/javascript/widget/i18n/locale/zh_TW.json
+++ b/app/javascript/widget/i18n/locale/zh_TW.json
@@ -106,6 +106,11 @@
"NOT_FOUND": "查無相符的 emoji",
"ARIA_LABEL": "表情選擇"
},
+ "EMOJI_ICON_PICKER": {
+ "SEARCH_EMOJI": "Search emoji…",
+ "FREQUENTLY_USED": "Frequently used",
+ "NO_EMOJI": "找不到符合的表情符號"
+ },
"CSAT": {
"TITLE": "為此對話評分",
"SUBMITTED_TITLE": "感謝您提交的評分",
diff --git a/app/jobs/webhooks/whatsapp_events_job.rb b/app/jobs/webhooks/whatsapp_events_job.rb
index 14429e61c..f81ce242b 100644
--- a/app/jobs/webhooks/whatsapp_events_job.rb
+++ b/app/jobs/webhooks/whatsapp_events_job.rb
@@ -153,11 +153,11 @@ class Webhooks::WhatsappEventsJob < MutexApplicationJob
end
def get_channel_from_wb_payload(wb_params)
- phone_number = "+#{wb_params[:entry].first[:changes].first.dig(:value, :metadata, :display_phone_number)}"
- phone_number_id = wb_params[:entry].first[:changes].first.dig(:value, :metadata, :phone_number_id)
- channel = Channel::Whatsapp.find_by(phone_number: phone_number)
- # validate to ensure the phone number id matches the whatsapp channel
- return channel if channel && channel.provider_config['phone_number_id'] == phone_number_id
+ metadata = wb_params[:entry].first[:changes].first.dig(:value, :metadata) || {}
+ Whatsapp::WebhookChannelFinderService.new(
+ display_phone_number: metadata[:display_phone_number],
+ phone_number_id: metadata[:phone_number_id]
+ ).perform
end
end
diff --git a/app/services/whatsapp/incoming_message_base_service.rb b/app/services/whatsapp/incoming_message_base_service.rb
index 00936ff15..09632c5b1 100644
--- a/app/services/whatsapp/incoming_message_base_service.rb
+++ b/app/services/whatsapp/incoming_message_base_service.rb
@@ -113,12 +113,14 @@ class Whatsapp::IncomingMessageBaseService
end
def set_conversation
+ # Scope reuse to the contact across all its contact_inboxes in this inbox: WhatsApp coexistence
+ # gives one contact multiple source_ids (phone + BSUID), so reopen must not be limited to a single contact_inbox.
+ conversations = @contact.conversations.where(inbox_id: @inbox.id)
# if lock to single conversation is disabled, we will create a new conversation if previous conversation is resolved
@conversation = if @inbox.lock_to_single_conversation
- @contact_inbox.conversations.last
+ conversations.last
else
- @contact_inbox.conversations
- .where.not(status: :resolved).last
+ conversations.where.not(status: :resolved).last
end
return if @conversation
diff --git a/app/services/whatsapp/send_on_whatsapp_service.rb b/app/services/whatsapp/send_on_whatsapp_service.rb
index 20419c0cd..b8de35d1c 100644
--- a/app/services/whatsapp/send_on_whatsapp_service.rb
+++ b/app/services/whatsapp/send_on_whatsapp_service.rb
@@ -6,12 +6,10 @@ class Whatsapp::SendOnWhatsappService < Base::SendOnChannelService
end
def perform_reply
- should_send_template_message = template_params.present? || !message.conversation.can_reply?
- if should_send_template_message
- send_template_message
- else
- send_session_message
- end
+ return send_template_message if template_params.present?
+ return send_session_message if message.conversation.can_reply?
+
+ message.update!(status: :failed, external_error: I18n.t('errors.whatsapp.message_outside_messaging_window'))
end
def send_template_message
diff --git a/app/services/whatsapp/webhook_channel_finder_service.rb b/app/services/whatsapp/webhook_channel_finder_service.rb
new file mode 100644
index 000000000..32fe8356f
--- /dev/null
+++ b/app/services/whatsapp/webhook_channel_finder_service.rb
@@ -0,0 +1,35 @@
+# Resolves the WhatsApp channel for an inbound WhatsApp Cloud webhook. Meta's
+# display_phone_number can arrive formatted or in a country-specific variant (e.g. Brazil
+# omits the mobile 9, Argentina adds a digit after the country code), so we try the
+# raw digits first and then a normalized fallback, accepting only a candidate whose
+# phone_number_id matches.
+class Whatsapp::WebhookChannelFinderService
+ def initialize(display_phone_number:, phone_number_id:)
+ @display_phone_number = display_phone_number
+ @phone_number_id = phone_number_id
+ end
+
+ def perform
+ return if digits.blank?
+
+ candidates = [
+ Channel::Whatsapp.find_by(phone_number: "+#{digits}"),
+ channel_by_normalized_number
+ ]
+ candidates.compact.find { |channel| channel.provider_config['phone_number_id'] == @phone_number_id }
+ end
+
+ private
+
+ def digits
+ @digits ||= @display_phone_number.to_s.gsub(/[^0-9]/, '')
+ end
+
+ def channel_by_normalized_number
+ normalizer = Whatsapp::PhoneNumberNormalizationService::NORMALIZERS
+ .lazy.map(&:new).find { |n| n.handles_country?(digits) }
+ return unless normalizer
+
+ Channel::Whatsapp.find_by(phone_number: "+#{normalizer.normalize(digits)}")
+ end
+end
diff --git a/app/views/layouts/vueapp.html.erb b/app/views/layouts/vueapp.html.erb
index 954be9c29..146f1ebda 100644
--- a/app/views/layouts/vueapp.html.erb
+++ b/app/views/layouts/vueapp.html.erb
@@ -6,9 +6,9 @@
<% if @global_config['DISPLAY_MANIFEST'] %>
-
+
-
+
<% if ENV['IOS_APP_IDENTIFIER'].present? %>
'>
diff --git a/config/app.yml b/config/app.yml
index a55b621f6..085af6efb 100644
--- a/config/app.yml
+++ b/config/app.yml
@@ -1,5 +1,5 @@
shared: &shared
- version: '4.15.1'
+ version: '4.16.0'
development:
<<: *shared
diff --git a/config/features.yml b/config/features.yml
index 590f28814..950d6e7c5 100644
--- a/config/features.yml
+++ b/config/features.yml
@@ -265,6 +265,6 @@
enabled: false
column: feature_flags_ext_1
- name: whatsapp_embedded_signup_inbox_creation
- display_name: WhatsApp Embedded Signup Inbox Creation
+ display_name: WhatsApp Embedded Signup Flow
enabled: false
column: feature_flags_ext_1
diff --git a/config/initializers/languages.rb b/config/initializers/languages.rb
index 183a0e54e..c9fbcb8a7 100644
--- a/config/initializers/languages.rb
+++ b/config/initializers/languages.rb
@@ -43,7 +43,8 @@ LANGUAGES_CONFIG = {
38 => { name: 'lietuvių (lt)', iso_639_3_code: 'lit', iso_639_1_code: 'lt', enabled: true },
39 => { name: 'Српски (sr)', iso_639_3_code: 'srp', iso_639_1_code: 'sr', enabled: true },
40 => { name: 'български (bg)', iso_639_3_code: 'bul', iso_639_1_code: 'bg', enabled: true },
- 41 => { name: 'Eesti keel (et)', iso_639_3_code: 'est', iso_639_1_code: 'et', enabled: true }
+ 41 => { name: 'Eesti keel (et)', iso_639_3_code: 'est', iso_639_1_code: 'et', enabled: true },
+ 42 => { name: 'Oʻzbekcha (uz)', iso_639_3_code: 'uzb', iso_639_1_code: 'uz', enabled: true }
}.filter { |_key, val| val[:enabled] }.freeze
Rails.configuration.i18n.available_locales = LANGUAGES_CONFIG.map { |_index, lang| lang[:iso_639_1_code].to_sym }
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb
index e08a6a6e1..caf49c047 100644
--- a/config/initializers/rack_attack.rb
+++ b/config/initializers/rack_attack.rb
@@ -31,10 +31,11 @@ class Rack::Attack
(default_allowed_ips + env_allowed_ips).include?(remote_ip)
end
- # Rails would allow requests to paths with extensions, so lets compare against the path with extension stripped
- # example /auth & /auth.json would both work
+ # Rails allows paths with extensions and trailing slashes, so compare against a normalized path.
+ # For example, /auth, /auth.json, and /auth/ should all use the same throttle.
def path_without_extensions
- path[/^[^.]+/]
+ normalized_path = path[/^[^.]+/]
+ normalized_path == '/' ? normalized_path : normalized_path.sub(%r{/+\z}, '')
end
end
@@ -188,6 +189,11 @@ class Rack::Attack
throttle('widget?website_token={website_token}&cw_conversation={x-auth-token}', limit: 5, period: 1.hour) do |req|
req.ip if req.path_without_extensions == '/widget' && ActionDispatch::Request.new(req.env).params['cw_conversation'].blank?
end
+
+ ## Prevent Transcript Bombing on Widget API ###
+ throttle('api/v1/widget/conversations/transcript', limit: 5, period: 1.hour) do |req|
+ req.ip if req.path_without_extensions == '/api/v1/widget/conversations/transcript' && req.post?
+ end
end
##-----------------------------------------------##
@@ -212,6 +218,24 @@ class Rack::Attack
match_data[:account_id] if match_data.present?
end
+ ## Prevent abuse of agent create APIs (per account, covers bulk_create)
+ throttle('/api/v1/accounts/:account_id/agents POST',
+ limit: ENV.fetch('RATE_LIMIT_AGENT_CREATE', '100').to_i, period: 1.day) do |req|
+ next unless req.post?
+
+ match_data = %r{\A/api/v1/accounts/(?\d+)/agents(?:/bulk_create)?/?\z}.match(req.path_without_extensions)
+ match_data[:account_id] if match_data.present?
+ end
+
+ ## Prevent abuse of agent delete API (per account)
+ throttle('/api/v1/accounts/:account_id/agents/:id DELETE',
+ limit: ENV.fetch('RATE_LIMIT_AGENT_DELETE', '50').to_i, period: 1.day) do |req|
+ next unless req.delete?
+
+ match_data = %r{\A/api/v1/accounts/(?\d+)/agents/(?\d+)/?\z}.match(req.path_without_extensions)
+ match_data[:account_id] if match_data.present?
+ end
+
## Prevent Abuse of attachment upload APIs ##
throttle('/api/v1/accounts/:account_id/upload', limit: 60, period: 1.hour) do |req|
match_data = %r{/api/v1/accounts/(?\d+)/upload}.match(req.path)
diff --git a/config/locales/am.yml b/config/locales/am.yml
index 70c1310af..252dd6237 100644
--- a/config/locales/am.yml
+++ b/config/locales/am.yml
@@ -33,8 +33,33 @@ am:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ am:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ am:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ am:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ am:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ am:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ am:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ am:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'ነባሪ'
+ features:
+ editor: 'Editor'
+ assistant: 'አስማሪ'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 3882666eb..5dbdc3806 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -33,8 +33,33 @@ ar:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: سيتم معالجة طلب حذف صندوق الوارد الخاص بك في بعض الوقت.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ar:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: نوع البيانات غير صالح
@@ -92,6 +122,15 @@ ar:
unique: يجب أن تكون فريدة من نوعها في الفئة والبوابة
dyte:
invalid_message_type: 'نوع الرسالة غير صالح. الإجراء غير مسموح به'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'قناة Slack غير صحيحة. الرجاء المحاولة مرة أخرى'
whatsapp:
@@ -104,6 +143,7 @@ ar:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ar:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -329,9 +372,9 @@ ar:
name: 'تطبيقات لوحة التحكم'
description: 'تسمح لك تطبيقات لوحة التحكم بإنشاء وتضمين التطبيقات التي تعرض معلومات المستخدم أو الطلبات أو سجل الدفع، مما يوفر المزيد من السياق لوكلاء دعم العملاء الخاص بك.'
dyte:
- name: 'Dyte'
+ name: 'Cloudflare RealtimeKit'
short_description: 'Start video/voice calls with customers directly from Chatwoot.'
- description: 'Dyte هو منتج يدمج وظائف الصوت والفيديو في تطبيقك. مع هذا الدمج، يمكن لوكلائك بدء مكالمات الفيديو/الصوت مع عملائك مباشرة من Chatwoot.'
+ description: 'يتيح Cloudflare RealtimeKit لوكلائك بَدْء مكالمات فيديو أو صوت مع عملائك مباشرةً من Chatwoot.'
meeting_name: 'بدأ %{agent_name} اجتماعاً'
slack:
name: 'Slack'
@@ -438,7 +481,10 @@ ar:
browse_by_topic_subtitle: اعثر على أدلة ودروس وأجوبة منظمة حسب الفئة.
popular_articles: المقالات الشائعة
popular_articles_subtitle: ما يقرأه الآخرون الآن.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'مواضيع شائعة:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} و %{count} آخرون"
primary_nav: التنقل الرئيسي
hero:
@@ -474,6 +520,7 @@ ar:
light: فاتح
dark: مظلم
featured_articles: المقالات المميزة
+ recommended: Recommended articles
uncategorized: غير مصنف
404:
title: لم يتم العثور على الصفحة
@@ -564,6 +611,29 @@ ar:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'نموذج'
+ sources:
+ account_override: 'Account override'
+ default: 'افتراضي'
+ features:
+ editor: 'Editor'
+ assistant: 'مساعد'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'لم يتم العثور على المستخدم.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/az.yml b/config/locales/az.yml
index fe51b907d..3d8d5264c 100644
--- a/config/locales/az.yml
+++ b/config/locales/az.yml
@@ -33,8 +33,33 @@ az:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ az:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ az:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ az:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ az:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ az:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ az:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ az:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Defolt'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index e2674edda..bb98fbd44 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -33,8 +33,33 @@ bg:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ bg:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ bg:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ bg:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ bg:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ bg:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ bg:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ bg:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Асистент'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/bn.yml b/config/locales/bn.yml
index fb88cd27b..94c76a96e 100644
--- a/config/locales/bn.yml
+++ b/config/locales/bn.yml
@@ -33,8 +33,33 @@ bn:
login_saml_user: এই অ্যাকাউন্টটি SAML প্রমাণীকরণ ব্যবহার করে। অনুগ্রহ করে আপনার প্রতিষ্ঠানের SAML প্রদানকারীর মাধ্যমে সাইন ইন করুন।.
saml_not_available: এই ইনস্টলেশনে SAML প্রমাণীকরণ উপলব্ধ নয়।.
inbox_deletetion_response: আপনার ইনবক্স মুছে ফেলার অনুরোধ কিছু সময়ের মধ্যে প্রক্রিয়াকরণ করা হবে।.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: বৈধ টাইমজোন নয়
support_email:
@@ -64,9 +89,14 @@ bn:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: এই অ্যাকাউন্টের জন্য SAML ফিচার সক্রিয় নয়
sso_not_enabled: এই ইনস্টলেশনের জন্য SAML SSO সক্রিয় করা হয়নি
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: অবৈধ ডেটা টাইপ
@@ -92,6 +122,15 @@ bn:
unique: ক্যাটাগরি ও পোর্টালে অবশ্যই ইউনিক হতে হবে
dyte:
invalid_message_type: 'অবৈধ বার্তার ধরন। এই কার্যক্রম অনুমোদিত নয়'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'অবৈধ Slack চ্যানেল। অনুগ্রহ করে আবার চেষ্টা করুন।'
whatsapp:
@@ -104,6 +143,7 @@ bn:
not_supported: 'এই ধরনের WhatsApp চ্যানেলের জন্য পুনরায় অনুমোদন সমর্থিত নয়।.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ bn:
invalid_token: ভুল বা মেয়াদোত্তীর্ণ MFA টোকেন
invalid_credentials: ভুল শংসাপত্র বা যাচাইকরণ কোড
feature_unavailable: MFA ফিচারটি উপলব্ধ নয়। অনুগ্রহ করে এনক্রিপশন কী কনফিগার করুন।.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: ক্রেডিটের পরিমাণ আবশ্যক
invalid_credits: অবৈধ ক্রেডিটের পরিমাণ
@@ -434,7 +477,10 @@ bn:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ bn:
light: হালকা
dark: গাঢ়
featured_articles: ফিচার্ড প্রবন্ধ
+ recommended: Recommended articles
uncategorized: বিনাশ্রেণীভুক্ত
404:
title: পৃষ্ঠা খুঁজে পাওয়া যায়নি
@@ -544,6 +591,29 @@ bn:
ssl_status:
custom_domain_not_configured: 'কাস্টম ডোমেইন কনফিগার করা হয়নি'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'ডিফল্ট'
+ features:
+ editor: 'Editor'
+ assistant: 'সহকারী'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index ebf894da2..a026715a2 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -33,8 +33,33 @@ ca:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: La teva sol·licitud d'eliminació de la safata d'entrada es processarà d'aquí a un temps.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ca:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Tipus de dades no vàlid
@@ -92,6 +122,15 @@ ca:
unique: hauria de ser únic a la categoria i al portal
dyte:
invalid_message_type: 'Tipus de missatge no vàlid. Acció no permesa'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Canal slack no vàlid. Torna-ho a provar'
whatsapp:
@@ -104,6 +143,7 @@ ca:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ca:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ca:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ca:
light: Clar
dark: Fosc
featured_articles: Articles destacats
+ recommended: Recommended articles
uncategorized: Sense categoria
404:
title: Pàgina no trobada
@@ -544,6 +591,29 @@ ca:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Per defecte'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 5e6315000..d40104675 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -33,8 +33,33 @@ cs:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ cs:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ cs:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ cs:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ cs:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ cs:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ cs:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -554,6 +601,29 @@ cs:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 43d291bfc..7aa9e8926 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -33,8 +33,33 @@ da:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ da:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Ugyldig datatype
@@ -92,6 +122,15 @@ da:
unique: bør være unik i kategorien og portalen
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ da:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ da:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ da:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ da:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Ikke Kategoriseret
404:
title: Page not found
@@ -544,6 +591,29 @@ da:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Standard'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/de.yml b/config/locales/de.yml
index ddf1ad052..80cc08b3e 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -33,8 +33,33 @@ de:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Die Löschanfrage Ihres Posteingangs wird in Kürze bearbeitet.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -51,7 +76,7 @@ de:
invalid_params: 'Ungültig, bitte überprüfen Sie die Anmeldeparameter und versuchen Sie es erneut'
failed: Anmeldung gescheitert
voice:
- call_already_accepted: '%{agent_name} is already handling the call.'
+ call_already_accepted: 'Dieser Anruf wird bereits von %{agent_name} betreut.'
assignment_policy:
not_found: Assignment policy not found
attachments:
@@ -64,9 +89,14 @@ de:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Ungültiger Datentyp
@@ -92,6 +122,15 @@ de:
unique: sollte in der Kategorie und im Portal eindeutig sein
dyte:
invalid_message_type: 'Ungültiger Nachrichtentyp. Aktion nicht erlaubt'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Ungültiger Slack Channel. Bitte erneut versuchen'
whatsapp:
@@ -104,6 +143,7 @@ de:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ de:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ de:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ de:
light: Hell
dark: Dunkel
featured_articles: Empfohlene Artikel
+ recommended: Recommended articles
uncategorized: Unkategorisiert
404:
title: Seite nicht gefunden
@@ -544,6 +591,29 @@ de:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Modell'
+ sources:
+ account_override: 'Account override'
+ default: 'Standard'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/devise.uz.yml b/config/locales/devise.uz.yml
new file mode 100644
index 000000000..5f83eefdc
--- /dev/null
+++ b/config/locales/devise.uz.yml
@@ -0,0 +1,61 @@
+#Additional translations at https://github.com/plataformatec/devise/wiki/I18n
+uz:
+ devise:
+ confirmations:
+ confirmed: "Your email address has been successfully confirmed."
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
+ failure:
+ already_authenticated: "You are already signed in."
+ inactive: "Your account is not activated yet."
+ invalid: "Invalid %{authentication_keys}/password or account is not verified yet."
+ locked: "Your account is locked."
+ last_attempt: "You have one more attempt before your account is locked."
+ not_found_in_database: "Invalid %{authentication_keys} or password."
+ timeout: "Your session expired. Please sign in again to continue."
+ unauthenticated: "You need to sign in or sign up before continuing."
+ unconfirmed: "You have to confirm your email address before continuing."
+ mailer:
+ confirmation_instructions:
+ subject: "Confirmation Instructions"
+ reset_password_instructions:
+ subject: "Reset password instructions"
+ unlock_instructions:
+ subject: "Unlock instructions"
+ password_change:
+ subject: "Password Changed"
+ omniauth_callbacks:
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
+ success: "Successfully authenticated from %{kind} account."
+ passwords:
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
+ updated: "Your password has been changed successfully. You are now signed in."
+ updated_not_active: "Your password has been changed successfully."
+ registrations:
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
+ signed_up: "Welcome! You have signed up successfully."
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
+ updated: "Your account has been updated successfully."
+ sessions:
+ signed_in: "Signed in successfully."
+ signed_out: "Signed out successfully."
+ already_signed_out: "Signed out successfully."
+ unlocks:
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ errors:
+ messages:
+ already_confirmed: "was already confirmed, please try signing in"
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
+ expired: "has expired, please request a new one"
+ not_found: "not found"
+ not_locked: "was not locked"
+ not_saved:
+ one: "1 error prohibited this %{resource} from being saved:"
+ other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 153bb5c89..6f35eb7f8 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -33,8 +33,33 @@ el:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ el:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Μη έγκυρος τύπος δεδομένων
@@ -92,6 +122,15 @@ el:
unique: πρέπει να είναι μοναδικό στην κατηγορία και την πύλη
dyte:
invalid_message_type: 'Μη έγκυρος τύπος μηνύματος. Δεν επιτρέπεται η ενέργεια'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ el:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ el:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ el:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ el:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ el:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Μοντέλο'
+ sources:
+ account_override: 'Account override'
+ default: 'Προεπιλογή'
+ features:
+ editor: 'Editor'
+ assistant: 'Βοηθός'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 735d52205..1efae55e1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -154,6 +154,7 @@ en:
invalid_token_permissions: 'The access token does not have the required permissions for WhatsApp.'
phone_info_fetch_failed: 'Failed to fetch phone number information. Please try again.'
phone_number_already_exists: 'Channel already exists for this phone number: %{phone_number}, please contact support if the error persists'
+ message_outside_messaging_window: 'Message not sent because the WhatsApp 24-hour customer service window is closed and no template parameters were provided. Send an approved template message instead.'
reauthorization:
generic: 'Failed to reauthorize WhatsApp. Please try again.'
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
diff --git a/config/locales/es.yml b/config/locales/es.yml
index c5a17fc79..dcd7652fb 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -33,8 +33,33 @@ es:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Su solicitud de eliminación de la bandeja de entrada será procesada en algún tiempo.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} asignó la conversación'
+ assignment_with_target: '%{actor} asignó la conversación a %{target}'
+ assign_and_reopen: '%{actor} asignado y reabierto la conversación'
+ assign_and_reopen_with_target: '%{actor} asignó la conversación a %{target} y la reabrió'
+ open: '%{actor} abrió la conversación'
+ close: '%{actor} cerró la conversación'
+ snoozed: '%{actor} silenció la conversación'
+ participant_added: '%{actor} agregó un participante'
+ participant_added_with_target: '%{actor} agregó a %{target} como participante'
+ participant_removed: '%{actor} eliminó un participante'
+ participant_removed_with_target: '%{actor} eliminó %{target} como participante'
+ conversation_attribute_updated: '%{actor} actualizó los atributos de la conversación'
+ ticket_attribute_updated: '%{actor} actualizó los atributos del ticket'
+ ticket_state_updated: '%{actor} actualizó el estado del ticket'
+ custom_action_started: '%{actor} inició una acción personalizada'
+ custom_action_finished: '%{actor} terminó una acción personalizada'
+ quick_reply: '%{actor} usó una respuesta rápida'
+ generic: '%{actor} grabado %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: No puede revocar la sesión actual.
errors:
account:
+ not_authorized: No está autorizado a acceder a esta cuenta
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -51,7 +76,7 @@ es:
invalid_params: 'Inválido, por favor comprueba los parámetros de registro e inténtalo de nuevo'
failed: Registro fallido
voice:
- call_already_accepted: '%{agent_name} is already handling the call.'
+ call_already_accepted: '%{agent_name} ya está gestionando la llamada.'
assignment_policy:
not_found: Assignment policy not found
attachments:
@@ -64,9 +89,14 @@ es:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'La solicitud tardó demasiado en completarse. Por favor, inténtalo de nuevo.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Función de contadores no leídos de conversación no habilitada para esta cuenta
data_import:
data_type:
invalid: Tipo de datos no válido
@@ -92,6 +122,15 @@ es:
unique: debe ser único en la categoría y el portal
dyte:
invalid_message_type: 'Tipo de mensaje inválido. Acción no permitida'
+ realtimekit_credentials_required: 'Las credenciales de Cloudflare RealtimeKit son requeridas. Elimina la integración existente de Dyte y vuelve a crearla con las credenciales Cloudflare RealtimeKit.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Las credenciales de Cloudflare RealtimeKit no son válidas. Por favor, comprueba el ID de cuenta, el ID de la aplicación RealtimeKit y los permisos de token de la API.'
+ missing_credentials: 'ID de la cuenta Cloudflare, ID de la aplicación RealtimeKit, y token API son requeridos.'
+ invalid_api_token: 'El token de la API de Cloudflare no es válido o está inactivo. Por favor, crea un nuevo token con permisos de administración de tiempo real.'
+ invalid_account_or_permissions: 'El ID de cuenta de Cloudflare no es válido, o el token de la API no tiene acceso de Administrador de tiempo real a esta cuenta.'
+ app_not_found: 'El ID de la aplicación RealtimeKit no se ha encontrado en esta cuenta Cloudflare. Por favor, comprueba la aplicación seleccionada.'
+ verification_failed: 'No se han podido verificar las credenciales de Cloudflare RealtimeKit en este momento. Por favor, inténtalo de nuevo.'
slack:
invalid_channel_id: 'Canal de slack inválido. Por favor, inténtalo de nuevo'
whatsapp:
@@ -103,14 +142,15 @@ es:
generic: 'Failed to reauthorize WhatsApp. Please try again.'
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
- not_enabled: 'Calling is not enabled for this inbox'
- no_recording: 'No recording file provided'
- no_message: 'Call has no associated message'
- sdp_offer_required: 'sdp_offer is required'
- contact_phone_required: 'Contact phone number is required'
- permission_request_failed: 'Failed to send call permission request'
+ not_enabled: 'Llamada no está habilitada para esta bandeja de entrada'
+ already_ended: 'Esta llamada ya ha finalizado'
+ no_recording: 'Ningún archivo de grabación proporcionado'
+ no_message: 'La llamada no tiene ningún mensaje asociado'
+ sdp_offer_required: 'sdp_offer es requerido'
+ contact_phone_required: 'Se requiere un número de teléfono de contacto'
+ permission_request_failed: 'Error al enviar la solicitud de permiso de llamada'
openai:
- invalid_api_key: 'OpenAI API key is invalid or revoked. Please check your key in your OpenAI dashboard.'
+ invalid_api_key: 'La clave API OpenAI no es válida o revocada. Por favor, compruebe su clave en su panel de control OpenAI.'
inboxes:
imap:
socket_error: Verifique la conexión de red, la dirección IMAP y vuelva a intentarlo.
@@ -142,6 +182,9 @@ es:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Moneda de facturación no válida
+ currency_locked: La moneda de facturación no se puede cambiar después de que se haya configurado la facturación
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -240,11 +283,11 @@ es:
deleted: Este mensaje se ha eliminado
whatsapp:
list_button_label: 'Choose an item'
- call_permission_request_body: 'We would like to call you regarding your conversation.'
- unsupported_message: 'This message is unavailable.'
+ call_permission_request_body: 'Nos gustaría llamarte en relación con tu conversación.'
+ unsupported_message: 'Este mensaje no está disponible.'
voice_call:
- twilio: 'Voice Call'
- whatsapp: 'WhatsApp Call'
+ twilio: 'Llamada de voz'
+ whatsapp: 'Llamada de WhatsApp'
delivery_status:
error_code: 'Código de error: %{error_code}'
activity:
@@ -290,8 +333,8 @@ es:
issue_linked: 'Linear issue %{issue_id} was linked by %{user_name}'
issue_unlinked: 'Linear issue %{issue_id} was unlinked by %{user_name}'
whatsapp_call:
- permission_requested: 'Sent a call permission request to %{contact_name}.'
- permission_granted: '%{contact_name} accepted the call permission request.'
+ permission_requested: 'Envió una solicitud de permiso de llamada a %{contact_name}.'
+ permission_granted: '%{contact_name} ha aceptado la solicitud de permiso de llamada.'
csat:
not_sent_due_to_messaging_window: 'CSAT survey not sent due to outgoing message restrictions'
auto_resolve:
@@ -356,7 +399,7 @@ es:
name: 'Lineal'
short_description: 'Create and link Linear issues directly from conversations.'
description: 'Crea problemas en Linear directamente desde tu ventana de conversación. Alternativamente, enlaza problemas existentes en Linear para un proceso de seguimiento de problemas más eficiente y ágil.'
- attachment_link_title: 'Conversation (#%{conversation_id}) with %{name}'
+ attachment_link_title: 'Conversación (%{conversation_id}) con %{name}'
notion:
name: 'Notion'
short_description: 'Integrate databases, documents and pages directly with Captain.'
@@ -385,9 +428,9 @@ es:
limit_exceeded: 'Document limit exceeded'
pdf_format_error: 'must be a PDF file'
pdf_size_error: 'must be less than 10MB'
- sync_not_supported_for_pdf: 'Sync is not supported for PDF documents'
- sync_only_available_documents: 'Sync is only available for processed documents'
- sync_already_in_progress: 'Document sync is already in progress'
+ sync_not_supported_for_pdf: 'La sincronización no es compatible con documentos PDF'
+ sync_only_available_documents: 'La sincronización sólo está disponible para documentos procesados'
+ sync_already_in_progress: 'La sincronización de documentos ya está en progreso'
pdf_upload_failed: 'Failed to upload PDF to OpenAI'
pdf_upload_success: 'PDF uploaded successfully with file_id: %{file_id}'
pdf_processing_failed: 'Failed to process PDF document %{document_id}: %{error}'
@@ -414,29 +457,32 @@ es:
loading_placeholder: Buscando...
results_title: Buscar resultados
results: Buscar resultados
- results_for: "Search Results for '%{query}'"
- no_results: "No results found for '%{query}'"
+ results_for: "Resultados de búsqueda para '%{query}'"
+ no_results: "No se han encontrado resultados para '%{query}'"
found_results:
- one: Found 1 result
- other: 'Found %{count} results'
+ one: Se encontró 1 resultado
+ other: 'Se encontraron %{count} resultados'
submit: Buscar
toc_header: 'En esta página'
sidebar:
help_center: Centro de ayuda
categories: Categorías
language: Idioma
- theme: Theme
+ theme: Tema
open_sidebar: Abrir barra lateral
close_sidebar: Cerrar barra lateral
- browse: Browse
- back_to_category: Back to %{name}
- browse_by_topic: Browse by topic
- browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
- popular_articles: Popular articles
- popular_articles_subtitle: What other people are reading right now.
- popular_label: 'Popular topics:'
- authors_others: "%{names} and %{count} others"
- primary_nav: Primary
+ browse: Navegar
+ back_to_category: Regresar a %{name}
+ browse_by_topic: Navegar por tema
+ browse_by_topic_subtitle: Encuentra guías, tutoriales y respuestas organizadas por categoría.
+ popular_articles: Artículos populares
+ popular_articles_subtitle: Lo que otras personas están leyendo ahora mismo.
+ recommended: Artículos recomendados
+ recommended_subtitle: Artículos elegidos a mano para empezar.
+ popular_label: 'Temas populares:'
+ recommended_label: 'Temas recomendados:'
+ authors_others: "%{names} y %{count} otros"
+ primary_nav: Primario
hero:
sub_title: Busque aquí los artículos o busque las categorías de abajo.
common:
@@ -454,11 +500,11 @@ es:
previous: Anterior
next: Siguiente
article_actions:
- label: Open in
- view_markdown: View as Markdown
- open_in_chatgpt: Open in ChatGPT
- open_in_claude: Open in Claude
- llm_prompt: "Read the following article and help me understand it: %{url}"
+ label: Abrir en
+ view_markdown: Ver como Markdown
+ open_in_chatgpt: Abrir en ChatGPT
+ open_in_claude: Abrir en Claude
+ llm_prompt: "Lee el siguiente artículo y ayúdame a entenderlo: %{url}"
footer:
made_with: Hecho con
header:
@@ -470,6 +516,7 @@ es:
light: Claro
dark: Oscuro
featured_articles: Artículos destacados
+ recommended: Artículos recomendados
uncategorized: Sin categoría
404:
title: Página no encontrada
@@ -530,11 +577,11 @@ es:
inbox_already_assigned: 'Inbox has already been assigned to this policy'
portals:
articles:
- captain_not_available: 'Translation requires Captain to be enabled for this account'
- locale_not_available: 'Locale not available in this portal'
- category_not_found: 'Category not found in this portal'
- no_articles_found: 'No articles found to process'
- invalid_status: 'Invalid status value'
+ captain_not_available: 'La traducción requiere que el Capitán esté habilitado para esta cuenta'
+ locale_not_available: 'Locale no disponible en este portal'
+ category_not_found: 'Categoría no encontrada en este portal'
+ no_articles_found: 'No hay artículos para procesar'
+ invalid_status: 'Valor de estado inválido'
send_instructions:
email_required: 'El email es requerido'
invalid_email_format: 'Invalid email format'
@@ -544,8 +591,31 @@ es:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Deje un modelo en blanco para usar el valor por defecto de YAML para esa función de IA.'
+ use_default: 'Usar por defecto: %{model} (%{model_id})'
+ show:
+ summary: 'Ver ruta del modelo'
+ provider: 'Proveedor'
+ model: 'Modelo'
+ sources:
+ account_override: 'Anulación de cuenta'
+ default: 'Predeterminado'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistente'
+ copilot: 'Copilot'
+ label_suggestion: 'Sugerencia de etiqueta'
+ document_faq_generation: 'Generación de FAQ de documentos'
+ conversation_faq_generation: 'Generación de FAQ de conversación'
+ help_center_article_generation: 'Centro de ayuda para la generación de artículos'
+ onboarding_content_generation: 'Generación de contenidos integrados'
+ help_center_query_translation: 'Traducción de consultas al centro de ayuda'
+ audio_transcription: 'Transcripción de audio'
+ help_center_search: 'Centro de búsqueda de ayuda'
push_diagnostics:
- user_not_found: 'User not found.'
- no_subscriptions_to_test: 'Select at least one subscription to test.'
- no_subscriptions_to_delete: 'Select at least one subscription to delete.'
- subscriptions_deleted: "Deleted %{count} subscription(s). The user's device(s) will re-register on next app launch."
+ user_not_found: 'Usuario no encontrado.'
+ no_subscriptions_to_test: 'Seleccione al menos una suscripción para probar.'
+ no_subscriptions_to_delete: 'Seleccione al menos una suscripción a eliminar.'
+ subscriptions_deleted: "Suscripción(es) %{count} eliminada(s). El dispositivo(s) del usuario volverá a registrarse en el próximo lanzamiento de la aplicación."
diff --git a/config/locales/et.yml b/config/locales/et.yml
index 4a846374e..1b861c587 100644
--- a/config/locales/et.yml
+++ b/config/locales/et.yml
@@ -33,8 +33,33 @@ et:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ et:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Vigane andmetüüp
@@ -92,6 +122,15 @@ et:
unique: peab olema kategoorias ja portaalis unikaalne
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ et:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ et:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ et:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ et:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ et:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Vaikimisi'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Kaassõitja'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 4e6e2e492..e836d6c72 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -33,8 +33,33 @@ fa:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: درخواست حذف صندوق ورودی شما پس از مدتی پردازش خواهد شد.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ fa:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: نوع داده نامعتبر است
@@ -92,6 +122,15 @@ fa:
unique: باید منحصر به فرد در دستهبندی و پورتال باشد
dyte:
invalid_message_type: 'نوع پیام نامعتبر است. اقدام مجاز نیست'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'کانال اسلک نامعتبر است. لطفا دوباره تلاش کنید'
whatsapp:
@@ -104,6 +143,7 @@ fa:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ fa:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ fa:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ fa:
light: روشن
dark: تیره
featured_articles: مقالات برگزیده
+ recommended: Recommended articles
uncategorized: دسته بندی نشده
404:
title: صفحه یافت نشد
@@ -544,6 +591,29 @@ fa:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'مدل'
+ sources:
+ account_override: 'Account override'
+ default: 'پیشفرض'
+ features:
+ editor: 'Editor'
+ assistant: 'دستیار'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 3317f547e..6aa94436a 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -33,8 +33,33 @@ fi:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ fi:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ fi:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ fi:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ fi:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ fi:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ fi:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ fi:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistentti'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index b63c46cd6..ab8d0fcec 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -33,8 +33,33 @@ fr:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Votre demande de suppression de la boîte de réception sera traitée dans un certain délai.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ fr:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: La fonctionnalité de comptage des conversations non lues n'est pas activée pour ce compte
data_import:
data_type:
invalid: Type de données incorrect
@@ -92,6 +122,15 @@ fr:
unique: Doit être unique dans la catégorie et le portail
dyte:
invalid_message_type: 'Type de message invalide. Action non autorisée'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Canal Slack invalide. Veuillez réessayer'
whatsapp:
@@ -104,6 +143,7 @@ fr:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer est requis'
@@ -142,6 +182,9 @@ fr:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ fr:
browse_by_topic_subtitle: Trouvez des guides, des tutoriels et des réponses organisés par catégorie.
popular_articles: Articles populaires
popular_articles_subtitle: Ce que les autres lisent en ce moment.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Sujets populaires :'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} et %{count} autres"
primary_nav: Navigation principale
hero:
@@ -470,6 +516,7 @@ fr:
light: Clair
dark: Sombre
featured_articles: Articles à la une
+ recommended: Recommended articles
uncategorized: Non catégorisé
404:
title: Page introuvable
@@ -544,6 +591,29 @@ fr:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Modèle'
+ sources:
+ account_override: 'Account override'
+ default: 'Par défaut'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistant IA'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'Utilisateur introuvable.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/he.yml b/config/locales/he.yml
index 39ad787fc..61805dc54 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -33,8 +33,33 @@ he:
login_saml_user: חשבון זה משתמש באימות SAML. אנא התחבר דרך ספק SAML של הארגון שלך.
saml_not_available: אימות SAML אינו זמין בהתקנה זו.
inbox_deletetion_response: בקשת מחיקת תיבת הדואר הנכנס שלך תעובד בקרוב.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ he:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: תכונת SAML לא מופעלת עבור חשבון זה
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: סוג נתונים לא חוקי
@@ -92,6 +122,15 @@ he:
unique: צריך להיות ייחודי בקטגוריה ובפורטל
dyte:
invalid_message_type: 'סוג הודעה לא חוקי. פעולה אסורה'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'ערוץ Slack לא תקין. אנא נסה שוב'
whatsapp:
@@ -104,6 +143,7 @@ he:
not_supported: 'אישור מחדש אינו נתמך עבור סוג ערוץ WhatsApp זה.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ he:
invalid_token: אסימון MFA לא תקין או שפג תוקפו
invalid_credentials: פרטי התחברות או קוד אימות לא תקינים
feature_unavailable: תכונת MFA אינה זמינה. אנא הגדר מפתחות הצפנה.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ he:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ he:
light: בהיר
dark: כהה
featured_articles: מאמרים מוצעים
+ recommended: Recommended articles
uncategorized: ללא קטגוריה
404:
title: דף לא נמצא
@@ -554,6 +601,29 @@ he:
ssl_status:
custom_domain_not_configured: 'דומיין מותאם אישית לא מוגדר'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'מודל'
+ sources:
+ account_override: 'Account override'
+ default: 'ברירת מחדל'
+ features:
+ editor: 'Editor'
+ assistant: 'עוזר'
+ copilot: 'טייס משנה'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/hi.yml b/config/locales/hi.yml
index 06fabd7d5..62b5f1fd9 100644
--- a/config/locales/hi.yml
+++ b/config/locales/hi.yml
@@ -33,8 +33,33 @@ hi:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ hi:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ hi:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ hi:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ hi:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ hi:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ hi:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ hi:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'सहायक'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index 2cbae5b61..c505b9bd7 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -33,8 +33,33 @@ hr:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ hr:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ hr:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ hr:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ hr:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -435,7 +478,10 @@ hr:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -471,6 +517,7 @@ hr:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -549,6 +596,29 @@ hr:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 64133fab1..b16c92b16 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -33,8 +33,33 @@ hu:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: A beérkező üzeneteid törlésére vonatkozó kérésed nem sokára feldolgozásra kerül.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ hu:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Hibás adattípus
@@ -92,6 +122,15 @@ hu:
unique: egyedinek kell lennie a kategóriában a portálon
dyte:
invalid_message_type: 'Hibás üzenet típus. Kérés elutasítva'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Érvénytelen Slack csatorna. Kérjük, próbálja újra'
whatsapp:
@@ -104,6 +143,7 @@ hu:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ hu:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ hu:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ hu:
light: Világos mód
dark: Sötét mód
featured_articles: Kiemelt cikkek
+ recommended: Recommended articles
uncategorized: Kategorizálhatatlan
404:
title: Az oldal nem található
@@ -544,6 +591,29 @@ hu:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Alapértelmezett'
+ features:
+ editor: 'Editor'
+ assistant: 'Asszisztens'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/hy.yml b/config/locales/hy.yml
index 664459655..97991fe08 100644
--- a/config/locales/hy.yml
+++ b/config/locales/hy.yml
@@ -33,8 +33,33 @@ hy:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Ձեր մուտքի ջնջման հարցումը կմշակվի որոշ ժամանակ անց։
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ hy:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Անվավեր տվյալների տեսակ
@@ -92,6 +122,15 @@ hy:
unique: պետք է լինի եզակի կատեգորիայում և պորտալում
dyte:
invalid_message_type: 'Հաղորդագրության անվավեր տեսակ։ Գործողությունը թույլատրված չէ'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Սխալ Slack ալիք։ Խնդրում ենք փորձել կրկին'
whatsapp:
@@ -104,6 +143,7 @@ hy:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ hy:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ hy:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ hy:
light: Լուսավոր
dark: Մութ
featured_articles: Առաջարկվող հոդվածներ
+ recommended: Recommended articles
uncategorized: Առանց կատեգորիայի
404:
title: Էջը չի գտնվել
@@ -544,6 +591,29 @@ hy:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Նախնական'
+ features:
+ editor: 'Editor'
+ assistant: 'Օգնական'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/id.yml b/config/locales/id.yml
index f465157a5..bea75210f 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -33,8 +33,33 @@ id:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Permintaan penghapusan kotak masuk Anda akan diproses dalam beberapa waktu.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -51,7 +76,7 @@ id:
invalid_params: 'Invalid, please check the signup paramters and try again'
failed: Pendaftaran gagal
voice:
- call_already_accepted: '%{agent_name} is already handling the call.'
+ call_already_accepted: '%{agent_name} sudah menangani panggilan tersebut.'
assignment_policy:
not_found: Assignment policy not found
attachments:
@@ -64,9 +89,14 @@ id:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Fitur penghitung percakapan yang belum dibaca belum diaktifkan untuk akun ini
data_import:
data_type:
invalid: Jenis data tidak valid
@@ -92,6 +122,15 @@ id:
unique: harus unik dalam kategori dan portal
dyte:
invalid_message_type: 'Jenis pesan tidak valid. Tindakan tidak diizinkan'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -103,14 +142,15 @@ id:
generic: 'Failed to reauthorize WhatsApp. Please try again.'
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
- not_enabled: 'Calling is not enabled for this inbox'
- no_recording: 'No recording file provided'
- no_message: 'Call has no associated message'
- sdp_offer_required: 'sdp_offer is required'
- contact_phone_required: 'Contact phone number is required'
- permission_request_failed: 'Failed to send call permission request'
+ not_enabled: 'Panggilan tidak diaktifkan untuk kotak masuk ini'
+ already_ended: 'This call has already ended'
+ no_recording: 'Tidak ada berkas rekaman yang disediakan'
+ no_message: 'Panggilan tidak memiliki pesan terkait'
+ sdp_offer_required: 'sdp_offer diperlukan'
+ contact_phone_required: 'Nomor telepon kontak wajib diisi'
+ permission_request_failed: 'Permintaan izin panggilan gagal dikirim'
openai:
- invalid_api_key: 'OpenAI API key is invalid or revoked. Please check your key in your OpenAI dashboard.'
+ invalid_api_key: 'Kunci API OpenAI tidak sah atau dicabut. Silakan periksa kunci Anda di dasbor OpenAI Anda.'
inboxes:
imap:
socket_error: Periksa sambungan jaringan, alamat IMAP, dan coba lagi.
@@ -142,6 +182,9 @@ id:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -240,11 +283,11 @@ id:
deleted: Pesan ini telah terhapus
whatsapp:
list_button_label: 'Choose an item'
- call_permission_request_body: 'We would like to call you regarding your conversation.'
- unsupported_message: 'This message is unavailable.'
+ call_permission_request_body: 'Kami ingin menghubungi Anda terkait percakapan Anda.'
+ unsupported_message: 'Pesan ini tidak tersedia.'
voice_call:
- twilio: 'Voice Call'
- whatsapp: 'WhatsApp Call'
+ twilio: 'Panggilan Suara'
+ whatsapp: 'Panggilan WhatsApp'
delivery_status:
error_code: 'Error code: %{error_code}'
activity:
@@ -290,8 +333,8 @@ id:
issue_linked: 'Linear issue %{issue_id} was linked by %{user_name}'
issue_unlinked: 'Linear issue %{issue_id} was unlinked by %{user_name}'
whatsapp_call:
- permission_requested: 'Sent a call permission request to %{contact_name}.'
- permission_granted: '%{contact_name} accepted the call permission request.'
+ permission_requested: 'Mengirim permintaan izin panggilan ke %{contact_name}.'
+ permission_granted: '%{contact_name} menerima permintaan izin panggilan.'
csat:
not_sent_due_to_messaging_window: 'CSAT survey not sent due to outgoing message restrictions'
auto_resolve:
@@ -356,7 +399,7 @@ id:
name: 'Linear'
short_description: 'Create and link Linear issues directly from conversations.'
description: 'Create issues in Linear directly from your conversation window. Alternatively, link existing Linear issues for a more streamlined and efficient issue tracking process.'
- attachment_link_title: 'Conversation (#%{conversation_id}) with %{name}'
+ attachment_link_title: 'Percakapan (#%{conversation_id}) dengan %{name}'
notion:
name: 'Notion'
short_description: 'Integrate databases, documents and pages directly with Captain.'
@@ -385,9 +428,9 @@ id:
limit_exceeded: 'Document limit exceeded'
pdf_format_error: 'must be a PDF file'
pdf_size_error: 'must be less than 10MB'
- sync_not_supported_for_pdf: 'Sync is not supported for PDF documents'
- sync_only_available_documents: 'Sync is only available for processed documents'
- sync_already_in_progress: 'Document sync is already in progress'
+ sync_not_supported_for_pdf: 'Sinkronisasi tidak didukung untuk dokumen PDF'
+ sync_only_available_documents: 'Sinkronisasi hanya tersedia untuk dokumen yang telah diproses'
+ sync_already_in_progress: 'Sinkronisasi dokumen sedang berlangsung'
pdf_upload_failed: 'Failed to upload PDF to OpenAI'
pdf_upload_success: 'PDF uploaded successfully with file_id: %{file_id}'
pdf_processing_failed: 'Failed to process PDF document %{document_id}: %{error}'
@@ -414,8 +457,8 @@ id:
loading_placeholder: Sedang mencari...
results_title: Hasil pencarian
results: Hasil Pencarian
- results_for: "Search Results for '%{query}'"
- no_results: "No results found for '%{query}'"
+ results_for: "Hasil Pencarian untuk '%{query}'"
+ no_results: "Tidak ada hasil yang ditemukan untuk '%{query}'"
found_results:
other: 'Found %{count} results'
submit: Cari
@@ -433,7 +476,10 @@ id:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ id:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Tanpa Kategori
404:
title: Page not found
@@ -539,6 +586,29 @@ id:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Asisten'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/is.yml b/config/locales/is.yml
index 840ac4f4f..4429dfc4e 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -33,8 +33,33 @@ is:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ is:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ is:
unique: ætti að vera einstakt í flokki og gátt
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ is:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ is:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ is:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ is:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ is:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Aðstoðarmaður'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 54e2c218f..41b1c8a51 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -33,8 +33,33 @@ it:
login_saml_user: Questo account utilizza autenticazione SAML. Effettua il login dal portale SAML della tua organizzazione.
saml_not_available: Autenticazione SAML non disponibile in questa installazione.
inbox_deletetion_response: La tua richiesta di cancellazione inbox verrà elaborata.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: non è un fuso orario valido
support_email:
@@ -64,9 +89,14 @@ it:
file_too_large: 'Il file supera la dimensione massima consentita'
unsupported_content_type: 'Tipo di file non supportato (sono ammessi solo immagini e video)'
unexpected: 'Si è verificato un errore imprevisto'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: Funzionalità SAML non attiva per questo account
sso_not_enabled: SAML SSO non è abilitato per questa installazione
+ conversations:
+ unread_counts:
+ feature_not_enabled: Funzione conteggio conversazioni non lette non abilitata per questo account
data_import:
data_type:
invalid: Tipo di dato non valido
@@ -92,6 +122,15 @@ it:
unique: deve essere unico nella categoria e nel portale
dyte:
invalid_message_type: 'Tipo messaggio non valido. Azione non consentita'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Canale slack non valido. Riprova'
whatsapp:
@@ -104,13 +143,14 @@ it:
not_supported: 'La riautorizzazione non è supportata per questo tipo di canale WhatsApp.'
calls:
not_enabled: 'Le chiamate non sono abilitate per questa inbox'
+ already_ended: 'This call has already ended'
no_recording: 'Nessun file di registrazione fornito'
no_message: 'La chiamata non ha messaggi associati'
sdp_offer_required: 'sdp_offer è richiesto'
contact_phone_required: 'È richiesto il numero di telefono del contatto'
permission_request_failed: 'Impossibile inviare la richiesta di autorizzazione di chiamata'
openai:
- invalid_api_key: 'OpenAI API key is invalid or revoked. Please check your key in your OpenAI dashboard.'
+ invalid_api_key: 'La chiave API OpenAI non è valida o è revocata. Controlla la tua chiave nella dashboard OpenAI.'
inboxes:
imap:
socket_error: Controlla la connessione di rete, l'indirizzo IMAP e riprova.
@@ -142,6 +182,9 @@ it:
invalid_token: Token MFA non valido o scaduto
invalid_credentials: Credenziali o codice di verifica non validi
feature_unavailable: MFA non disponibile. Configura le chiavi di cifratura.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Quantità crediti richiesta
invalid_credits: Quantità crediti non valida
@@ -241,7 +284,7 @@ it:
whatsapp:
list_button_label: 'Scegli un elemento'
call_permission_request_body: 'Vorremmo chiamarti riguardo alla tua conversazione.'
- unsupported_message: 'This message is unavailable.'
+ unsupported_message: 'Questo messaggio non è disponibile.'
voice_call:
twilio: 'Chiamata Vocale'
whatsapp: 'Chiamata WhatsApp'
@@ -414,29 +457,32 @@ it:
loading_placeholder: Ricerca...
results_title: Risultati di ricerca
results: Risultati di Ricerca
- results_for: "Search Results for '%{query}'"
- no_results: "No results found for '%{query}'"
+ results_for: "Risultati di ricerca per '%{query}'"
+ no_results: "Nessun risultato trovato per '%{query}'"
found_results:
- one: Found 1 result
- other: 'Found %{count} results'
+ one: Trovato 1 risultato
+ other: 'Trovati %{count} risultati'
submit: Cerca
toc_header: 'Su questa pagina'
sidebar:
help_center: Help Center
categories: Categorie
language: Lingua
- theme: Theme
+ theme: Tema
open_sidebar: Apri barra laterale
close_sidebar: Chiudi barra laterale
- browse: Browse
- back_to_category: Back to %{name}
- browse_by_topic: Browse by topic
- browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
- popular_articles: Popular articles
- popular_articles_subtitle: What other people are reading right now.
- popular_label: 'Popular topics:'
- authors_others: "%{names} and %{count} others"
- primary_nav: Primary
+ browse: Esplora
+ back_to_category: Torna a %{name}
+ browse_by_topic: Esplora per argomento
+ browse_by_topic_subtitle: Trova guide, tutorial e risposte organizzate per categoria.
+ popular_articles: Articoli popolari
+ popular_articles_subtitle: Cosa leggono le altre persone in questo momento.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
+ popular_label: 'Argomenti popolari:'
+ recommended_label: 'Recommended topics:'
+ authors_others: "%{names} e %{count} altri"
+ primary_nav: Principale
hero:
sub_title: Cerca gli articoli qui oppure sfoglia le categorie qui sotto.
common:
@@ -454,11 +500,11 @@ it:
previous: Precedente
next: Successivo
article_actions:
- label: Open in
- view_markdown: View as Markdown
- open_in_chatgpt: Open in ChatGPT
- open_in_claude: Open in Claude
- llm_prompt: "Read the following article and help me understand it: %{url}"
+ label: Apri in
+ view_markdown: Visualizza come Markdown
+ open_in_chatgpt: Apri in ChatGPT
+ open_in_claude: Apri in Claude
+ llm_prompt: "Leggi il seguente articolo e aiutami a capirlo: %{url}"
footer:
made_with: Realizzato con
header:
@@ -470,6 +516,7 @@ it:
light: Chiaro
dark: Scuro
featured_articles: Articoli in evidenza
+ recommended: Recommended articles
uncategorized: Senza categoria
404:
title: Pagina non trovata
@@ -544,6 +591,29 @@ it:
ssl_status:
custom_domain_not_configured: 'Il dominio personalizzato non è configurato'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Modello'
+ sources:
+ account_override: 'Account override'
+ default: 'Predefinito'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistente'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'Utente non trovato.'
no_subscriptions_to_test: 'Seleziona almeno una subscription da testare.'
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index e6a0fbaa2..540994692 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -33,8 +33,33 @@ ja:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: 受信トレイの削除リクエストは、しばらくしてから処理されます。
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ja:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: 無効なデータ型。
@@ -92,6 +122,15 @@ ja:
unique: カテゴリとポータルで一意である必要があります
dyte:
invalid_message_type: '無効なメッセージタイプです。アクションは許可されていません'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: '無効なSlackチャンネルです。もう一度お試しください。'
whatsapp:
@@ -104,6 +143,7 @@ ja:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ja:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -433,7 +476,10 @@ ja:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ ja:
light: ライト
dark: ダーク
featured_articles: 注目の記事
+ recommended: Recommended articles
uncategorized: 未分類
404:
title: ページが見つかりません
@@ -539,6 +586,29 @@ ja:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'アシスタント'
+ copilot: 'コパイロット'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ka.yml b/config/locales/ka.yml
index 81f2921f7..b5db83e78 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -33,8 +33,33 @@ ka:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ka:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ka:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ka:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ka:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ka:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ka:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ ka:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'სტანდარტი'
+ features:
+ editor: 'Editor'
+ assistant: 'მხარდაჭერა'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index e50dac85a..dd4b8d62c 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -33,8 +33,33 @@ ko:
login_saml_user: 이 계정은 SAML 인증을 사용합니다. 조직의 SAML 제공자를 통해 로그인하십시오.
saml_not_available: 이 설치에서는 SAML 인증을 사용할 수 없습니다.
inbox_deletetion_response: 받은 메시지함 삭제 요청이 곧 처리될 예정입니다.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ko:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: 이 계정에서는 SAML 기능이 활성화되지 않았습니다
sso_not_enabled: 이 설치에서는 SAML SSO가 활성화되지 않았습니다
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: 유효하지 않은 데이터 유형
@@ -92,6 +122,15 @@ ko:
unique: 카테고리와 포털에서 고유해야 합니다
dyte:
invalid_message_type: '유효하지 않은 메시지 유형입니다. 작업이 허용되지 않습니다'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: '유효하지 않은 Slack 채널입니다. 다시 시도하십시오'
whatsapp:
@@ -104,6 +143,7 @@ ko:
not_supported: '이 유형의 WhatsApp 채널은 재인증을 지원하지 않습니다.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ko:
invalid_token: 유효하지 않거나 만료된 MFA 토큰
invalid_credentials: 유효하지 않은 자격 증명 또는 인증 코드
feature_unavailable: MFA 기능을 사용할 수 없습니다. 암호화 키를 구성하십시오.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: 크레딧 금액이 필요합니다
invalid_credits: 유효하지 않은 크레딧 금액
@@ -433,7 +476,10 @@ ko:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ ko:
light: 밝게
dark: 어둡게
featured_articles: 추천 게시물
+ recommended: Recommended articles
uncategorized: 카테고리가 지정되지 않음
404:
title: 페이지를 찾을 수 없습니다
@@ -539,6 +586,29 @@ ko:
ssl_status:
custom_domain_not_configured: '사용자 정의 도메인이 구성되지 않았습니다'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: '기본'
+ features:
+ editor: 'Editor'
+ assistant: '어시스턴트'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index eaf3ff8ff..36bd666ef 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -33,8 +33,33 @@ lt:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Jūsų gautųj laiškų aplanko ištrynimo užklausa bus apdorota po kurio laiko.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ lt:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO neįjungta šiai diegimo versijai
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Neteisingas duomenų tipas
@@ -92,6 +122,15 @@ lt:
unique: turėtų būti unikalūs kategorijoje ir portale
dyte:
invalid_message_type: 'Neteisingas pranešimo tipas. Veiksmas neleidžiamas'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ lt:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ lt:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ lt:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ lt:
light: Šviesus
dark: Tamsus
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Neįtraukta į kategorijas
404:
title: Puslapis nerastas
@@ -554,6 +601,29 @@ lt:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Pagal nutylėjimą'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistentas'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
index c8e45b2a4..5db35c120 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -33,8 +33,33 @@ lv:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Jūsu iesūtnes dzēšanas pieprasījums pēc kāda laika tiks apstrādāts.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ lv:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Nederīgs datu tips
@@ -92,6 +122,15 @@ lv:
unique: vajadzētu būt unikālai, kategorijā un portālā
dyte:
invalid_message_type: 'Nederīgs ziņojuma veids. Darbība nav atļauta'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Nepareizs Slack kanāls. Lūdzu, mēģiniet vēlreiz'
whatsapp:
@@ -104,6 +143,7 @@ lv:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ lv:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -435,7 +478,10 @@ lv:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -471,6 +517,7 @@ lv:
light: Gaišs
dark: Tumšs
featured_articles: Piedāvātie raksti
+ recommended: Recommended articles
uncategorized: Bez kategorijas
404:
title: Lapa nav atrasta
@@ -549,6 +596,29 @@ lv:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Noklusējums'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistents'
+ copilot: 'Kopilots'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ml.yml b/config/locales/ml.yml
index 7dee9f525..1ab62fc1e 100644
--- a/config/locales/ml.yml
+++ b/config/locales/ml.yml
@@ -33,8 +33,33 @@ ml:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ml:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ml:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ml:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ml:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ml:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ml:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ ml:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'ഡീഫോൾട്ട്'
+ features:
+ editor: 'Editor'
+ assistant: 'സഹായി'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ms.yml b/config/locales/ms.yml
index 095c8b9e3..71f1ec470 100644
--- a/config/locales/ms.yml
+++ b/config/locales/ms.yml
@@ -33,8 +33,33 @@ ms:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ms:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ms:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ms:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ms:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -433,7 +476,10 @@ ms:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ ms:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -539,6 +586,29 @@ ms:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Lalai'
+ features:
+ editor: 'Editor'
+ assistant: 'Pembantu'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ne.yml b/config/locales/ne.yml
index cbc3d624f..917ea7add 100644
--- a/config/locales/ne.yml
+++ b/config/locales/ne.yml
@@ -33,8 +33,33 @@ ne:
login_saml_user: यो खाता SAML प्रमाणीकरण प्रयोग गर्छ। कृपया आफ्नो संस्थाको SAML प्रदायकमार्फत साइन इन गर्नुहोस्।.
saml_not_available: यस इन्स्टलेशनमा SAML प्रमाणीकरण उपलब्ध छैन.
inbox_deletetion_response: तपाईंको पत्रपेटिका मेटाउने अनुरोध केही समयपछि प्रक्रिया हुनेछ।.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ne:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: यस खाताको लागि SAML सुविधा सक्षम गरिएको छैन
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ne:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ne:
not_supported: 'यस प्रकारको WhatsApp च्यानलमा पुन: अधिकृत समर्थन छैन।.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ne:
invalid_token: अवैध वा म्याद सकिएको MFA टोकन
invalid_credentials: अवैध प्रमाणपत्र वा प्रमाणीकरण कोड
feature_unavailable: MFA सुविधा उपलब्ध छैन। कृपया इन्क्रिप्सन कुञ्जीहरू सेटअप गर्नुहोस्।.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: क्रेडिट रकम आवश्यक छ
invalid_credits: अवैध क्रेडिट रकम
@@ -434,7 +477,10 @@ ne:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ne:
light: हल्का
dark: गाढा
featured_articles: विशेष लेखहरू
+ recommended: Recommended articles
uncategorized: वर्गीकरण नगरिएको
404:
title: पृष्ठ फेला परेन
@@ -544,6 +591,29 @@ ne:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'पूर्वनिर्धारित'
+ features:
+ editor: 'Editor'
+ assistant: 'सहायक'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 7d872bcab..aa59e8759 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -33,8 +33,33 @@ nl:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Uw verzoek tot verwijdering binnen de inbox zal binnen enige tijd worden verwerkt.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ nl:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Ongeldig datatype
@@ -92,6 +122,15 @@ nl:
unique: moet uniek zijn in de categorie en portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ nl:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ nl:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ nl:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ nl:
light: Light
dark: Dark
featured_articles: Uitgelichte artikelen
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ nl:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 5a9caa60c..5e8b957d6 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -33,8 +33,33 @@
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Innboksen din slettingsforespørsel vil bli behandlet i løpet av en periode.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Ugyldig datatype
@@ -92,6 +122,15 @@
unique: må være unikt i kategorien og portalen
dyte:
invalid_message_type: 'Ugyldig meldingstype. Handlingen er ikke tillatt'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Ugyldig slack kanal. Vennligst prøv på nytt'
whatsapp:
@@ -104,6 +143,7 @@
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index f4368c230..cb26ca412 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -33,8 +33,33 @@ pl:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Żądanie usunięcia skrzynki odbiorczej zostanie rozpatrzone za jakiś czas.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ pl:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Nieprawidłowy typ danych
@@ -92,6 +122,15 @@ pl:
unique: powinno być unikalne w kategorii i portalu
dyte:
invalid_message_type: 'Nieprawidłowy typ wiadomości. Niedozwolone działanie.'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ pl:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ pl:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ pl:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ pl:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Bez kategorii
404:
title: Page not found
@@ -554,6 +601,29 @@ pl:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Domyślny'
+ features:
+ editor: 'Editor'
+ assistant: 'Asystent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index e5cf9e883..df307b09f 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -33,8 +33,33 @@ pt:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: O seu pedido de eliminação de caixa de entrada será processado mais tarde.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ pt:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Tipo de dados inválido
@@ -92,6 +122,15 @@ pt:
unique: deve ser único na categoria e no portal
dyte:
invalid_message_type: 'Tipo de mensagem inválido. Ação não permitida'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Canal de slack inválido. Por favor, tente novamente'
whatsapp:
@@ -104,6 +143,7 @@ pt:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ pt:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ pt:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ pt:
light: Claro
dark: Escuro
featured_articles: Artigos destacados
+ recommended: Recommended articles
uncategorized: Sem categoria
404:
title: Página não encontrada
@@ -532,6 +579,29 @@ pt:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Padrão'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistente'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/pt_BR.yml b/config/locales/pt_BR.yml
index f647c2c9a..8bb6c79d6 100644
--- a/config/locales/pt_BR.yml
+++ b/config/locales/pt_BR.yml
@@ -33,8 +33,33 @@ pt_BR:
login_saml_user: Esta conta usa autenticação SAML. Por favor, faça login através do provedor SAML da sua organização.
saml_not_available: A autenticação SAML não está disponível nesta instalação.
inbox_deletetion_response: Seu pedido de exclusão da caixa de entrada será processado dentro de algum tempo.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} atribuiu a conversa'
+ assignment_with_target: '%{actor} atribuiu a conversa a %{target}'
+ assign_and_reopen: '%{actor} atribuiu e reabriu a conversa'
+ assign_and_reopen_with_target: '%{actor} atribuiu a conversa a %{target} e a reabriu'
+ open: '%{actor} abriu a conversa'
+ close: '%{actor} fechou a conversa'
+ snoozed: '%{actor} adiou a conversa'
+ participant_added: '%{actor} adicionou um participante'
+ participant_added_with_target: '%{actor} adicionou %{target} como participante'
+ participant_removed: '%{actor} removeu um usuário'
+ participant_removed_with_target: '%{actor} removeu %{target} como participante'
+ conversation_attribute_updated: '%{actor} atualizou atributos de conversa'
+ ticket_attribute_updated: '%{actor} atributos atualizados do ticket'
+ ticket_state_updated: '%{actor} atualizou o estado do ticket'
+ custom_action_started: '%{actor} iniciou uma ação personalizada'
+ custom_action_finished: '%{actor} finalizou uma ação personalizada'
+ quick_reply: '%{actor} usou uma resposta rápida'
+ generic: '%{actor} gravou %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: Você não pode revogar a sessão atual.
errors:
account:
+ not_authorized: Você não está autorizado a acessar esta conta
reporting_timezone:
invalid: não é um fuso horário válido
support_email:
@@ -64,9 +89,14 @@ pt_BR:
file_too_large: 'O arquivo excede o tamanho máximo permitido'
unsupported_content_type: 'Tipo de arquivo não suportado (apenas imagens e vídeos são permitidos)'
unexpected: 'Ocorreu um erro inesperado'
+ database:
+ query_canceled: 'A solicitação demorou muito para ser concluída. Tente novamente.'
saml:
feature_not_enabled: SAML não está habilitado para esta conta
sso_not_enabled: O SSO via SAML não está habilitado para esta instalação
+ conversations:
+ unread_counts:
+ feature_not_enabled: O recurso de contagem de conversas não lidas não está habilitado para esta conta
data_import:
data_type:
invalid: Tipo de dado inválido
@@ -92,6 +122,15 @@ pt_BR:
unique: deve ser único na categoria e no portal
dyte:
invalid_message_type: 'Tipo de mensagem inválido. Ação não permitida'
+ realtimekit_credentials_required: 'Credenciais do Cloudflare RealtimeKit são necessárias. Exclua a integração de Dyte existente e crie-a novamente com Cloudflare RealtimeKit credenciais.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'As credenciais do Cloudflare RealtimeKit são inválidas. Verifique o ID da conta, RealtimeKit App ID e as permissões do token de API.'
+ missing_credentials: 'ID da conta Cloudflare, ID do App RealtimeKit e token API são necessários.'
+ invalid_api_token: 'O token API do Cloudflare está inválido ou inativo. Por favor, crie um novo token com permissões de administrador em tempo real.'
+ invalid_account_or_permissions: 'O ID da conta Cloudflare é inválido, ou o token de API não tem acesso de Administrador em tempo real a esta conta.'
+ app_not_found: 'RealtimeKit App ID não foi encontrado nesta conta Cloudflare. Por favor, verifique o app selecionado.'
+ verification_failed: 'Não foi possível verificar as credenciais do Cloudflare RealtimeKit agora. Tente novamente.'
slack:
invalid_channel_id: 'Canal de slack inválido. Por favor, tente novamente'
whatsapp:
@@ -104,6 +143,7 @@ pt_BR:
not_supported: 'Reautenticação não é suportado por este tipo de canal WhatsApp.'
calls:
not_enabled: 'As chamadas não estão habilitadas para esta caixa de entrada'
+ already_ended: 'Esta chamada já terminou'
no_recording: 'Nenhum arquivo de gravação fornecido'
no_message: 'A chamada não possui mensagem associada'
sdp_offer_required: 'sdp_offer é obrigatório'
@@ -142,6 +182,9 @@ pt_BR:
invalid_token: Token MFA inválido ou expirado
invalid_credentials: Credenciais ou código de verificação inválidos
feature_unavailable: O recurso MFA não está disponível. Por favor, configure as chaves de criptografia.
+ billing:
+ invalid_currency: Moeda de cobrança inválida
+ currency_locked: Moeda de faturamento não pode ser alterada após o faturamento ter sido configurado
topup:
credits_required: A quantidade de créditos é obrigatória
invalid_credits: Quantidade de créditos inválida
@@ -414,11 +457,11 @@ pt_BR:
loading_placeholder: Procurando...
results_title: Resultados de pesquisa
results: Resultados da Pesquisa
- results_for: "Search Results for '%{query}'"
- no_results: "No results found for '%{query}'"
+ results_for: "Resultados da pesquisa para '%{query}'"
+ no_results: "Nenhum resultado encontrado para '%{query}'"
found_results:
one: Um resultado encontrado
- other: 'Found %{count} results'
+ other: 'Encontrados %{count} resultados'
submit: Pesquisar
toc_header: 'Nesta página'
sidebar:
@@ -434,7 +477,10 @@ pt_BR:
browse_by_topic_subtitle: Encontre guias, tutoriais e respostas organizados por categoria.
popular_articles: Artigos populares
popular_articles_subtitle: O que outras pessoas estão lendo agora.
+ recommended: Artigos recomendados
+ recommended_subtitle: Artigos escolhidos para você começar.
popular_label: 'Tópicos populares:'
+ recommended_label: 'Tópicos recomendados:'
authors_others: "%{names} e %{count} outros"
primary_nav: Primário
hero:
@@ -470,6 +516,7 @@ pt_BR:
light: Claro
dark: Escuro
featured_articles: Artigos em Destaque
+ recommended: Artigos recomendados
uncategorized: Não categorizado
404:
title: Página não encontrada
@@ -544,6 +591,29 @@ pt_BR:
ssl_status:
custom_domain_not_configured: 'Domínio personalizado não está configurado'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Deixe um modelo em branco para usar o padrão YAML para esse recurso AI.'
+ use_default: 'Usar padrão: %{model} (%{model_id})'
+ show:
+ summary: 'Ver roteamento de modelo'
+ provider: 'Fornecedor'
+ model: 'Modelo'
+ sources:
+ account_override: 'Substituição de cliente'
+ default: 'Padrão'
+ features:
+ editor: 'Editores'
+ assistant: 'Assistente'
+ copilot: 'Copiloto'
+ label_suggestion: 'Sugestão de etiqueta'
+ document_faq_generation: 'Documentar geração de FAQ'
+ conversation_faq_generation: 'Conversação de geração FAQ'
+ help_center_article_generation: 'Ajuda da geração de artigo central'
+ onboarding_content_generation: 'Integração de geração de conteúdo'
+ help_center_query_translation: 'Tradução da consulta central de ajuda'
+ audio_transcription: 'Transcrição de áudio'
+ help_center_search: 'Pesquisa central de ajuda'
push_diagnostics:
user_not_found: 'Usuário não encontrado.'
no_subscriptions_to_test: 'Selecione pelo menos uma assinatura para teste.'
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index 5b5772b41..fce9d3971 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -33,8 +33,33 @@ ro:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Solicitarea de ștergere a inboxului va fi procesată într-un anumit timp.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ro:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Tip de date nevalid
@@ -92,6 +122,15 @@ ro:
unique: ar trebui să fie unic în categorie și portal
dyte:
invalid_message_type: 'Tip de mesaj nevalid. Acțiune nepermisă'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ro:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ro:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -435,7 +478,10 @@ ro:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -471,6 +517,7 @@ ro:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Necategorizat
404:
title: Page not found
@@ -549,6 +596,29 @@ ro:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Implicit'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index ff7ac7980..c51fd193d 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -33,8 +33,33 @@ ru:
login_saml_user: Эта учетная запись использует SAML аутентификацию. Пожалуйста, войдите через SAML провайдера вашей организации.
saml_not_available: SAML аутентификация не доступна в этой установке.
inbox_deletetion_response: Ваш запрос на удаление входящих сообщений будет обработан через некоторое время.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: неверный часовой пояс
support_email:
@@ -64,9 +89,14 @@ ru:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: Функция SAML не включена для этой учетной записи
sso_not_enabled: SSO SAML не включен для этой установки
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Недопустимый тип данных
@@ -92,6 +122,15 @@ ru:
unique: Должны быть уникальными в категории и портале
dyte:
invalid_message_type: 'Недопустимый тип сообщения. Действие запрещено'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Неправильный канал slack - попробуйте еще раз'
whatsapp:
@@ -104,6 +143,7 @@ ru:
not_supported: 'Повторная авторизация не поддерживается для данного типа канала WhatsApp.'
calls:
not_enabled: 'Вызов не включен для этого входящего сообщения'
+ already_ended: 'This call has already ended'
no_recording: 'Файл записи не указан'
no_message: 'Звонок не имеет связанных сообщений'
sdp_offer_required: 'Необходимо указать sdp_offer'
@@ -142,6 +182,9 @@ ru:
invalid_token: Недопустимый или просроченный MFA токен
invalid_credentials: Неверные учетные данные или проверочный код
feature_unavailable: Функция MFA недоступна. Пожалуйста, настройте ключи шифрования.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Необходимо ввести сумму кредитов
invalid_credits: Неверная сумма кредитов
@@ -436,7 +479,10 @@ ru:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ ru:
light: Светлая
dark: Тёмная
featured_articles: Рекомендуемые статьи
+ recommended: Recommended articles
uncategorized: Без категории
404:
title: Страница не найдена
@@ -554,6 +601,29 @@ ru:
ssl_status:
custom_domain_not_configured: 'Пользовательский домен не настроен'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Модель'
+ sources:
+ account_override: 'Account override'
+ default: 'По умолчанию'
+ features:
+ editor: 'Editor'
+ assistant: 'Ассистент'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'Пользователь не найден.'
no_subscriptions_to_test: 'Выберите хотя бы одну подписку для тестирования.'
diff --git a/config/locales/sh.yml b/config/locales/sh.yml
index 37588e130..cf378bd49 100644
--- a/config/locales/sh.yml
+++ b/config/locales/sh.yml
@@ -33,8 +33,33 @@ sh:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sh:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Nevažeći tip podataka
@@ -92,6 +122,15 @@ sh:
unique: mora biti jedinstven u kategoriji i portalu
dyte:
invalid_message_type: 'Neispravan tip poruke. Akcija nije dozvoljena'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ sh:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sh:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ sh:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ sh:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -554,6 +601,29 @@ sh:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Zadano'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 2a5c9d917..242b0171d 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -33,8 +33,33 @@ sk:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sk:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ sk:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ sk:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sk:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ sk:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ sk:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -554,6 +601,29 @@ sk:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 0cb87bfbb..3080a15c4 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -33,8 +33,33 @@ sl:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Vaša zahteva za izbris predala bo obdelana čez nekaj časa.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sl:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Nepravilen podatkovni tip
@@ -92,6 +122,15 @@ sl:
unique: mora biti edinstven v kategoriji in portalu
dyte:
invalid_message_type: 'Neveljavna vrsta sporočila. Dejanje ni dovoljeno'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Neveljaven slack kanal. Prosimo poskusite ponovno'
whatsapp:
@@ -104,6 +143,7 @@ sl:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sl:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ sl:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ sl:
light: Svetlo
dark: Temno
featured_articles: Predstavljeni članki
+ recommended: Recommended articles
uncategorized: Nekategorizirano
404:
title: Stran ni najdena
@@ -554,6 +601,29 @@ sl:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Privzeto'
+ features:
+ editor: 'Editor'
+ assistant: 'Pomočnik'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index 59e98e325..21017c4c3 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -33,8 +33,33 @@ sq:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sq:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'Ndodhi një gabim i papritur'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ sq:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ sq:
not_supported: 'Riautorizimi nuk mbështetet për këtë lloj kanali të WhatsApp-it.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sq:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ sq:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ sq:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ sq:
ssl_status:
custom_domain_not_configured: 'Domeni i personalizuar nuk është konfiguruar'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Parazgjedhje'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 5120a1066..b1efa8dd4 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -33,8 +33,33 @@ sr-Latn:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sr-Latn:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Neispravan tip podatka
@@ -92,6 +122,15 @@ sr-Latn:
unique: treba biti jedinstvena u kategoriji i portalu
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ sr-Latn:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sr-Latn:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -435,7 +478,10 @@ sr-Latn:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -471,6 +517,7 @@ sr-Latn:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -549,6 +596,29 @@ sr-Latn:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Predefinisano'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 94c0ba3cb..06cc4b693 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -33,8 +33,33 @@ sv:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ sv:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ sv:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ sv:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ sv:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ sv:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ sv:
light: Ljus
dark: Mörk
featured_articles: Utvalda artiklar
+ recommended: Recommended articles
uncategorized: Okategoriserade
404:
title: Sidan kunde inte hittas
@@ -544,6 +591,29 @@ sv:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistent'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ta.yml b/config/locales/ta.yml
index 0915cdabd..c22224fc5 100644
--- a/config/locales/ta.yml
+++ b/config/locales/ta.yml
@@ -33,8 +33,33 @@ ta:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ta:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ta:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ta:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ta:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ta:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ta:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ ta:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'இயல்புநிலை'
+ features:
+ editor: 'Editor'
+ assistant: 'உதவியாளர்'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 3131e5918..6521aac20 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -33,8 +33,33 @@ th:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ th:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ th:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ th:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ th:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -433,7 +476,10 @@ th:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ th:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -539,6 +586,29 @@ th:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'ผู้ช่วย'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/tl.yml b/config/locales/tl.yml
index e95be4794..4dda6a87a 100644
--- a/config/locales/tl.yml
+++ b/config/locales/tl.yml
@@ -33,8 +33,33 @@ tl:
login_saml_user: Gumagamit ang account na ito ng SAML na pagpapatotoo. Mangyaring mag-sign in sa pamamagitan ng SAML provider ng iyong organisasyon.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ tl:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: Hindi naka-enable ang tampok na SAML para sa account na ito
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Hindi wastong uri ng datos
@@ -92,6 +122,15 @@ tl:
unique: dapat ay natatangi sa kategorya at portal
dyte:
invalid_message_type: 'Hindi wastong uri ng mensahe. Hindi pinapayagan ang aksyon'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ tl:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ tl:
invalid_token: Hindi wastong o paso na ang MFA token
invalid_credentials: Hindi wastong kredensyal o code ng beripikasyon
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ tl:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ tl:
light: Maliwanag
dark: Madilim
featured_articles: Mga Tampok na Artikulo
+ recommended: Recommended articles
uncategorized: Walang kategorya
404:
title: Hindi makita ang pahina
@@ -544,6 +591,29 @@ tl:
ssl_status:
custom_domain_not_configured: 'Hindi nakaayos ang custom domain'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Katulong'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index fdeb50341..60072f613 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -33,8 +33,33 @@ tr:
login_saml_user: Bu hesap SAML kimlik doğrulaması kullanmaktadır. Lütfen kuruluşunuzun SAML sağlayıcısı aracılığıyla oturum açın.
saml_not_available: SAML kimlik doğrulaması bu kurulumda mevcut değildir.
inbox_deletetion_response: Gelen kutusu silme isteğiniz bir süre sonra işleme alınacaktır.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: geçerli bir saat dilimi değil
support_email:
@@ -64,9 +89,14 @@ tr:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: Bu hesap için SAML özelliği etkinleştirilmemiş
sso_not_enabled: SAML SSO bu kurulum için etkinleştirilmemiş
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Hatalı veri türü
@@ -92,6 +122,15 @@ tr:
unique: kategori ve portalde tekil olmalı
dyte:
invalid_message_type: 'Geçersiz mesaj türü. İşlem izin verilmiyor'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Geçersiz Slack kanalı. Lütfen tekrar deneyin'
whatsapp:
@@ -104,6 +143,7 @@ tr:
not_supported: 'Bu tür WhatsApp kanalları için yeniden yetkilendirme desteklenmemektedir.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ tr:
invalid_token: Geçersiz veya süresi dolmuş MFA jetonu
invalid_credentials: Geçersiz kimlik bilgileri veya doğrulama kodu
feature_unavailable: MFA özelliği kullanılamıyor. Lütfen şifreleme anahtarlarını yapılandırın.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ tr:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ tr:
light: Açık Mod
dark: Koyu Mod
featured_articles: Öne Çıkan Makaleler
+ recommended: Recommended articles
uncategorized: Kategorize Edilmemiş
404:
title: Sayfa bulunamadı
@@ -544,6 +591,29 @@ tr:
ssl_status:
custom_domain_not_configured: 'Özel alan adı yapılandırılmamış'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Varsayılan'
+ features:
+ editor: 'Editor'
+ assistant: 'Asistan'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 7cef7561a..e520ff6ea 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -33,8 +33,33 @@ uk:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Ваш запит на видалення буде оброблений протягом деякого часу.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ uk:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Некоректний тип даних
@@ -92,6 +122,15 @@ uk:
unique: має бути унікальним на категорії і порталі
dyte:
invalid_message_type: 'Невірний тип повідомлення. Дію не дозволено'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Недійсний канал slack. Будь ласка, спробуйте ще раз'
whatsapp:
@@ -104,6 +143,7 @@ uk:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ uk:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -436,7 +479,10 @@ uk:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -472,6 +518,7 @@ uk:
light: Світла
dark: Темна
featured_articles: Вибрані статті
+ recommended: Recommended articles
uncategorized: Без категорії
404:
title: Сторінку не знайдено
@@ -554,6 +601,29 @@ uk:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'За замовчуванням'
+ features:
+ editor: 'Editor'
+ assistant: 'Асистент'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ur.yml b/config/locales/ur.yml
index 0a3d9c705..b4e89414a 100644
--- a/config/locales/ur.yml
+++ b/config/locales/ur.yml
@@ -33,8 +33,33 @@ ur:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ur:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ur:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ur:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ur:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ur:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ur:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ ur:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'اسسٹنٹ'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/ur_IN.yml b/config/locales/ur_IN.yml
index f3cfab8b1..b5c864971 100644
--- a/config/locales/ur_IN.yml
+++ b/config/locales/ur_IN.yml
@@ -33,8 +33,33 @@ ur:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ ur:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Invalid data type
@@ -92,6 +122,15 @@ ur:
unique: should be unique in the category and portal
dyte:
invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ ur:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ ur:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -434,7 +477,10 @@ ur:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -470,6 +516,7 @@ ur:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Uncategorized
404:
title: Page not found
@@ -544,6 +591,29 @@ ur:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'ڈیفالٹ'
+ features:
+ editor: 'Editor'
+ assistant: 'اسسٹنٹ'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/uz.yml b/config/locales/uz.yml
new file mode 100644
index 000000000..689032af1
--- /dev/null
+++ b/config/locales/uz.yml
@@ -0,0 +1,621 @@
+#Files in the config/locales directory are used for internationalization
+#and are automatically loaded by Rails. If you want to use locales other
+#than English, add the necessary files in this directory.
+#To use the locales, use `I18n.t`:
+#I18n.t 'hello'
+#In views, this is aliased to just `t`:
+#<%= t('hello') %>
+#To use a different locale, set it with `I18n.locale`:
+#I18n.locale = :es
+#This would use the information in config/locales/es.yml.
+#The following keys must be escaped otherwise they will not be retrieved by
+#the default I18n backend:
+#true, false, on, off, yes, no
+#Instead, surround them with single quotes.
+#en:
+#'true': 'foo'
+#To learn more, please read the Rails Internationalization guide
+#available at https://guides.rubyonrails.org/i18n.html.
+uz:
+ hello: 'Hello world'
+ inbox:
+ reauthorization:
+ success: 'Channel reauthorized successfully'
+ not_required: 'Reauthorization is not required for this inbox'
+ invalid_channel: 'Invalid channel type for reauthorization'
+ auth:
+ saml:
+ invalid_email: 'Please enter a valid email address'
+ authentication_failed: 'Authentication failed. Please check your credentials and try again.'
+ messages:
+ reset_password: Request for password reset is successful. A email with instructions will be sent to your email if it exists.
+ reset_password_saml_user: This account uses SAML authentication. Password reset is not available. Please contact your administrator.
+ login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
+ saml_not_available: SAML authentication is not available in this installation.
+ inbox_deletetion_response: Your inbox deletion request will be processed in some time.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
+ errors:
+ account:
+ not_authorized: You are not authorized to access this account
+ reporting_timezone:
+ invalid: is not a valid timezone
+ support_email:
+ invalid: is not a valid email address
+ validations:
+ presence: must not be blank
+ webhook:
+ invalid: Invalid events
+ signup:
+ disposable_email: We do not allow disposable emails
+ blocked_domain: This domain is not allowed. If you believe this is a mistake, please contact support.
+ invalid_email: You have entered an invalid email
+ email_already_exists: 'You have already signed up for an account with %{email}'
+ invalid_params: 'Invalid, please check the signup paramters and try again'
+ failed: Signup failed
+ voice:
+ call_already_accepted: '%{agent_name} is already handling the call.'
+ assignment_policy:
+ not_found: Assignment policy not found
+ attachments:
+ invalid: Invalid attachment
+ upload:
+ missing_input: 'No file or URL provided'
+ invalid_url: 'Invalid URL provided'
+ fetch_failed: 'Failed to fetch file from URL'
+ fetch_failed_with_message: 'Failed to fetch file from URL: %{message}'
+ file_too_large: 'File exceeds the maximum allowed size'
+ unsupported_content_type: 'File type not supported (only images and videos are allowed)'
+ unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
+ saml:
+ feature_not_enabled: SAML feature not enabled for this account
+ sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
+ data_import:
+ data_type:
+ invalid: Invalid data type
+ contacts:
+ import:
+ failed: File is blank
+ export:
+ success: We will notify you once contacts export file is ready to view.
+ email:
+ invalid: Invalid email
+ phone_number:
+ invalid: should be in e164 format
+ companies:
+ domain:
+ invalid: must be a valid domain name
+ search:
+ query_missing: Specify search string with parameter q
+ messages:
+ search:
+ time_range_limit_exceeded: 'Search is limited to the last %{days} days'
+ categories:
+ locale:
+ unique: should be unique in the category and portal
+ dyte:
+ invalid_message_type: 'Invalid message type. Action not permitted'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
+ slack:
+ invalid_channel_id: 'Invalid slack channel. Please try again'
+ whatsapp:
+ token_exchange_failed: 'Failed to exchange code for access token. Please try again.'
+ invalid_token_permissions: 'The access token does not have the required permissions for WhatsApp.'
+ phone_info_fetch_failed: 'Failed to fetch phone number information. Please try again.'
+ phone_number_already_exists: 'Channel already exists for this phone number: %{phone_number}, please contact support if the error persists'
+ reauthorization:
+ generic: 'Failed to reauthorize WhatsApp. Please try again.'
+ not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
+ calls:
+ not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
+ no_recording: 'No recording file provided'
+ no_message: 'Call has no associated message'
+ sdp_offer_required: 'sdp_offer is required'
+ contact_phone_required: 'Contact phone number is required'
+ permission_request_failed: 'Failed to send call permission request'
+ openai:
+ invalid_api_key: 'OpenAI API key is invalid or revoked. Please check your key in your OpenAI dashboard.'
+ inboxes:
+ imap:
+ socket_error: Please check the network connection, IMAP address and try again.
+ no_response_error: Please check the IMAP credentials and try again.
+ host_unreachable_error: Host unreachable, Please check the IMAP address, IMAP port and try again.
+ connection_timed_out_error: Connection timed out for %{address}:%{port}
+ connection_closed_error: Connection closed.
+ smtp:
+ authentication_error: SMTP authentication failed. Please verify your login credentials.
+ connection_error: Could not connect to SMTP server. Please check the server address and port.
+ ssl_error: SSL/TLS error. Please verify your encryption settings.
+ smtp_error: SMTP server error. Please check your configuration and try again.
+ validations:
+ name: should not start or end with symbols, and it should not have < > / \ @ characters.
+ custom_filters:
+ number_of_records: Limit reached. The maximum number of allowed custom filters for a user per account is 1000.
+ invalid_attribute: Invalid attribute key - [%{key}]. The key should be one of [%{allowed_keys}] or a custom attribute defined in the account.
+ invalid_operator: Invalid operator. The allowed operators for %{attribute_name} are [%{allowed_keys}].
+ invalid_query_operator: Query operator must be either "AND" or "OR".
+ invalid_value: Invalid value. The values provided for %{attribute_name} are invalid
+ custom_attribute_definition:
+ attribute_key_format: must only contain letters, numbers, underscores, hyphens, and dots
+ key_conflict: The provided key is not allowed as it might conflict with default attributes.
+ mfa:
+ already_enabled: MFA is already enabled
+ not_enabled: MFA is not enabled
+ invalid_code: Invalid verification code
+ invalid_backup_code: Invalid backup code
+ invalid_token: Invalid or expired MFA token
+ invalid_credentials: Invalid credentials or verification code
+ feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
+ topup:
+ credits_required: Credits amount is required
+ invalid_credits: Invalid credits amount
+ invalid_option: Invalid topup option
+ plan_not_eligible: Top-ups are only available for paid plans. Please upgrade your plan first.
+ stripe_customer_not_configured: Stripe customer not configured
+ no_payment_method: No payment methods found. Please add a payment method before making a purchase.
+ reports:
+ date_range_too_long: Date range cannot exceed 6 months
+ profile:
+ mfa:
+ enabled: MFA enabled successfully
+ disabled: MFA disabled successfully
+ account_saml_settings:
+ invalid_certificate: must be a valid X.509 certificate in PEM format
+ reports:
+ period: Reporting period %{since} to %{until}
+ utc_warning: The report generated is in UTC timezone
+ agent_csv:
+ agent_name: Agent name
+ conversations_count: Assigned conversations
+ avg_first_response_time: Avg first response time
+ avg_resolution_time: Avg resolution time
+ resolution_count: Resolution Count
+ avg_customer_waiting_time: Avg customer waiting time
+ inbox_csv:
+ inbox_name: Inbox name
+ inbox_type: Inbox type
+ conversations_count: No. of conversations
+ avg_first_response_time: Avg first response time
+ avg_resolution_time: Avg resolution time
+ label_csv:
+ label_title: Label
+ conversations_count: No. of conversations
+ avg_first_response_time: Avg first response time
+ avg_resolution_time: Avg resolution time
+ avg_reply_time: Avg reply time
+ resolution_count: Resolution Count
+ team_csv:
+ team_name: Team name
+ conversations_count: Conversations count
+ avg_first_response_time: Avg first response time
+ avg_resolution_time: Avg resolution time
+ resolution_count: Resolution Count
+ avg_customer_waiting_time: Avg customer waiting time
+ conversation_csv:
+ conversations_count: Conversations
+ incoming_messages_count: Messages received
+ outgoing_messages_count: Messages sent
+ avg_first_response_time: Avg first response time
+ avg_resolution_time: Avg resolution time
+ resolution_count: Resolution count
+ avg_customer_waiting_time: Avg customer waiting time
+ conversation_traffic_csv:
+ timezone: Timezone
+ sla_csv:
+ conversation_id: Conversation ID
+ sla_policy_breached: SLA Policy
+ assignee: Assignee
+ team: Team
+ inbox: Inbox
+ labels: Labels
+ conversation_link: Link to the Conversation
+ breached_events: Breached Events
+ default_group_by: day
+ csat:
+ headers:
+ contact_name: Contact Name
+ contact_email_address: Contact Email Address
+ contact_phone_number: Contact Phone Number
+ link_to_the_conversation: Link to the conversation
+ agent_name: Agent Name
+ rating: Rating
+ feedback: Feedback Comment
+ recorded_at: Recorded date
+ review_notes: Review Notes
+ notifications:
+ notification_title:
+ conversation_creation: 'A conversation (#%{display_id}) has been created in %{inbox_name}'
+ conversation_assignment: 'A conversation (#%{display_id}) has been assigned to you'
+ assigned_conversation_new_message: 'A new message is created in conversation (#%{display_id})'
+ conversation_mention: 'You have been mentioned in conversation (#%{display_id})'
+ sla_missed_first_response: 'SLA target first response missed for conversation (#%{display_id})'
+ sla_missed_next_response: 'SLA target next response missed for conversation (#%{display_id})'
+ sla_missed_resolution: 'SLA target resolution missed for conversation (#%{display_id})'
+ attachment: 'Attachment'
+ no_content: 'No content'
+ conversations:
+ captain:
+ handoff: 'Transferring to another agent for further assistance.'
+ messages:
+ instagram_story_content: '%{story_sender} mentioned you in the story: '
+ instagram_deleted_story_content: This story is no longer available.
+ instagram_shared_story_content: 'Shared story'
+ instagram_shared_post_content: 'Shared post'
+ deleted: This message was deleted
+ whatsapp:
+ list_button_label: 'Choose an item'
+ call_permission_request_body: 'We would like to call you regarding your conversation.'
+ unsupported_message: 'This message is unavailable.'
+ voice_call:
+ twilio: 'Voice Call'
+ whatsapp: 'WhatsApp Call'
+ delivery_status:
+ error_code: 'Error code: %{error_code}'
+ activity:
+ captain:
+ resolved: 'Conversation was marked resolved by %{user_name} due to inactivity'
+ resolved_with_reason: 'Conversation was marked resolved by %{user_name} (%{reason})'
+ resolved_by_tool: 'Conversation was marked resolved by %{user_name}: %{reason}'
+ open: 'Conversation was marked open by %{user_name}'
+ open_with_reason: 'Conversation was marked open by %{user_name} (%{reason})'
+ auto_opened_after_agent_reply: 'Conversation was marked open automatically after an agent reply'
+ agent_bot:
+ error_moved_to_open: 'Conversation was marked open by system due to an error with the agent bot.'
+ status:
+ resolved: 'Conversation was marked resolved by %{user_name}'
+ contact_resolved: 'Conversation was resolved by %{contact_name}'
+ open: 'Conversation was reopened by %{user_name}'
+ pending: 'Conversation was marked as pending by %{user_name}'
+ snoozed: 'Conversation was snoozed by %{user_name}'
+ auto_resolved_days: 'Conversation was marked resolved by system due to %{count} days of inactivity'
+ auto_resolved_hours: 'Conversation was marked resolved by system due to %{count} hours of inactivity'
+ auto_resolved_minutes: 'Conversation was marked resolved by system due to %{count} minutes of inactivity'
+ system_auto_open: System reopened the conversation due to a new incoming message.
+ priority:
+ added: '%{user_name} set the priority to %{new_priority}'
+ updated: '%{user_name} changed the priority from %{old_priority} to %{new_priority}'
+ removed: '%{user_name} removed the priority'
+ assignee:
+ self_assigned: '%{user_name} self-assigned this conversation'
+ assigned: 'Assigned to %{assignee_name} by %{user_name}'
+ removed: 'Conversation unassigned by %{user_name}'
+ team:
+ assigned: 'Assigned to %{team_name} by %{user_name}'
+ assigned_with_assignee: 'Assigned to %{assignee_name} via %{team_name} by %{user_name}'
+ removed: 'Unassigned from %{team_name} by %{user_name}'
+ labels:
+ added: '%{user_name} added %{labels}'
+ removed: '%{user_name} removed %{labels}'
+ sla:
+ added: '%{user_name} added SLA policy %{sla_name}'
+ removed: '%{user_name} removed SLA policy %{sla_name}'
+ linear:
+ issue_created: 'Linear issue %{issue_id} was created by %{user_name}'
+ issue_linked: 'Linear issue %{issue_id} was linked by %{user_name}'
+ issue_unlinked: 'Linear issue %{issue_id} was unlinked by %{user_name}'
+ whatsapp_call:
+ permission_requested: 'Sent a call permission request to %{contact_name}.'
+ permission_granted: '%{contact_name} accepted the call permission request.'
+ csat:
+ not_sent_due_to_messaging_window: 'CSAT survey not sent due to outgoing message restrictions'
+ auto_resolve:
+ not_sent_due_to_messaging_window: 'Auto-resolve message not sent due to outgoing message restrictions'
+ muted: '%{user_name} has muted the conversation'
+ unmuted: '%{user_name} has unmuted the conversation'
+ auto_resolution_message: 'Resolving the conversation as it has been inactive for a while. Please start a new conversation if you need further assistance.'
+ templates:
+ greeting_message_body: '%{account_name} typically replies in a few hours.'
+ ways_to_reach_you_message_body: 'Give the team a way to reach you.'
+ email_input_box_message_body: 'Get notified by email'
+ csat_input_message_body: 'Please rate the conversation'
+ reply:
+ email:
+ header:
+ notifications: 'Notifications'
+ from_with_name: '%{assignee_name} from %{inbox_name} <%{from_email}>'
+ reply_with_name: '%{assignee_name} from %{inbox_name} '
+ friendly_name: '%{sender_name} from %{business_name} <%{from_email}>'
+ professional_name: '%{business_name} <%{from_email}>'
+ channel_email:
+ header:
+ reply_with_name: '%{assignee_name} from %{inbox_name} <%{from_email}>'
+ reply_with_inbox_name: '%{inbox_name} <%{from_email}>'
+ email_subject: 'New messages on this conversation'
+ transcript_subject: 'Conversation Transcript'
+ survey:
+ response: 'Please rate this conversation, %{link}'
+ contacts:
+ online:
+ delete: '%{contact_name} is Online, please try again later'
+ integration_apps:
+ #Note: webhooks and dashboard_apps don't need short_description as they use different modal components
+ dashboard_apps:
+ name: 'Dashboard Apps'
+ description: 'Dashboard Apps allow you to create and embed applications that display user information, orders, or payment history, providing more context to your customer support agents.'
+ dyte:
+ name: 'Cloudflare RealtimeKit'
+ short_description: 'Start video/voice calls with customers directly from Chatwoot.'
+ description: 'Cloudflare RealtimeKit lets your agents start video/voice calls with your customers directly from Chatwoot.'
+ meeting_name: '%{agent_name} has started a meeting'
+ slack:
+ name: 'Slack'
+ short_description: 'Receive notifications and respond to conversations directly in Slack.'
+ description: "Integrate Chatwoot with Slack to keep your team in sync. This integration allows you to receive notifications for new conversations and respond to them directly within Slack's interface."
+ webhooks:
+ name: 'Webhooks'
+ description: 'Webhook events provide real-time updates about activities in your Chatwoot account. You can subscribe to your preferred events, and Chatwoot will send you HTTP callbacks with the updates.'
+ dialogflow:
+ name: 'Dialogflow'
+ short_description: 'Build chatbots to handle initial queries before transferring to agents.'
+ description: 'Build chatbots with Dialogflow and easily integrate them into your inbox. These bots can handle initial queries before transferring them to a customer service agent.'
+ google_translate:
+ name: 'Google Translate'
+ short_description: 'Automatically translate customer messages for agents.'
+ description: "Integrate Google Translate to help agents easily translate customer messages. This integration automatically detects the language and converts it to the agent's or admin's preferred language."
+ openai:
+ name: 'OpenAI'
+ short_description: 'AI-powered reply suggestions, summarization, and message enhancement.'
+ description: 'Leverage the power of large language models from OpenAI with the features such as reply suggestions, summarization, message rephrasing, spell-checking, and label classification.'
+ linear:
+ name: 'Linear'
+ short_description: 'Create and link Linear issues directly from conversations.'
+ description: 'Create issues in Linear directly from your conversation window. Alternatively, link existing Linear issues for a more streamlined and efficient issue tracking process.'
+ attachment_link_title: 'Conversation (#%{conversation_id}) with %{name}'
+ notion:
+ name: 'Notion'
+ short_description: 'Integrate databases, documents and pages directly with Captain.'
+ description: 'Connect your Notion workspace to enable Captain to access and generate intelligent responses using content from your databases, documents, and pages to provide more contextual customer support.'
+ shopify:
+ name: 'Shopify'
+ short_description: 'Access order details and customer data from your Shopify store.'
+ description: 'Connect your Shopify store to access order details, customer information, and product data directly within your conversations and helps your support team provide faster, more contextual assistance to your customers.'
+ leadsquared:
+ name: 'LeadSquared'
+ short_description: 'Sync your contacts and conversations with LeadSquared CRM.'
+ description: 'Sync your contacts and conversations with LeadSquared CRM. This integration automatically creates leads in LeadSquared when new contacts are added, and logs conversation activity to provide your sales team with complete context.'
+ captain:
+ copilot_message_required: Message is required
+ copilot_error: 'Please connect an assistant to this inbox to use Copilot'
+ copilot_limit: 'You are out of Copilot credits. You can buy more credits from the billing section.'
+ upgrade: 'Upgrade your plan to enable Captain AI'
+ disabled: 'Captain AI is disabled for this account.'
+ api_key_missing: 'Captain AI API key is not configured.'
+ copilot:
+ using_tool: 'Using tool %{function_name}'
+ completed_tool_call: 'Completed %{function_name} tool call'
+ invalid_tool_call: 'Invalid tool call'
+ tool_not_available: 'Tool not available'
+ documents:
+ limit_exceeded: 'Document limit exceeded'
+ pdf_format_error: 'must be a PDF file'
+ pdf_size_error: 'must be less than 10MB'
+ sync_not_supported_for_pdf: 'Sync is not supported for PDF documents'
+ sync_only_available_documents: 'Sync is only available for processed documents'
+ sync_already_in_progress: 'Document sync is already in progress'
+ pdf_upload_failed: 'Failed to upload PDF to OpenAI'
+ pdf_upload_success: 'PDF uploaded successfully with file_id: %{file_id}'
+ pdf_processing_failed: 'Failed to process PDF document %{document_id}: %{error}'
+ pdf_processing_success: 'Successfully processed PDF document %{document_id}'
+ faq_generation_complete: 'FAQ generation complete. Total FAQs created: %{count}'
+ using_paginated_faq: 'Using paginated FAQ generation for document %{document_id}'
+ using_standard_faq: 'Using standard FAQ generation for document %{document_id}'
+ response_creation_error: 'Error in creating response document: %{error}'
+ missing_openai_file_id: 'Document must have openai_file_id for paginated processing'
+ openai_api_error: 'OpenAI API Error: %{error}'
+ starting_paginated_faq: 'Starting paginated FAQ generation (%{pages_per_chunk} pages per chunk)'
+ stopping_faq_generation: 'Stopping processing. Reason: %{reason}'
+ paginated_faq_complete: 'Paginated generation complete. Total FAQs: %{total_faqs}, Pages processed: %{pages_processed}'
+ processing_pages: 'Processing pages %{start}-%{end} (iteration %{iteration})'
+ chunk_generated: 'Chunk generated %{chunk_faqs} FAQs. Total so far: %{total_faqs}'
+ page_processing_error: 'Error processing pages %{start}-%{end}: %{error}'
+ custom_tool:
+ slug_generation_failed: 'Unable to generate unique slug after 5 attempts'
+ limit_exceeded: 'You can create a maximum of %{limit} custom tools per account'
+ public_portal:
+ search:
+ search_placeholder: Search for article by title or body...
+ empty_placeholder: No results found.
+ loading_placeholder: Searching...
+ results_title: Search results
+ results: Search Results
+ results_for: "Search Results for '%{query}'"
+ no_results: "No results found for '%{query}'"
+ found_results:
+ one: Found 1 result
+ other: 'Found %{count} results'
+ submit: Search
+ toc_header: 'On this page'
+ sidebar:
+ help_center: Help Center
+ categories: Categories
+ language: Language
+ theme: Theme
+ open_sidebar: Open sidebar
+ close_sidebar: Close sidebar
+ browse: Browse
+ back_to_category: Back to %{name}
+ browse_by_topic: Browse by topic
+ browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
+ popular_articles: Popular articles
+ popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
+ popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
+ authors_others: "%{names} and %{count} others"
+ primary_nav: Primary
+ hero:
+ sub_title: Search for the articles here or browse the categories below.
+ common:
+ home: Home
+ last_updated_on: Last updated on %{last_updated_on}
+ view_all_articles: View all
+ article: article
+ articles: articles
+ author: author
+ authors: authors
+ other: other
+ others: others
+ by: By
+ no_articles: There are no articles here
+ previous: Previous
+ next: Next
+ article_actions:
+ label: Open in
+ view_markdown: View as Markdown
+ open_in_chatgpt: Open in ChatGPT
+ open_in_claude: Open in Claude
+ llm_prompt: "Read the following article and help me understand it: %{url}"
+ footer:
+ made_with: Made with
+ header:
+ go_to_homepage: Website
+ visit_website: Visit website
+ appearance:
+ title: Appearance
+ system: System
+ light: Light
+ dark: Dark
+ featured_articles: Featured Articles
+ recommended: Recommended articles
+ uncategorized: Uncategorized
+ 404:
+ title: Page not found
+ description: We couldn't find the page you were looking for.
+ back_to_home: Go to home page
+ not_active:
+ title: Help Center Unavailable
+ description: Please contact the site administrator for more information.
+ action: If you are the administrator, please upgrade your plan to restore access.
+ slack_unfurl:
+ fields:
+ name: Name
+ email: Email
+ phone_number: Phone
+ company_name: Company
+ inbox_name: Inbox
+ inbox_type: Inbox Type
+ button: Open conversation
+ time_units:
+ days:
+ one: '%{count} day'
+ other: '%{count} days'
+ hours:
+ one: '%{count} hour'
+ other: '%{count} hours'
+ minutes:
+ one: '%{count} minute'
+ other: '%{count} minutes'
+ seconds:
+ one: '%{count} second'
+ other: '%{count} seconds'
+ auto_assignment:
+ default_policy_name: 'Default Policy'
+ policy_actor: 'Automation System via %{policy_name}'
+ automation:
+ system_name: 'Automation System'
+ crm:
+ no_message: 'No messages in conversation'
+ attachment: '[Attachment: %{type}]'
+ no_content: '[No content]'
+ created_activity: |
+ New conversation started on %{brand_name}
+
+ Channel: %{channel_info}
+ Created: %{formatted_creation_time}
+ Conversation ID: %{display_id}
+ View in %{brand_name}: %{url}
+ transcript_activity: |
+ Conversation Transcript from %{brand_name}
+
+ Channel: %{channel_info}
+ Conversation ID: %{display_id}
+ View in %{brand_name}: %{url}
+
+ Transcript:
+ %{format_messages}
+ agent_capacity_policy:
+ inbox_already_assigned: 'Inbox has already been assigned to this policy'
+ portals:
+ articles:
+ captain_not_available: 'Translation requires Captain to be enabled for this account'
+ locale_not_available: 'Locale not available in this portal'
+ category_not_found: 'Category not found in this portal'
+ no_articles_found: 'No articles found to process'
+ invalid_status: 'Invalid status value'
+ send_instructions:
+ email_required: 'Email is required'
+ invalid_email_format: 'Invalid email format'
+ custom_domain_not_configured: 'Custom domain is not configured'
+ instructions_sent_successfully: 'Instructions sent successfully'
+ subject: 'Finish setting up %{custom_domain}'
+ ssl_status:
+ custom_domain_not_configured: 'Custom domain is not configured'
+ super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Default'
+ features:
+ editor: 'Editor'
+ assistant: 'Assistant'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
+ push_diagnostics:
+ user_not_found: 'User not found.'
+ no_subscriptions_to_test: 'Select at least one subscription to test.'
+ no_subscriptions_to_delete: 'Select at least one subscription to delete.'
+ subscriptions_deleted: "Deleted %{count} subscription(s). The user's device(s) will re-register on next app launch."
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index b6430287e..ab8fcdc4b 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -33,8 +33,33 @@ vi:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: Yêu cầu xoá hộp thư của bạn sẽ được xử lý.
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ vi:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: Kiểu dữ liệu không hợp lệ
@@ -92,6 +122,15 @@ vi:
unique: phải là duy nhất trong danh mục và cổng thông tin
dyte:
invalid_message_type: 'Loại tin nhắn không hợp lệ. Hành động không được phép'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: 'Invalid slack channel. Please try again'
whatsapp:
@@ -104,6 +143,7 @@ vi:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ vi:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -433,7 +476,10 @@ vi:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ vi:
light: Light
dark: Dark
featured_articles: Featured Articles
+ recommended: Recommended articles
uncategorized: Chưa được phân loại
404:
title: Page not found
@@ -539,6 +586,29 @@ vi:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: 'Mặc định'
+ features:
+ editor: 'Editor'
+ assistant: 'Trợ lý'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/zh_CN.yml b/config/locales/zh_CN.yml
index 5d1bdef9f..4d585f1df 100644
--- a/config/locales/zh_CN.yml
+++ b/config/locales/zh_CN.yml
@@ -33,8 +33,33 @@ zh_CN:
login_saml_user: This account uses SAML authentication. Please sign in through your organization's SAML provider.
saml_not_available: SAML authentication is not available in this installation.
inbox_deletetion_response: 您的收件箱删除请求将在一段时间内处理。
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: is not a valid timezone
support_email:
@@ -64,9 +89,14 @@ zh_CN:
file_too_large: 'File exceeds the maximum allowed size'
unsupported_content_type: 'File type not supported (only images and videos are allowed)'
unexpected: 'An unexpected error occurred'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: SAML feature not enabled for this account
sso_not_enabled: SAML SSO is not enabled for this installation
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: 错误的数据类型
@@ -92,6 +122,15 @@ zh_CN:
unique: 在类别和门户中应该是唯一的
dyte:
invalid_message_type: '无效的消息类型。不允许操作'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: '无效的Slack频道。请重试'
whatsapp:
@@ -104,6 +143,7 @@ zh_CN:
not_supported: 'Reauthorization is not supported for this type of WhatsApp channel.'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ zh_CN:
invalid_token: Invalid or expired MFA token
invalid_credentials: Invalid credentials or verification code
feature_unavailable: MFA feature is not available. Please configure encryption keys.
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: Credits amount is required
invalid_credits: Invalid credits amount
@@ -433,7 +476,10 @@ zh_CN:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ zh_CN:
light: 浅色
dark: 暗色
featured_articles: 精选文章
+ recommended: Recommended articles
uncategorized: 未分类
404:
title: 页面不存在
@@ -539,6 +586,29 @@ zh_CN:
ssl_status:
custom_domain_not_configured: 'Custom domain is not configured'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: '默认'
+ features:
+ editor: 'Editor'
+ assistant: '助手'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/locales/zh_TW.yml b/config/locales/zh_TW.yml
index d51d86f29..df97573e5 100644
--- a/config/locales/zh_TW.yml
+++ b/config/locales/zh_TW.yml
@@ -33,8 +33,33 @@ zh_TW:
login_saml_user: 此帳號使用 SAML 驗證,請透過您組織的 SAML 提供者登入。
saml_not_available: 此安裝尚未啟用 SAML 驗證。
inbox_deletetion_response: 您的收件匣刪除請求將在一段時間後處理。
+ data_imports:
+ intercom:
+ activities:
+ assignment: '%{actor} assigned the conversation'
+ assignment_with_target: '%{actor} assigned the conversation to %{target}'
+ assign_and_reopen: '%{actor} assigned and reopened the conversation'
+ assign_and_reopen_with_target: '%{actor} assigned the conversation to %{target} and reopened it'
+ open: '%{actor} opened the conversation'
+ close: '%{actor} closed the conversation'
+ snoozed: '%{actor} snoozed the conversation'
+ participant_added: '%{actor} added a participant'
+ participant_added_with_target: '%{actor} added %{target} as a participant'
+ participant_removed: '%{actor} removed a participant'
+ participant_removed_with_target: '%{actor} removed %{target} as a participant'
+ conversation_attribute_updated: '%{actor} updated conversation attributes'
+ ticket_attribute_updated: '%{actor} updated ticket attributes'
+ ticket_state_updated: '%{actor} updated the ticket state'
+ custom_action_started: '%{actor} started a custom action'
+ custom_action_finished: '%{actor} finished a custom action'
+ quick_reply: '%{actor} used a quick reply'
+ generic: '%{actor} recorded %{event}'
+ profile_settings:
+ sessions:
+ cannot_revoke_current: You cannot revoke the current session.
errors:
account:
+ not_authorized: You are not authorized to access this account
reporting_timezone:
invalid: 不是有效的時區
support_email:
@@ -64,9 +89,14 @@ zh_TW:
file_too_large: '檔案超過允許的最大大小'
unsupported_content_type: '不支援的檔案類型(僅允許圖片和影片)'
unexpected: '發生未預期的錯誤'
+ database:
+ query_canceled: 'The request took too long to complete. Please try again.'
saml:
feature_not_enabled: 此帳號尚未啟用 SAML 功能
sso_not_enabled: 此安裝尚未啟用 SAML SSO
+ conversations:
+ unread_counts:
+ feature_not_enabled: Conversation unread counts feature not enabled for this account
data_import:
data_type:
invalid: 無效的資料類型
@@ -92,6 +122,15 @@ zh_TW:
unique: 在該分類與入口網站中應為唯一
dyte:
invalid_message_type: '無效的訊息類型,不允許此操作'
+ realtimekit_credentials_required: 'Cloudflare RealtimeKit credentials are required. Delete the existing Dyte integration and create it again with Cloudflare RealtimeKit credentials.'
+ cloudflare:
+ realtimekit:
+ invalid_credentials: 'Cloudflare RealtimeKit credentials are invalid. Please check the Account ID, RealtimeKit App ID, and API token permissions.'
+ missing_credentials: 'Cloudflare Account ID, RealtimeKit App ID, and API token are required.'
+ invalid_api_token: 'Cloudflare API token is invalid or inactive. Please create a new token with Realtime Admin permissions.'
+ invalid_account_or_permissions: 'Cloudflare Account ID is invalid, or the API token does not have Realtime Admin access to this account.'
+ app_not_found: 'RealtimeKit App ID was not found in this Cloudflare account. Please check the app you selected.'
+ verification_failed: 'Could not verify Cloudflare RealtimeKit credentials right now. Please try again.'
slack:
invalid_channel_id: '無效的 Slack 頻道,請再試一次'
whatsapp:
@@ -104,6 +143,7 @@ zh_TW:
not_supported: '此類型的 WhatsApp 頻道不支援重新授權。'
calls:
not_enabled: 'Calling is not enabled for this inbox'
+ already_ended: 'This call has already ended'
no_recording: 'No recording file provided'
no_message: 'Call has no associated message'
sdp_offer_required: 'sdp_offer is required'
@@ -142,6 +182,9 @@ zh_TW:
invalid_token: 無效或已過期的 MFA 權杖
invalid_credentials: 無效的憑證或驗證碼
feature_unavailable: MFA 功能無法使用,請設定加密金鑰。
+ billing:
+ invalid_currency: Invalid billing currency
+ currency_locked: Billing currency cannot be changed after billing has been set up
topup:
credits_required: 需填入儲值點數金額
invalid_credits: 無效的儲值點數金額
@@ -433,7 +476,10 @@ zh_TW:
browse_by_topic_subtitle: Find guides, tutorials, and answers organised by category.
popular_articles: Popular articles
popular_articles_subtitle: What other people are reading right now.
+ recommended: Recommended articles
+ recommended_subtitle: Hand-picked articles to get you started.
popular_label: 'Popular topics:'
+ recommended_label: 'Recommended topics:'
authors_others: "%{names} and %{count} others"
primary_nav: Primary
hero:
@@ -469,6 +515,7 @@ zh_TW:
light: 淺色
dark: 深色
featured_articles: 精選文章
+ recommended: Recommended articles
uncategorized: 未分類
404:
title: 找不到頁面
@@ -539,6 +586,29 @@ zh_TW:
ssl_status:
custom_domain_not_configured: '尚未設定自訂網域'
super_admin:
+ captain_model_overrides:
+ form:
+ helper_text: 'Leave a model blank to use the YAML default for that AI feature.'
+ use_default: 'Use default: %{model} (%{model_id})'
+ show:
+ summary: 'View model routing'
+ provider: 'Provider'
+ model: 'Model'
+ sources:
+ account_override: 'Account override'
+ default: '預設'
+ features:
+ editor: 'Editor'
+ assistant: '助理'
+ copilot: 'Copilot'
+ label_suggestion: 'Label suggestion'
+ document_faq_generation: 'Document FAQ generation'
+ conversation_faq_generation: 'Conversation FAQ generation'
+ help_center_article_generation: 'Help center article generation'
+ onboarding_content_generation: 'Onboarding content generation'
+ help_center_query_translation: 'Help center query translation'
+ audio_transcription: 'Audio transcription'
+ help_center_search: 'Help center search'
push_diagnostics:
user_not_found: 'User not found.'
no_subscriptions_to_test: 'Select at least one subscription to test.'
diff --git a/config/routes.rb b/config/routes.rb
index dfdc23727..7314dbda5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -66,7 +66,8 @@ Rails.application.routes.draw do
resources :assistants do
member do
post :playground
- get :stats
+ get :metrics
+ get :faq_stats
get :summary
get :drilldown
end
@@ -76,6 +77,7 @@ Rails.application.routes.draw do
resources :inboxes, only: [:index, :create, :destroy], param: :inbox_id
resources :scenarios
end
+ resources :agent_sessions, only: [:show]
resources :assistant_responses
resources :message_reports, only: [:create]
resources :bulk_actions, only: [:create]
diff --git a/enterprise/LICENSE b/enterprise/LICENSE
index dd92c09e9..3241a4ad0 100644
--- a/enterprise/LICENSE
+++ b/enterprise/LICENSE
@@ -1,5 +1,5 @@
The Chatwoot Enterprise license (the “Enterprise License”)
-Copyright (c) 2017-2025 Chatwoot Inc
+Copyright (c) 2017-2026 Chatwoot Inc
With regard to the Chatwoot Software:
diff --git a/enterprise/app/builders/captain/assistant_stats_builder.rb b/enterprise/app/builders/captain/assistant_stats_builder.rb
index d162406ad..93f51448b 100644
--- a/enterprise/app/builders/captain/assistant_stats_builder.rb
+++ b/enterprise/app/builders/captain/assistant_stats_builder.rb
@@ -37,6 +37,23 @@ class Captain::AssistantStatsBuilder
build_metrics(current, previous)
end
+ # Approved/pending FAQ counts and the document total in a single round trip.
+ def faq_stats
+ approved, pending, documents = Captain::AssistantResponse.by_assistant(assistant.id).reorder(nil).pick(
+ Arel.sql("COUNT(*) FILTER (WHERE status = #{Captain::AssistantResponse.statuses['approved']})"),
+ Arel.sql("COUNT(*) FILTER (WHERE status = #{Captain::AssistantResponse.statuses['pending']})"),
+ Arel.sql("(SELECT COUNT(*) FROM captain_documents WHERE assistant_id = #{assistant.id.to_i})")
+ )
+ total = approved + pending
+
+ {
+ approved: approved,
+ pending: pending,
+ documents: documents,
+ coverage: total.zero? ? 0 : (approved.to_f / total * 100).round
+ }
+ end
+
private
attr_reader :window
@@ -56,8 +73,7 @@ class Captain::AssistantStatsBuilder
handoff_rate: pack(current[:handoff], previous[:handoff], :point),
hours_saved: pack(current[:hours_saved], previous[:hours_saved], :percent),
reopen_rate: pack(current[:reopen], previous[:reopen], :point),
- conversation_depth: pack(current[:depth], previous[:depth], :absolute),
- knowledge: knowledge
+ conversation_depth: pack(current[:depth], previous[:depth], :absolute)
}
end
@@ -73,7 +89,7 @@ class Captain::AssistantStatsBuilder
auto_resolution: rate(resolution[:resolved], handled),
handoff: rate(resolution[:handoff], handled),
hours_saved: (public_count * SECONDS_SAVED_PER_REPLY / 3600.0).round,
- reopen: reopen_rate(range),
+ reopen: reopen_rate(range, resolution[:resolved]),
depth: depth_conversations.zero? ? 0 : (public_count.to_f / depth_conversations).round(1)
}
end
@@ -158,7 +174,9 @@ class Captain::AssistantStatsBuilder
# derived from the assistant's handled conversations (not current inbox membership) so a later
# inbox reassignment doesn't drop historical resolves, and covers both the evaluated (inference)
# and time-based (bot) resolve paths so the denominator matches auto_resolution_rate.
- def reopen_rate(range)
+ def reopen_rate(range, resolved_count)
+ return 0 if resolved_count.zero?
+
resolved_scope = account.reporting_events
.where(name: RESOLVED_EVENT_NAMES, created_at: range,
conversation_id: handled_scope(range).select(:conversation_id))
@@ -178,24 +196,7 @@ class Captain::AssistantStatsBuilder
'ON resolves.conversation_id = reporting_events.conversation_id ' \
'AND reporting_events.event_end_time >= resolves.event_end_time')
.distinct.count('reporting_events.conversation_id')
- rate(reopened, resolved_scope.distinct.count(:conversation_id))
- end
-
- # Approved/pending FAQ counts and the document total in a single round trip.
- def knowledge
- approved, pending, documents = Captain::AssistantResponse.by_assistant(assistant.id).reorder(nil).pick(
- Arel.sql("COUNT(*) FILTER (WHERE status = #{Captain::AssistantResponse.statuses['approved']})"),
- Arel.sql("COUNT(*) FILTER (WHERE status = #{Captain::AssistantResponse.statuses['pending']})"),
- Arel.sql("(SELECT COUNT(*) FROM captain_documents WHERE assistant_id = #{assistant.id.to_i})")
- )
- total = approved + pending
-
- {
- approved: approved,
- pending: pending,
- documents: documents,
- coverage: total.zero? ? 0 : (approved.to_f / total * 100).round
- }
+ rate(reopened, resolved_count)
end
def rate(numerator, denominator)
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/agent_sessions_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/agent_sessions_controller.rb
new file mode 100644
index 000000000..f9163de04
--- /dev/null
+++ b/enterprise/app/controllers/api/v1/accounts/captain/agent_sessions_controller.rb
@@ -0,0 +1,25 @@
+class Api::V1::Accounts::Captain::AgentSessionsController < Api::V1::Accounts::BaseController
+ before_action :set_message
+ before_action :authorize_conversation
+
+ def show
+ @agent_session = Current.account.captain_agent_sessions.find_by(result_type: 'Message', result_id: @message.id)
+ return head :not_found if @agent_session.blank?
+
+ @citations = Current.account.captain_assistant_responses
+ .where(id: @agent_session.faq_ids)
+ .includes(:documentable)
+ @scenario_titles = Captain::Scenario.where(account_id: Current.account.id, id: @agent_session.scenario_ids)
+ .pluck(:id, :title).to_h
+ end
+
+ private
+
+ def set_message
+ @message = Current.account.messages.find(params[:id])
+ end
+
+ def authorize_conversation
+ authorize @message.conversation, :show?
+ end
+end
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/assistant_responses_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/assistant_responses_controller.rb
index 151cf279c..80e05e912 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/assistant_responses_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/assistant_responses_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Assistant) }
before_action :set_current_page, only: [:index]
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb
index 4fbb93d20..f1509f11c 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb
@@ -1,8 +1,7 @@
class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Assistant) }
- before_action :set_assistant, only: [:show, :update, :destroy, :playground, :stats, :summary, :drilldown]
+ before_action :set_assistant, only: [:show, :update, :destroy, :playground, :metrics, :faq_stats, :summary, :drilldown]
def index
@assistants = account_assistants.ordered
@@ -43,12 +42,17 @@ class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::Base
@tools = assistant.available_agent_tools
end
- def stats
+ def metrics
render json: Captain::AssistantStatsBuilder.new(@assistant, params[:range], params[:timezone_offset]).metrics
end
+ def faq_stats
+ render json: Captain::AssistantStatsBuilder.new(@assistant).faq_stats
+ end
+
def summary
- result = cached_or_generated_summary(Captain::AssistantStatsBuilder.new(@assistant, params[:range], params[:timezone_offset]))
+ window = Captain::AssistantStatsWindow.new(params[:range], params[:timezone_offset])
+ result = cached_or_generated_summary(window, summary_stats)
if result[:error]
render json: { error: result[:error] }, status: :unprocessable_content
@@ -69,8 +73,8 @@ class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::Base
params.permit(:metric, :range, :timezone_offset, :page, :per_page)
end
- def cached_or_generated_summary(builder)
- cache_key = summary_cache_key(builder.range)
+ def cached_or_generated_summary(window, stats)
+ cache_key = summary_cache_key(window.range)
cached = Rails.cache.read(cache_key)
return cached if cached
@@ -78,14 +82,25 @@ class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::Base
account: Current.account,
assistant: @assistant,
first_name: Current.user.name.to_s.split.first,
- stats: builder.metrics,
- period: builder.period
+ stats: stats,
+ period: window.period
).perform
# Don't cache transient LLM/config failures, otherwise every reload returns 422 for the next hour.
Rails.cache.write(cache_key, result, expires_in: 1.hour) unless result[:error]
result
end
+ def summary_stats
+ params.require(:stats).permit(
+ conversations_handled: %i[current],
+ hours_saved: %i[current],
+ auto_resolution_rate: %i[current trend],
+ handoff_rate: %i[current trend],
+ reopen_rate: %i[current trend],
+ knowledge: %i[coverage approved documents]
+ ).to_h.deep_symbolize_keys
+ end
+
def summary_cache_key(range)
"captain_overview_summary/#{@assistant.id}/#{Current.user.id}/#{range}/#{Date.current}"
end
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb
index 7e2817f69..2bd7c8eed 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::BulkActionsController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Assistant) }
before_action :validate_params
before_action :type_matches?
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/custom_tools_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/custom_tools_controller.rb
index 874197870..f0222434c 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/custom_tools_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/custom_tools_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::CustomToolsController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action :ensure_custom_tools_enabled
before_action -> { check_authorization(Captain::CustomTool) }
before_action :set_custom_tool, only: [:show, :update, :destroy]
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/documents_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/documents_controller.rb
index d88cc6b48..cb6fb782d 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/documents_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/documents_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::DocumentsController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Assistant) }
before_action :set_current_page, only: [:index]
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/inboxes_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/inboxes_controller.rb
index f4ec303b6..88b8f2fb3 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/inboxes_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/inboxes_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::InboxesController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Assistant) }
before_action :set_assistant
diff --git a/enterprise/app/controllers/api/v1/accounts/captain/scenarios_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/scenarios_controller.rb
index 376cee0b3..fa7157dae 100644
--- a/enterprise/app/controllers/api/v1/accounts/captain/scenarios_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/captain/scenarios_controller.rb
@@ -1,5 +1,4 @@
class Api::V1::Accounts::Captain::ScenariosController < Api::V1::Accounts::BaseController
- before_action :current_account
before_action -> { check_authorization(Captain::Scenario) }
before_action :set_assistant
before_action :set_scenario, only: [:show, :update, :destroy]
diff --git a/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb b/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb
index a0627ce49..2f86e0de8 100644
--- a/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb
+++ b/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb
@@ -1,8 +1,6 @@
class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseController
- PERMISSION_REQUEST_THROTTLE = 5.minutes
-
before_action :set_call, only: %i[show accept reject terminate upload_recording]
- before_action :set_conversation, only: :initiate
+ before_action :set_call_context, only: :initiate
before_action :ensure_calling_enabled, only: :initiate
before_action :ensure_sdp_offer, only: :initiate
before_action :ensure_contact_phone, only: :initiate
@@ -53,7 +51,7 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
end
def provider_service
- @provider_service ||= @conversation.inbox.channel.provider_service
+ @provider_service ||= @inbox.channel.provider_service
end
def set_call
@@ -61,13 +59,38 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
authorize @call.conversation, :show?
end
- def set_conversation
+ def set_call_context
+ params[:conversation_id].present? ? set_context_from_conversation : set_context_from_contact
+ end
+
+ def set_context_from_conversation
@conversation = Current.account.conversations.find_by!(display_id: params[:conversation_id])
authorize @conversation, :show?
+ @inbox = @conversation.inbox
+ @contact = @conversation.contact
+ end
+
+ def set_context_from_contact
+ @inbox = Current.account.inboxes.find(params[:inbox_id])
+ authorize @inbox, :show?
+ @contact = Current.account.contacts.find(params[:contact_id])
+ @conversation = conversation_builder.existing_conversation
+ # Authorize the thread the call will land in — after the dial is too late to refuse a ringing call.
+ authorize(@conversation || conversation_builder.new_conversation, :show?)
+ end
+
+ def conversation_builder
+ @conversation_builder ||= Whatsapp::CallConversationBuilder.new(inbox: @inbox, contact: @contact, user: Current.user)
+ end
+
+ # Created only after the dial succeeds, so a failed call leaves no empty thread and there is nothing to
+ # roll back. Re-authorized because a concurrent caller may have created the thread we get back.
+ def open_conversation!
+ (@conversation || conversation_builder.perform!).tap { |conversation| authorize conversation, :show? }
end
def ensure_calling_enabled
- channel = @conversation.inbox.channel
+ channel = @inbox.channel
return if channel.is_a?(Channel::Whatsapp) && channel.voice_enabled?
render_could_not_create_error(I18n.t('errors.whatsapp.calls.not_enabled'))
@@ -80,7 +103,7 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
end
def ensure_contact_phone
- return if @conversation.contact&.phone_number.present?
+ return if @contact.phone_number.present?
render_could_not_create_error(I18n.t('errors.whatsapp.calls.contact_phone_required'))
end
@@ -105,92 +128,45 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
end
def create_outbound_call
- contact_phone = @conversation.contact.phone_number.delete('+')
- # Claim for the caller only if unassigned at trigger time (before the round-trip); wins over auto-assignment.
- claim_for_caller = @conversation.assignee_id.nil?
+ # A reused thread unassigned at click time is claimed for the caller (wins over auto-assignment); a
+ # fresh thread (@conversation nil until the dial succeeds) is created already assigned to the caller.
+ claim_for_caller = @conversation.present? && @conversation.assignee_id.nil?
- result = provider_service.initiate_call(contact_phone, params[:sdp_offer])
+ result = provider_service.initiate_call(@contact.phone_number.delete('+'), params[:sdp_offer])
provider_call_id = result.dig('calls', 0, 'id') || result['call_id']
+ @conversation = open_conversation!
@conversation.with_lock { @conversation.update!(assignee: Current.user) } if claim_for_caller
+ create_call_record(provider_call_id)
+ end
+
+ def create_call_record(provider_call_id)
+ existing = Current.account.calls.whatsapp.find_by(provider_call_id: provider_call_id)
+ return existing if existing
+
Current.account.calls.create!(
provider: :whatsapp, inbox: @conversation.inbox, conversation: @conversation, contact: @conversation.contact,
provider_call_id: provider_call_id, direction: :outgoing, status: 'ringing',
accepted_by_agent_id: Current.user.id,
meta: { 'sdp_offer' => params[:sdp_offer], 'ice_servers' => Call.default_ice_servers }
)
+ rescue ActiveRecord::RecordNotUnique
+ # A webhook inserted the row between the find_by above and this create; reconcile to it.
+ Current.account.calls.whatsapp.find_by!(provider_call_id: provider_call_id)
end
- # Meta error 138006 means the contact hasn't opted in yet; send the opt-in
- # template (throttled, behind a conversation lock to prevent double-send).
def render_permission_request
- status = nil
- @conversation.with_lock do
- if permission_request_throttled?
- status = 'permission_pending'
- next
- end
-
- sent = send_permission_request_safely
- if sent
- record_permission_request_wamid(sent)
- emit_permission_requested_activity
- status = 'permission_requested'
- else
- status = 'failed'
- end
- end
+ # Raised mid-dial, so a fresh contact has no thread yet — open one for the opt-in template to land in.
+ @conversation = open_conversation!
+ status = Whatsapp::CallPermissionRequestService.new(conversation: @conversation).perform
return render_could_not_create_error(I18n.t('errors.whatsapp.calls.permission_request_failed')) if status == 'failed'
# 422 (not 200) so any client treating 2xx as "call placed" can't mistake
# the permission-template path for a successful dial. The FE composable
# detects this status and surfaces the banner instead of throwing.
- render json: { status: status }, status: :unprocessable_entity
- end
-
- def permission_request_throttled?
- last_requested = @conversation.additional_attributes&.dig('call_permission_requested_at')
- last_requested.present? && Time.zone.parse(last_requested) > PERMISSION_REQUEST_THROTTLE.ago
- end
-
- # Treat transport errors as a falsy return so we render 422 rather than 500.
- def send_permission_request_safely
- provider_service.send_call_permission_request(
- @conversation.contact.phone_number.delete('+'),
- *permission_request_body_args
- )
- rescue StandardError => e
- Rails.logger.warn "[WHATSAPP CALL] permission_request failed: #{e.class} #{e.message}"
- nil
- end
-
- # Pass the inbox-level override only when present so the provider falls back
- # to the i18n default for inboxes that haven't customized the prompt.
- def permission_request_body_args
- custom_body = @conversation.inbox.channel.provider_config&.dig('call_permission_request_body').presence
- custom_body ? [custom_body] : []
- end
-
- def emit_permission_requested_activity
- content = I18n.t(
- 'conversations.activity.whatsapp_call.permission_requested',
- contact_name: @conversation.contact.name
- )
- ::Conversations::ActivityMessageJob.perform_later(
- @conversation,
- { account_id: @conversation.account_id, inbox_id: @conversation.inbox_id, message_type: :activity, content: content }
- )
- end
-
- # Stash the outbound wamid so the reply webhook can match context.id back here.
- def record_permission_request_wamid(sent)
- attrs = (@conversation.additional_attributes || {}).merge(
- 'call_permission_requested_at' => Time.current.iso8601,
- 'call_permission_request_message_id' => sent.dig('messages', 0, 'id')
- )
- @conversation.update!(additional_attributes: attrs)
+ render json: { status: status, conversation_id: @conversation.display_id }, status: :unprocessable_entity
end
def render_call_error(error)
diff --git a/enterprise/app/controllers/enterprise/api/v1/accounts/agents_controller.rb b/enterprise/app/controllers/enterprise/api/v1/accounts/agents_controller.rb
index b3a27c4ad..02d027b58 100644
--- a/enterprise/app/controllers/enterprise/api/v1/accounts/agents_controller.rb
+++ b/enterprise/app/controllers/enterprise/api/v1/accounts/agents_controller.rb
@@ -1,6 +1,8 @@
module Enterprise::Api::V1::Accounts::AgentsController
def create
super
+ return if @agent.blank?
+
associate_agent_with_custom_role
end
diff --git a/enterprise/app/controllers/twilio/voice_controller.rb b/enterprise/app/controllers/twilio/voice_controller.rb
index 66fef9583..52ec2637b 100644
--- a/enterprise/app/controllers/twilio/voice_controller.rb
+++ b/enterprise/app/controllers/twilio/voice_controller.rb
@@ -107,8 +107,8 @@ class Twilio::VoiceController < ApplicationController
when 'inbound'
Voice::InboundCallBuilder.perform!(
inbox: inbox,
- from_number: twilio_from,
- call_sid: twilio_call_sid
+ call_sid: twilio_call_sid,
+ caller: { source_ids: [twilio_from], contact_attributes: { name: twilio_from, phone_number: twilio_from } }
)
when 'outbound-api', 'outbound-dial'
sync_outbound_leg(call_sid: twilio_call_sid, direction: twilio_direction)
diff --git a/enterprise/app/policies/captain/assistant_policy.rb b/enterprise/app/policies/captain/assistant_policy.rb
index 573c0400c..fdcb2db89 100644
--- a/enterprise/app/policies/captain/assistant_policy.rb
+++ b/enterprise/app/policies/captain/assistant_policy.rb
@@ -7,7 +7,11 @@ class Captain::AssistantPolicy < ApplicationPolicy
true
end
- def stats?
+ def metrics?
+ true
+ end
+
+ def faq_stats?
true
end
diff --git a/enterprise/app/services/captain/assistant/session_capture_service.rb b/enterprise/app/services/captain/assistant/session_capture_service.rb
index d41a1b874..4de594883 100644
--- a/enterprise/app/services/captain/assistant/session_capture_service.rb
+++ b/enterprise/app/services/captain/assistant/session_capture_service.rb
@@ -22,13 +22,12 @@ class Captain::Assistant::SessionCaptureService
def capture!
model = @assistant.agent_model
- metadata = context.dig(:state, :cw_metadata) || {}
Captain::AgentSession.create!(
assistant: @assistant,
session_type: :assistant,
subject: @conversation,
- result: @result_message,
+ result: result_message,
llm_model: "#{Llm::Models.provider_for(model)}-#{model}",
credits_consumed: @credits_consumed,
faq_ids: metadata[:faq_ids] || [],
@@ -44,6 +43,23 @@ class Captain::Assistant::SessionCaptureService
@run_result.context || {}
end
+ def metadata
+ @metadata ||= context.dig(:state, :cw_metadata) || {}
+ end
+
+ # On handoff, HandoffTool records the private reason note it created; the session
+ # attaches there so agents can inspect the generation path on the note itself.
+ def result_message
+ handoff_note || @result_message
+ end
+
+ def handoff_note
+ note_id = metadata[:handoff_note_id]
+ return if note_id.blank?
+
+ @conversation.messages.find_by(id: note_id)
+ end
+
def scenario_ids
ids = current_turn_history.filter_map do |message|
next unless message[:role].to_s == 'assistant'
@@ -62,6 +78,11 @@ class Captain::Assistant::SessionCaptureService
return history[turn_start_index..] if turn_start_index
last_user_index = history.rindex { |message| message[:role].to_s == 'user' }
- last_user_index ? history[last_user_index..] : history
+ current_turn = last_user_index ? history[last_user_index..] : history
+
+ current_turn.map do |message|
+ content = message[:content]
+ content.is_a?(RubyLLM::Content) ? message.merge(content: content.to_h) : message
+ end
end
end
diff --git a/enterprise/app/services/voice/inbound_call_builder.rb b/enterprise/app/services/voice/inbound_call_builder.rb
index eef70e76b..c928da43f 100644
--- a/enterprise/app/services/voice/inbound_call_builder.rb
+++ b/enterprise/app/services/voice/inbound_call_builder.rb
@@ -1,17 +1,19 @@
class Voice::InboundCallBuilder
- attr_reader :inbox, :from_number, :call_sid, :provider, :extra_meta
+ attr_reader :inbox, :call_sid, :provider, :extra_meta, :source_ids, :contact_attributes
- def self.perform!(inbox:, from_number:, call_sid:, provider: :twilio, extra_meta: {})
- new(inbox: inbox, from_number: from_number, call_sid: call_sid,
- provider: provider, extra_meta: extra_meta).perform!
+ # `caller` carries the contact identity: { source_ids:, contact_attributes: }. Twilio passes
+ # its single +phone source_id; WhatsApp passes the message-path phone/user_id/parent_user_id set.
+ def self.perform!(inbox:, call_sid:, caller:, provider: :twilio, extra_meta: {})
+ new(inbox: inbox, call_sid: call_sid, caller: caller, provider: provider, extra_meta: extra_meta).perform!
end
- def initialize(inbox:, from_number:, call_sid:, provider: :twilio, extra_meta: {})
+ def initialize(inbox:, call_sid:, caller:, provider: :twilio, extra_meta: {})
@inbox = inbox
- @from_number = from_number
@call_sid = call_sid
@provider = provider.to_sym
@extra_meta = extra_meta || {}
+ @source_ids = Array(caller[:source_ids]).compact_blank
+ @contact_attributes = caller[:contact_attributes] || {}
end
def perform!
@@ -43,46 +45,17 @@ class Voice::InboundCallBuilder
.find_by(provider: provider, provider_call_id: call_sid)
end
- # Always look up by (inbox, source_id) first — that pair has a UNIQUE index, so
- # creating with a colliding source_id under a different contact would raise
- # RecordNotUnique. Reuse the existing ContactInbox (and its contact) when found.
- # A concurrent message webhook for the same wa_id can win the (inbox_id, source_id)
- # race; rescue and re-find so the call path doesn't drop the connect.
+ # Resolve the contact/ContactInbox the same way inbound messages do — match across every
+ # candidate source_id (phone + BSUID aliases) so a call reuses the existing thread, creating
+ # one keyed on the first (phone, else BSUID) only when none exists. Shared with messaging via
+ # ContactInboxSourceIdResolver, which also rescues the concurrent-webhook create race.
def ensure_contact_inbox!
- sid = source_id_for_provider
- existing = inbox.contact_inboxes.find_by(source_id: sid)
- return existing if existing
-
- ContactInbox.create!(contact: ensure_contact!, inbox: inbox, source_id: sid)
- rescue ActiveRecord::RecordNotUnique
- inbox.contact_inboxes.find_by!(source_id: sid)
+ ContactInboxSourceIdResolver.new(
+ inbox: inbox, source_ids: source_ids, contact_attributes: contact_attributes
+ ).perform
end
- def ensure_contact!
- contact = account.contacts.find_or_create_by!(phone_number: from_number) do |record|
- record.name = contact_name.presence || from_number
- end
- contact.update!(name: contact_name) if contact_name.present? && contact.name == from_number
- contact
- end
-
- # WhatsApp inbound calls carry the caller's profile name in extra_meta; Twilio
- # calls don't, so contact naming falls back to the phone number.
- def contact_name
- extra_meta['contact_name'].presence
- end
-
- # WhatsApp ContactInbox.source_id must be digits-only (the wa_id); Twilio accepts the +.
- # Run BR/AR-style wa_id normalization (same path messaging uses) so an inbound call
- # finds the existing ContactInbox instead of forking a new contact/conversation.
- def source_id_for_provider
- return from_number unless provider == :whatsapp
-
- digits = from_number.to_s.delete_prefix('+')
- Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact_by_provider(digits, :cloud)
- end
-
- # Mirror incoming-message routing: reuse the open conversation (or the last one when locked), else create new.
+ # Mirror Whatsapp::IncomingMessageBaseService#set_conversation: reuse this row's open conversation (or last when locked), else create.
def resolve_conversation!(contact, contact_inbox)
reusable = if inbox.lock_to_single_conversation
contact_inbox.conversations.last
diff --git a/enterprise/app/services/whatsapp/call_conversation_builder.rb b/enterprise/app/services/whatsapp/call_conversation_builder.rb
new file mode 100644
index 000000000..665f2fb20
--- /dev/null
+++ b/enterprise/app/services/whatsapp/call_conversation_builder.rb
@@ -0,0 +1,32 @@
+class Whatsapp::CallConversationBuilder
+ pattr_initialize [:inbox!, :contact!, :user!]
+
+ # Mirrors the continuity rule in Whatsapp::IncomingMessageBaseService#set_conversation.
+ # Locked inboxes hold a contact to one thread, so the caller is refused rather than given a second one.
+ def existing_conversation
+ return contact_conversations.first if inbox.lock_to_single_conversation
+
+ # Only threads the caller can open, else a newest-but-hidden thread would block the call.
+ Conversations::PermissionFilterService.new(
+ contact_conversations.where.not(status: :resolved), user, inbox.account
+ ).perform.first
+ end
+
+ def contact_conversations
+ inbox.conversations.where(contact_id: contact.id).order(last_activity_at: :desc)
+ end
+
+ # Unsaved, so callers can authorize the thread a call would open before dialing.
+ def new_conversation
+ inbox.account.conversations.new(inbox: inbox, contact: contact, assignee_id: user.id, status: :open)
+ end
+
+ # Locked so two agents calling the same fresh contact can't open two threads.
+ def perform!
+ contact_inbox = ContactInboxBuilder.new(contact: contact, inbox: inbox).perform
+
+ contact_inbox.with_lock do
+ existing_conversation || new_conversation.tap { |conversation| conversation.update!(contact_inbox: contact_inbox) }
+ end
+ end
+end
diff --git a/enterprise/app/services/whatsapp/call_permission_request_service.rb b/enterprise/app/services/whatsapp/call_permission_request_service.rb
new file mode 100644
index 000000000..65c4f1506
--- /dev/null
+++ b/enterprise/app/services/whatsapp/call_permission_request_service.rb
@@ -0,0 +1,63 @@
+# Meta error 138006 means the contact hasn't opted in to calls yet; send the opt-in template.
+class Whatsapp::CallPermissionRequestService
+ THROTTLE = 5.minutes
+
+ pattr_initialize [:conversation!]
+
+ # Locked so two agents calling the same contact can't both send the template.
+ def perform
+ conversation.with_lock do
+ next 'permission_pending' if throttled?
+
+ sent = send_request_safely
+ next 'failed' if sent.blank?
+
+ record_wamid(sent)
+ emit_activity
+ 'permission_requested'
+ end
+ end
+
+ private
+
+ def throttled?
+ last_requested = conversation.additional_attributes&.dig('call_permission_requested_at')
+ last_requested.present? && Time.zone.parse(last_requested) > THROTTLE.ago
+ end
+
+ # Treat transport errors as a falsy return so the caller renders 422 rather than 500.
+ def send_request_safely
+ provider_service.send_call_permission_request(conversation.contact.phone_number.delete('+'), *body_args)
+ rescue StandardError => e
+ Rails.logger.warn "[WHATSAPP CALL] permission_request failed: #{e.class} #{e.message}"
+ nil
+ end
+
+ # Pass the inbox-level override only when present so the provider falls back
+ # to the i18n default for inboxes that haven't customized the prompt.
+ def body_args
+ custom_body = conversation.inbox.channel.provider_config&.dig('call_permission_request_body').presence
+ custom_body ? [custom_body] : []
+ end
+
+ def emit_activity
+ content = I18n.t('conversations.activity.whatsapp_call.permission_requested', contact_name: conversation.contact.name)
+ ::Conversations::ActivityMessageJob.perform_later(
+ conversation,
+ { account_id: conversation.account_id, inbox_id: conversation.inbox_id, message_type: :activity, content: content }
+ )
+ end
+
+ # Stash the outbound wamid so the reply webhook can match context.id back here.
+ def record_wamid(sent)
+ attrs = (conversation.additional_attributes || {}).merge(
+ 'call_permission_requested_at' => Time.current.iso8601,
+ 'call_permission_request_message_id' => sent.dig('messages', 0, 'id')
+ )
+ conversation.update!(additional_attributes: attrs)
+ end
+
+ def provider_service
+ @provider_service ||= conversation.inbox.channel.provider_service
+ end
+end
diff --git a/enterprise/app/services/whatsapp/inbound_call_identity_builder.rb b/enterprise/app/services/whatsapp/inbound_call_identity_builder.rb
new file mode 100644
index 000000000..590a1f923
--- /dev/null
+++ b/enterprise/app/services/whatsapp/inbound_call_identity_builder.rb
@@ -0,0 +1,48 @@
+class Whatsapp::InboundCallIdentityBuilder
+ pattr_initialize [:inbox!, :params!]
+
+ # Build the message path's source_id set (phone wa_id -> user_id -> parent_user_id) plus
+ # contact attributes, so the resolver lands a call on the same ContactInbox a message would.
+ # BSUIDs ride in from_user_id/from_parent_user_id (or the contact's user_id/parent_user_id),
+ # never in `from` (the phone wa_id).
+ def perform(payload)
+ contact = caller_contact(payload)
+ phone = contact[:wa_id].presence || payload[:from].presence
+ source_ids = [
+ phone_source_id(phone),
+ payload[:from_user_id].presence || contact[:user_id].presence,
+ payload[:from_parent_user_id].presence || contact[:parent_user_id].presence
+ ].compact_blank.uniq
+ { source_ids: source_ids, contact_attributes: contact_attributes(contact, phone, source_ids.first) }
+ end
+
+ private
+
+ # Normalize the wa_id the same way messaging does so a call matches its stored source_id.
+ def phone_source_id(phone)
+ return unless phone.to_s.match?(/\A\d{1,15}\z/)
+
+ Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact_by_provider(phone.to_s, :cloud)
+ end
+
+ def contact_attributes(contact, phone, source_identifier)
+ name = contact.dig(:profile, :name).presence || source_identifier
+ return { name: name } unless phone.to_s.match?(/\A\d{1,15}\z/)
+
+ formatted = "+#{phone}"
+ { name: name == phone ? formatted : name, phone_number: formatted }
+ end
+
+ # Match the contacts entry to THIS caller so batched payloads don't borrow another's identity.
+ def caller_contact(payload)
+ Array(params[:contacts]).map(&:with_indifferent_access).find do |c|
+ identifier_match?(c[:wa_id], payload[:from]) ||
+ identifier_match?(c[:user_id], payload[:from_user_id]) ||
+ identifier_match?(c[:parent_user_id], payload[:from_parent_user_id])
+ end || {}.with_indifferent_access
+ end
+
+ def identifier_match?(left, right)
+ left.present? && right.present? && left.to_s == right.to_s
+ end
+end
diff --git a/enterprise/app/services/whatsapp/incoming_call_service.rb b/enterprise/app/services/whatsapp/incoming_call_service.rb
index 11b35d95a..ea08c8415 100644
--- a/enterprise/app/services/whatsapp/incoming_call_service.rb
+++ b/enterprise/app/services/whatsapp/incoming_call_service.rb
@@ -95,28 +95,21 @@ class Whatsapp::IncomingCallService
# commit) already terminal, never `ringing` — agents aren't rung for a dead call.
def build_inbound_call(payload, sdp_offer)
ActiveRecord::Base.transaction do
- call = Voice::InboundCallBuilder.perform!(inbox: inbox, from_number: "+#{payload[:from]}", call_sid: payload[:id],
- provider: :whatsapp, extra_meta: inbound_extra_meta(payload, sdp_offer))
+ identity = Whatsapp::InboundCallIdentityBuilder.new(inbox: inbox, params: params).perform(payload)
+ extra_meta = { 'sdp_offer' => sdp_offer, 'ice_servers' => Call.default_ice_servers }
+ call = Voice::InboundCallBuilder.perform!(inbox: inbox, call_sid: payload[:id],
+ provider: :whatsapp, extra_meta: extra_meta, caller: identity)
+ sync_caller_identifiers(call, identity)
tombstone = consume_terminate_tombstone(payload[:id])
finalize_terminate(call, tombstone['duration'], tombstone['terminate_reason']) if tombstone
call
end
end
- def inbound_extra_meta(payload, sdp_offer)
- extra_meta = { 'sdp_offer' => sdp_offer, 'ice_servers' => Call.default_ice_servers }
- name = caller_profile_name(payload)
- extra_meta['contact_name'] = name if name.present?
- extra_meta
- end
-
- # Match strictly on wa_id (== calls[].from): in a batched payload missing this
- # call's contact entry, borrowing another caller's name would corrupt this
- # contact, so fall back to the phone number (nil here) instead of contacts.first.
- def caller_profile_name(payload)
- contacts = Array(params[:contacts]).map(&:with_indifferent_access)
- match = contacts.find { |c| c[:wa_id].to_s == payload[:from].to_s }
- match&.dig(:profile, :name).presence
+ # Backfill every caller alias (the builder only stores the first) so a later event keyed on any one lands on this thread.
+ def sync_caller_identifiers(call, identity)
+ Whatsapp::IdentifierSyncService.new(contact_inbox: call.conversation.contact_inbox, contact: call.contact)
+ .perform(source_ids: identity[:source_ids], phone_number: identity.dig(:contact_attributes, :phone_number))
end
# `connect` is the WebRTC tunnel-ready signal, not the pickup signal. Apply
diff --git a/enterprise/app/views/api/v1/accounts/captain/agent_sessions/show.json.jbuilder b/enterprise/app/views/api/v1/accounts/captain/agent_sessions/show.json.jbuilder
new file mode 100644
index 000000000..1e1cd1d7d
--- /dev/null
+++ b/enterprise/app/views/api/v1/accounts/captain/agent_sessions/show.json.jbuilder
@@ -0,0 +1,18 @@
+json.id @agent_session.id
+json.message_id @agent_session.result_id
+json.llm_model @agent_session.llm_model
+json.credits_consumed @agent_session.credits_consumed
+json.run_context @agent_session.run_context.is_a?(Array) ? @agent_session.run_context : []
+json.citations @citations do |citation|
+ json.id citation.id
+ json.title citation.question
+ # display_url resolves uploaded PDFs to their blob URL; external_link holds a
+ # "PDF: ..." placeholder for those. Guard on scheme so placeholders render as
+ # plain text instead of dead anchors.
+ link = citation.documentable.is_a?(Captain::Document) ? citation.documentable.display_url : nil
+ json.link link&.match?(%r{\Ahttps?://}) ? link : nil
+end
+json.scenarios @scenario_titles do |id, title|
+ json.id id
+ json.title title
+end
diff --git a/enterprise/app/views/api/v1/accounts/whatsapp_calls/initiate.json.jbuilder b/enterprise/app/views/api/v1/accounts/whatsapp_calls/initiate.json.jbuilder
index bdb1fa204..920c5bb7d 100644
--- a/enterprise/app/views/api/v1/accounts/whatsapp_calls/initiate.json.jbuilder
+++ b/enterprise/app/views/api/v1/accounts/whatsapp_calls/initiate.json.jbuilder
@@ -2,4 +2,5 @@ json.status 'calling'
json.call_id @call.provider_call_id
json.id @call.id
json.message_id @message.id
+json.conversation_id @conversation.display_id
json.provider 'whatsapp'
diff --git a/enterprise/lib/captain/tools/handoff_tool.rb b/enterprise/lib/captain/tools/handoff_tool.rb
index d126840be..f3ca8b1fe 100644
--- a/enterprise/lib/captain/tools/handoff_tool.rb
+++ b/enterprise/lib/captain/tools/handoff_tool.rb
@@ -13,7 +13,7 @@ class Captain::Tools::HandoffTool < Captain::Tools::BasePublicTool
})
# Use existing handoff mechanism from ResponseBuilderJob
- trigger_handoff(conversation, reason)
+ trigger_handoff(tool_context, conversation, reason)
"Conversation handed off to human support team#{" (Reason: #{reason})" if reason}"
rescue StandardError => e
@@ -23,9 +23,9 @@ class Captain::Tools::HandoffTool < Captain::Tools::BasePublicTool
private
- def trigger_handoff(conversation, reason)
+ def trigger_handoff(tool_context, conversation, reason)
# post the reason as a private note
- conversation.messages.create!(
+ note = conversation.messages.create!(
message_type: :outgoing,
private: true,
sender: @assistant,
@@ -34,6 +34,15 @@ class Captain::Tools::HandoffTool < Captain::Tools::BasePublicTool
content: reason
)
+ # Session capture attributes the run to this note so agents can inspect the
+ # generation path on the handoff reason instead of the canned follow-up message.
+ # A reason-less note has no content and never renders in the dashboard, so
+ # leave it unrecorded and let capture fall back to the follow-up message.
+ if reason.present?
+ metadata = tool_context.state[:cw_metadata] ||= {}
+ metadata[:handoff_note_id] = note.id
+ end
+
# Trigger the bot handoff (sets status to open + dispatches events)
conversation.bot_handoff!
diff --git a/lib/captain/overview_summary_service.rb b/lib/captain/overview_summary_service.rb
index e11132d42..43eb8c24c 100644
--- a/lib/captain/overview_summary_service.rb
+++ b/lib/captain/overview_summary_service.rb
@@ -32,6 +32,7 @@ class Captain::OverviewSummaryService < Captain::BaseTaskService
{
'first_name' => first_name.to_s,
'assistant_name' => assistant.name.to_s,
+ 'language' => account.locale_english_name,
'conversations_handled' => current(:conversations_handled),
'hours_saved' => current(:hours_saved),
'auto_resolution_rate' => current(:auto_resolution_rate),
diff --git a/lib/integrations/openai/openai_prompts/captain_overview_summary.liquid b/lib/integrations/openai/openai_prompts/captain_overview_summary.liquid
index 19c32ed7c..c5637da0f 100644
--- a/lib/integrations/openai/openai_prompts/captain_overview_summary.liquid
+++ b/lib/integrations/openai/openai_prompts/captain_overview_summary.liquid
@@ -1,7 +1,8 @@
You are writing a short, warm summary of how an AI support assistant named "{{ assistant_name }}" performed over a reporting period, for {{ first_name }}, the person who manages it.
Voice and format:
-- Address {{ first_name }} directly and open with "Hey {{ first_name }},". Be conversational, never robotic.
+- Write the entire summary in {{ language }}.
+- Address {{ first_name }} directly and open with a short casual greeting to {{ first_name }} in {{ language }}, the natural equivalent of "Hey {{ first_name }},". Never leave the greeting in English when {{ language }} is not English. Be conversational, never robotic.
- Always call the assistant by its name, {{ assistant_name }}. Never call it "Captain", "the assistant", or "your assistant".
- This is a static, read-only poster on an analytics dashboard, not a chat. The reader cannot reply or ask you for anything. Never ask a question, invite a reply, offer further help, or say things like "let me know" or "I can dive in".
- Write 2 to 4 sentences in one short paragraph. Add a second short paragraph only for a genuinely useful heads-up.
diff --git a/package.json b/package.json
index d964a30a4..5c3ac2229 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@chatwoot/chatwoot",
- "version": "4.15.1",
+ "version": "4.16.0",
"license": "MIT",
"scripts": {
"eslint": "eslint app/**/*.{js,vue}",
@@ -34,8 +34,8 @@
"@amplitude/analytics-browser": "^2.11.10",
"@breezystack/lamejs": "^1.2.7",
"@chatwoot/ninja-keys": "1.2.3",
- "@chatwoot/prosemirror-schema": "1.3.22",
- "@chatwoot/utils": "^0.0.55",
+ "@chatwoot/prosemirror-schema": "1.3.23",
+ "@chatwoot/utils": "^0.0.56",
"@formkit/core": "^1.7.2",
"@formkit/vue": "^1.7.2",
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
@@ -86,9 +86,6 @@
"mitt": "^3.0.1",
"opus-recorder": "^8.0.5",
"pinia": "^3.0.4",
- "prosemirror-commands": "^1.7.1",
- "prosemirror-inputrules": "^1.4.0",
- "prosemirror-schema-list": "^1.5.1",
"qrcode": "^1.5.4",
"semver": "7.6.3",
"snakecase-keys": "^8.0.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0ffb85c18..87c892d19 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -25,11 +25,11 @@ importers:
specifier: 1.2.3
version: 1.2.3
'@chatwoot/prosemirror-schema':
- specifier: 1.3.22
- version: 1.3.22
+ specifier: 1.3.23
+ version: 1.3.23
'@chatwoot/utils':
- specifier: ^0.0.55
- version: 0.0.55
+ specifier: ^0.0.56
+ version: 0.0.56
'@formkit/core':
specifier: ^1.7.2
version: 1.7.2
@@ -180,15 +180,6 @@ importers:
pinia:
specifier: ^3.0.4
version: 3.0.4(typescript@5.6.2)(vue@3.5.12(typescript@5.6.2))
- prosemirror-commands:
- specifier: ^1.7.1
- version: 1.7.1
- prosemirror-inputrules:
- specifier: ^1.4.0
- version: 1.4.0
- prosemirror-schema-list:
- specifier: ^1.5.1
- version: 1.5.1
qrcode:
specifier: ^1.5.4
version: 1.5.4
@@ -461,11 +452,11 @@ packages:
'@chatwoot/ninja-keys@1.2.3':
resolution: {integrity: sha512-xM8d9P5ikDMZm2WbaCTk/TW5HFauylrU3cJ75fq5je6ixKwyhl/0kZbVN/vbbZN4+AUX/OaSIn6IJbtCgIF67g==}
- '@chatwoot/prosemirror-schema@1.3.22':
- resolution: {integrity: sha512-0r+PT8xhQLCKCpoV9k9XVTTRECs/0Nr37wbcLsRS7yvc7WkF9FY05z2hGCRJReWmTOcmmshHtb042LVP+MyB/w==}
+ '@chatwoot/prosemirror-schema@1.3.23':
+ resolution: {integrity: sha512-jGxbWELCdlVI64BJiE1wT84ekJHYDXXKiluQIKT3aKPEjPwMR48umKF3A0yHjKoR7IIxCC9oM77TvXOA0ebLtw==}
- '@chatwoot/utils@0.0.55':
- resolution: {integrity: sha512-8G6HYQe1ZEYfJEsSYfDVvE+uhf98JDRjtGlpB+bzMko+yltbrk4yACSo/ImC3jSaJ6K8yPTSjJToSRmsQbL2iQ==}
+ '@chatwoot/utils@0.0.56':
+ resolution: {integrity: sha512-A6dmPLfTSrW4qYNY73btyi4PqpfzcXRSaucscZTQdzNqF6G/QUdgnBmHtho8HeiYby/kSHXaSxLJj+0dx3yEQQ==}
engines: {node: '>=10'}
'@codemirror/commands@6.7.0':
@@ -4001,9 +3992,6 @@ packages:
prosemirror-tables@1.5.0:
resolution: {integrity: sha512-VMx4zlYWm7aBlZ5xtfJHpqa3Xgu3b7srV54fXYnXgsAcIGRqKSrhiK3f89omzzgaAgAtDOV4ImXnLKhVfheVNQ==}
- prosemirror-transform@1.10.0:
- resolution: {integrity: sha512-9UOgFSgN6Gj2ekQH5CTDJ8Rp/fnKR2IkYfGdzzp5zQMFsS4zDllLVx/+jGcX86YlACpG7UR5fwAXiWzxqWtBTg==}
-
prosemirror-transform@1.12.0:
resolution: {integrity: sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==}
@@ -5136,7 +5124,7 @@ snapshots:
hotkeys-js: 3.8.7
lit: 2.2.6
- '@chatwoot/prosemirror-schema@1.3.22':
+ '@chatwoot/prosemirror-schema@1.3.23':
dependencies:
markdown-it-sup: 2.0.0
prosemirror-commands: 1.7.1
@@ -5154,7 +5142,7 @@ snapshots:
prosemirror-utils: 1.2.2(prosemirror-model@1.22.3)(prosemirror-state@1.4.3)
prosemirror-view: 1.34.1
- '@chatwoot/utils@0.0.55':
+ '@chatwoot/utils@0.0.56':
dependencies:
date-fns: 2.30.0
@@ -9035,7 +9023,7 @@ snapshots:
dependencies:
prosemirror-model: 1.22.3
prosemirror-state: 1.4.3
- prosemirror-transform: 1.10.0
+ prosemirror-transform: 1.12.0
prosemirror-state@1.4.3:
dependencies:
@@ -9051,10 +9039,6 @@ snapshots:
prosemirror-transform: 1.12.0
prosemirror-view: 1.34.1
- prosemirror-transform@1.10.0:
- dependencies:
- prosemirror-model: 1.22.3
-
prosemirror-transform@1.12.0:
dependencies:
prosemirror-model: 1.22.3
diff --git a/public/android-icon-144x144.png b/public/android-icon-144x144.png
index 45c07cc11..a27e7f7b0 100644
Binary files a/public/android-icon-144x144.png and b/public/android-icon-144x144.png differ
diff --git a/public/android-icon-192x192.png b/public/android-icon-192x192.png
index df03935ea..e5eaa1032 100644
Binary files a/public/android-icon-192x192.png and b/public/android-icon-192x192.png differ
diff --git a/public/android-icon-36x36.png b/public/android-icon-36x36.png
index e9e928769..fb7690ad2 100644
Binary files a/public/android-icon-36x36.png and b/public/android-icon-36x36.png differ
diff --git a/public/android-icon-48x48.png b/public/android-icon-48x48.png
index a90fa1eda..7fb8e86cc 100644
Binary files a/public/android-icon-48x48.png and b/public/android-icon-48x48.png differ
diff --git a/public/android-icon-72x72.png b/public/android-icon-72x72.png
index ac98be771..8fd338f58 100644
Binary files a/public/android-icon-72x72.png and b/public/android-icon-72x72.png differ
diff --git a/public/android-icon-96x96.png b/public/android-icon-96x96.png
index 5fc50e9fc..de2e82032 100644
Binary files a/public/android-icon-96x96.png and b/public/android-icon-96x96.png differ
diff --git a/public/apple-icon-114x114.png b/public/apple-icon-114x114.png
index ca65ac675..3dd22c099 100644
Binary files a/public/apple-icon-114x114.png and b/public/apple-icon-114x114.png differ
diff --git a/public/apple-icon-120x120.png b/public/apple-icon-120x120.png
index cc8af3d12..593ce3ec2 100644
Binary files a/public/apple-icon-120x120.png and b/public/apple-icon-120x120.png differ
diff --git a/public/apple-icon-144x144.png b/public/apple-icon-144x144.png
index 45c07cc11..a27e7f7b0 100644
Binary files a/public/apple-icon-144x144.png and b/public/apple-icon-144x144.png differ
diff --git a/public/apple-icon-152x152.png b/public/apple-icon-152x152.png
index 12b598711..b469546ac 100644
Binary files a/public/apple-icon-152x152.png and b/public/apple-icon-152x152.png differ
diff --git a/public/apple-icon-180x180.png b/public/apple-icon-180x180.png
index d72c12398..b1836b9f5 100644
Binary files a/public/apple-icon-180x180.png and b/public/apple-icon-180x180.png differ
diff --git a/public/apple-icon-57x57.png b/public/apple-icon-57x57.png
index 7daa2fc9e..319bee681 100644
Binary files a/public/apple-icon-57x57.png and b/public/apple-icon-57x57.png differ
diff --git a/public/apple-icon-60x60.png b/public/apple-icon-60x60.png
index 8df0dc266..db095da54 100644
Binary files a/public/apple-icon-60x60.png and b/public/apple-icon-60x60.png differ
diff --git a/public/apple-icon-72x72.png b/public/apple-icon-72x72.png
index ac98be771..8fd338f58 100644
Binary files a/public/apple-icon-72x72.png and b/public/apple-icon-72x72.png differ
diff --git a/public/apple-icon-76x76.png b/public/apple-icon-76x76.png
index 1e9e9f139..5a9e25f8f 100644
Binary files a/public/apple-icon-76x76.png and b/public/apple-icon-76x76.png differ
diff --git a/public/apple-icon-precomposed.png b/public/apple-icon-precomposed.png
index c700e55e0..e5eaa1032 100644
Binary files a/public/apple-icon-precomposed.png and b/public/apple-icon-precomposed.png differ
diff --git a/public/apple-icon.png b/public/apple-icon.png
index c700e55e0..e5eaa1032 100644
Binary files a/public/apple-icon.png and b/public/apple-icon.png differ
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
index 24989ceb0..f96d7c968 100644
Binary files a/public/favicon-16x16.png and b/public/favicon-16x16.png differ
diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
index e5cb1e984..183f2d1d5 100644
Binary files a/public/favicon-32x32.png and b/public/favicon-32x32.png differ
diff --git a/public/favicon-512x512.png b/public/favicon-512x512.png
index c34c3753a..2d0007c8c 100644
Binary files a/public/favicon-512x512.png and b/public/favicon-512x512.png differ
diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png
index 5fc50e9fc..de2e82032 100644
Binary files a/public/favicon-96x96.png and b/public/favicon-96x96.png differ
diff --git a/public/favicon-badge-16x16.png b/public/favicon-badge-16x16.png
index 325f31785..f8cf72e02 100644
Binary files a/public/favicon-badge-16x16.png and b/public/favicon-badge-16x16.png differ
diff --git a/public/favicon-badge-32x32.png b/public/favicon-badge-32x32.png
index e68f6912f..8e1e11cb2 100644
Binary files a/public/favicon-badge-32x32.png and b/public/favicon-badge-32x32.png differ
diff --git a/public/favicon-badge-96x96.png b/public/favicon-badge-96x96.png
index 20ab1bde0..da6f99c50 100644
Binary files a/public/favicon-badge-96x96.png and b/public/favicon-badge-96x96.png differ
diff --git a/public/manifest.json b/public/manifest.json
index 78fcc4755..3644698a4 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -39,6 +39,6 @@
}],
"start_url": "/",
"display": "standalone",
- "background_color": "#1f93ff",
- "theme_color": "#1f93ff"
+ "background_color": "#2781F6",
+ "theme_color": "#2781F6"
}
diff --git a/public/ms-icon-144x144.png b/public/ms-icon-144x144.png
index 45c07cc11..a27e7f7b0 100644
Binary files a/public/ms-icon-144x144.png and b/public/ms-icon-144x144.png differ
diff --git a/public/ms-icon-150x150.png b/public/ms-icon-150x150.png
index 5d6194343..89dd0ed4a 100644
Binary files a/public/ms-icon-150x150.png and b/public/ms-icon-150x150.png differ
diff --git a/public/ms-icon-310x310.png b/public/ms-icon-310x310.png
index f0810d9ab..7174258ee 100644
Binary files a/public/ms-icon-310x310.png and b/public/ms-icon-310x310.png differ
diff --git a/public/ms-icon-70x70.png b/public/ms-icon-70x70.png
index 36382a499..4fb34350a 100644
Binary files a/public/ms-icon-70x70.png and b/public/ms-icon-70x70.png differ
diff --git a/spec/builders/agent_builder_spec.rb b/spec/builders/agent_builder_spec.rb
index f140f2f29..69cacb22b 100644
--- a/spec/builders/agent_builder_spec.rb
+++ b/spec/builders/agent_builder_spec.rb
@@ -23,6 +23,12 @@ RSpec.describe AgentBuilder, type: :model do
end
describe '#perform' do
+ it 'locks the account while checking and creating the agent' do
+ expect(account).to receive(:with_lock).and_call_original
+
+ agent_builder.perform
+ end
+
context 'when user does not exist' do
it 'creates a new user' do
expect { agent_builder.perform }.to change(User, :count).by(1)
@@ -67,5 +73,17 @@ RSpec.describe AgentBuilder, type: :model do
expect(user.encrypted_password).not_to be_empty
end
end
+
+ context 'when the account has reached its agent limit' do
+ before do
+ allow(account).to receive(:usage_limits).and_return({ agents: account.account_users.count })
+ end
+
+ it 'raises a limit exceeded error without creating a user' do
+ expect { agent_builder.perform }.to raise_error(described_class::LimitExceededError, described_class::LIMIT_EXCEEDED_MESSAGE)
+
+ expect(User.from_email(email)).to be_nil
+ end
+ end
end
end
diff --git a/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb b/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb
index a98f787e0..6e1b03bac 100644
--- a/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/agent_bots_controller_spec.rb
@@ -64,6 +64,14 @@ RSpec.describe 'Agent Bot API', type: :request do
expect(response).to have_http_status(:success)
expect(response.body).to include(agent_bot.access_token.token)
end
+
+ it 'supports API token authentication' do
+ get "/api/v1/accounts/#{account.id}/agent_bots",
+ headers: { api_access_token: admin.access_token.token },
+ as: :json
+
+ expect(response).to have_http_status(:success)
+ end
end
end
diff --git a/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb b/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb
index 5f512b2bd..8d28a2f2a 100644
--- a/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb
@@ -13,7 +13,9 @@ RSpec.describe 'Linear Integration API', type: :request do
end
describe 'DELETE /api/v1/accounts/:account_id/integrations/linear' do
- it 'deletes the linear integration' do
+ let(:admin) { create(:user, account: account, role: :administrator) }
+
+ it 'deletes the linear integration when the user is an administrator' do
# Stub the HTTP call to Linear's revoke endpoint
allow(HTTParty).to receive(:post).with(
'https://api.linear.app/oauth/revoke',
@@ -21,11 +23,19 @@ RSpec.describe 'Linear Integration API', type: :request do
).and_return(instance_double(HTTParty::Response, success?: true))
delete "/api/v1/accounts/#{account.id}/integrations/linear",
- headers: agent.create_new_auth_token,
+ headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:ok)
expect(account.hooks.count).to eq(0)
end
+
+ it 'returns unauthorized for an agent and keeps the integration' do
+ delete "/api/v1/accounts/#{account.id}/integrations/linear",
+ headers: agent.create_new_auth_token,
+ as: :json
+ expect(response).to have_http_status(:unauthorized)
+ expect(account.hooks.count).to eq(1)
+ end
end
describe 'GET /api/v1/accounts/:account_id/integrations/linear/teams' do
diff --git a/spec/controllers/api/v1/accounts/integrations/shopify_controller_spec.rb b/spec/controllers/api/v1/accounts/integrations/shopify_controller_spec.rb
index ef6c4d367..7f9a032ce 100644
--- a/spec/controllers/api/v1/accounts/integrations/shopify_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/integrations/shopify_controller_spec.rb
@@ -159,15 +159,17 @@ RSpec.describe 'Shopify Integration API', type: :request do
end
describe 'DELETE /api/v1/accounts/:account_id/integrations/shopify' do
+ let(:admin) { create(:user, account: account, role: :administrator) }
+
before do
create(:integrations_hook, :shopify, account: account)
end
- context 'when it is an authenticated user' do
+ context 'when it is an administrator' do
it 'deletes the shopify integration' do
expect do
delete "/api/v1/accounts/#{account.id}/integrations/shopify",
- headers: agent.create_new_auth_token,
+ headers: admin.create_new_auth_token,
as: :json
end.to change { account.hooks.count }.by(-1)
@@ -175,6 +177,18 @@ RSpec.describe 'Shopify Integration API', type: :request do
end
end
+ context 'when it is an agent' do
+ it 'returns unauthorized and keeps the integration' do
+ expect do
+ delete "/api/v1/accounts/#{account.id}/integrations/shopify",
+ headers: agent.create_new_auth_token,
+ as: :json
+ end.not_to(change { account.hooks.count })
+
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
delete "/api/v1/accounts/#{account.id}/integrations/shopify",
diff --git a/spec/enterprise/builders/captain/assistant_stats_builder_spec.rb b/spec/enterprise/builders/captain/assistant_stats_builder_spec.rb
index 6575c9856..c495244c4 100644
--- a/spec/enterprise/builders/captain/assistant_stats_builder_spec.rb
+++ b/spec/enterprise/builders/captain/assistant_stats_builder_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Captain::AssistantStatsBuilder do
expect(metrics.keys).to contain_exactly(
:conversations_handled, :auto_resolution_rate, :handoff_rate,
- :hours_saved, :reopen_rate, :conversation_depth, :knowledge
+ :hours_saved, :reopen_rate, :conversation_depth
)
expect(metrics[:conversations_handled]).to include(:current, :previous, :trend)
end
@@ -229,7 +229,7 @@ RSpec.describe Captain::AssistantStatsBuilder do
end
end
- describe '#metrics knowledge' do
+ describe '#faq_stats' do
before do
create_list(:captain_assistant_response, 3, assistant: assistant, account: account, status: :approved)
create(:captain_assistant_response, assistant: assistant, account: account, status: :pending)
@@ -237,7 +237,7 @@ RSpec.describe Captain::AssistantStatsBuilder do
end
it 'returns approved, pending, document counts and coverage' do
- knowledge = described_class.new(assistant, '30').metrics[:knowledge]
+ knowledge = described_class.new(assistant).faq_stats
expect(knowledge).to eq(approved: 3, pending: 1, documents: 2, coverage: 75)
end
@@ -245,7 +245,7 @@ RSpec.describe Captain::AssistantStatsBuilder do
it 'reports zero coverage when there are no responses' do
Captain::AssistantResponse.where(assistant: assistant).delete_all
- knowledge = described_class.new(assistant, '30').metrics[:knowledge]
+ knowledge = described_class.new(assistant).faq_stats
expect(knowledge[:coverage]).to eq(0)
end
diff --git a/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb
index e5a8a5b7d..270150979 100644
--- a/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb
+++ b/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb
@@ -21,6 +21,27 @@ RSpec.describe 'Agents API', type: :request do
expect(response).to have_http_status(:payment_required)
expect(response.body).to include('Account limit exceeded. Please purchase more licenses')
end
+
+ it 'prevents adding an agent if the last seat is consumed before creation' do
+ account.update!(limits: { agents: account.account_users.count + 1 })
+ competing_agent_created = false
+
+ allow(AgentBuilder).to receive(:new).and_wrap_original do |method, *args|
+ unless competing_agent_created
+ create(:user, account: account, role: :agent)
+ competing_agent_created = true
+ end
+
+ method.call(*args)
+ end
+
+ post "/api/v1/accounts/#{account.id}/agents", params: params, headers: admin.create_new_auth_token, as: :json
+
+ expect(response).to have_http_status(:payment_required)
+ expect(response.body).to include('Account limit exceeded. Please purchase more licenses')
+ expect(User.from_email(params[:email])).to be_nil
+ expect(account.account_users.count).to eq(account.usage_limits[:agents])
+ end
end
end
diff --git a/spec/enterprise/controllers/api/v1/accounts/captain/agent_sessions_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/captain/agent_sessions_controller_spec.rb
new file mode 100644
index 000000000..1444dc0a8
--- /dev/null
+++ b/spec/enterprise/controllers/api/v1/accounts/captain/agent_sessions_controller_spec.rb
@@ -0,0 +1,120 @@
+require 'rails_helper'
+
+RSpec.describe 'Api::V1::Accounts::Captain::AgentSessions', type: :request do
+ let(:account) { create(:account) }
+ let(:agent) { create(:user, account: account, role: :agent) }
+ let(:inbox) { create(:inbox, account: account) }
+ let(:conversation) { create(:conversation, account: account, inbox: inbox) }
+ let(:assistant) { create(:captain_assistant, account: account) }
+ let(:message) do
+ create(:message, account: account, conversation: conversation, message_type: :outgoing, sender: assistant)
+ end
+
+ before { create(:inbox_member, user: agent, inbox: inbox) }
+
+ def json_response
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ describe 'GET /api/v1/accounts/:account_id/captain/agent_sessions/:id' do
+ context 'when it is an unauthenticated user' do
+ it 'returns unauthorized' do
+ get "/api/v1/accounts/#{account.id}/captain/agent_sessions/#{message.id}", as: :json
+
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context 'when the message has an agent session' do
+ let(:document) { create(:captain_document, account: account, assistant: assistant) }
+ let(:documented_faq) do
+ create(:captain_assistant_response, account: account, assistant: assistant,
+ question: 'How do I reset my password?', documentable: document)
+ end
+ let(:plain_faq) do
+ create(:captain_assistant_response, account: account, assistant: assistant, question: 'How do I change my email?')
+ end
+ let(:pdf_document) do
+ create(:captain_document, account: account, assistant: assistant, external_link: nil,
+ pdf_file: Rack::Test::UploadedFile.new(Rails.root.join('spec/assets/sample.pdf'), 'application/pdf'))
+ end
+ let(:pdf_faq) do
+ create(:captain_assistant_response, account: account, assistant: assistant,
+ question: 'What are the pricing tiers?', documentable: pdf_document)
+ end
+ let(:scenario) { create(:captain_scenario, account: account, assistant: assistant, title: 'Refund flow') }
+ let(:run_context) do
+ [
+ { 'role' => 'user', 'content' => 'I want a refund' },
+ { 'role' => 'assistant', 'content' => '', 'agent_name' => 'Assistant',
+ 'tool_calls' => [{ 'id' => 'call_1', 'name' => 'faq_lookup', 'arguments' => { 'query' => 'refund' } }] },
+ { 'role' => 'tool', 'content' => 'Refunds take 5 days', 'tool_call_id' => 'call_1' },
+ { 'role' => 'assistant', 'content' => 'Refunds take 5 days', 'agent_name' => "scenario_#{scenario.id}_refund_flow" }
+ ]
+ end
+ let!(:agent_session) do
+ create(:captain_agent_session, account: account, assistant: assistant,
+ subject: conversation, result: message,
+ llm_model: 'openai-gpt-5.2', credits_consumed: 1.0,
+ faq_ids: [documented_faq.id, plain_faq.id, pdf_faq.id, documented_faq.id + 100_000],
+ scenario_ids: [scenario.id],
+ run_context: run_context)
+ end
+
+ it 'returns the session with hydrated citations and scenarios' do
+ get "/api/v1/accounts/#{account.id}/captain/agent_sessions/#{message.id}",
+ headers: agent.create_new_auth_token, as: :json
+
+ expect(response).to have_http_status(:success)
+ aggregate_failures do
+ expect(json_response[:id]).to eq(agent_session.id)
+ expect(json_response[:message_id]).to eq(message.id)
+ expect(json_response[:llm_model]).to eq('openai-gpt-5.2')
+ expect(json_response[:credits_consumed]).to eq(1.0)
+ expect(json_response[:run_context].length).to eq(4)
+ expect(json_response[:run_context].second[:tool_calls].first[:arguments][:query]).to eq('refund')
+
+ citations = json_response[:citations].index_by { |citation| citation[:id] }
+ expect(citations.keys).to contain_exactly(documented_faq.id, plain_faq.id, pdf_faq.id)
+ expect(citations[documented_faq.id][:title]).to eq('How do I reset my password?')
+ expect(citations[documented_faq.id][:link]).to eq(document.external_link)
+ expect(citations[plain_faq.id][:link]).to be_nil
+ expect(pdf_document.external_link).to start_with('PDF:')
+ expect(citations[pdf_faq.id][:link]).to eq(pdf_document.display_url)
+ expect(citations[pdf_faq.id][:link]).to match(%r{\Ahttps?://})
+
+ expect(json_response[:scenarios]).to eq([{ id: scenario.id, title: 'Refund flow' }])
+ end
+ end
+
+ it 'does not allow an agent without access to the conversation' do
+ other_agent = create(:user, account: account, role: :agent)
+
+ get "/api/v1/accounts/#{account.id}/captain/agent_sessions/#{message.id}",
+ headers: other_agent.create_new_auth_token, as: :json
+
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context 'when the message has no agent session' do
+ it 'returns not found' do
+ get "/api/v1/accounts/#{account.id}/captain/agent_sessions/#{message.id}",
+ headers: agent.create_new_auth_token, as: :json
+
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'when the message does not belong to the account' do
+ it 'returns not found' do
+ other_message = create(:message)
+
+ get "/api/v1/accounts/#{account.id}/captain/agent_sessions/#{other_message.id}",
+ headers: agent.create_new_auth_token, as: :json
+
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb
index afb6aa2de..c43924fc4 100644
--- a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb
+++ b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb
@@ -257,10 +257,20 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do
let(:alice) { create(:user, account: account, role: :administrator, name: 'Alice Adams') }
let(:bob) { create(:user, account: account, role: :administrator, name: 'Bob Brown') }
let(:summary_service) { instance_double(Captain::OverviewSummaryService) }
+ let(:summary_stats) do
+ {
+ conversations_handled: { current: 42 },
+ hours_saved: { current: 12 },
+ auto_resolution_rate: { current: 65.0, trend: 5.0 },
+ handoff_rate: { current: 20.0, trend: -2.0 },
+ reopen_rate: { current: 5.0, trend: -1.0 },
+ knowledge: { coverage: 80, approved: 8, documents: 3 }
+ }
+ end
def get_summary(user)
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/summary",
- params: { range: '30' },
+ params: { range: '30', stats: summary_stats },
headers: user.create_new_auth_token,
as: :json
end
@@ -273,6 +283,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do
it 'caches the summary per viewer so one user never receives another user\'s greeting' do
allow(summary_service).to receive(:perform).and_return({ message: 'Hi Alice' })
+ expect(Captain::AssistantStatsBuilder).not_to receive(:new)
get_summary(alice)
get_summary(alice) # served from Alice's cache, no regeneration
@@ -280,6 +291,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do
expect(response).to have_http_status(:success)
expect(Captain::OverviewSummaryService).to have_received(:new).twice
+ expect(Captain::OverviewSummaryService).to have_received(:new).with(hash_including(stats: summary_stats)).twice
end
it 'does not cache failures so a transient error is retried' do
diff --git a/spec/enterprise/controllers/twilio/voice_controller_spec.rb b/spec/enterprise/controllers/twilio/voice_controller_spec.rb
index 79fdd67a8..0f537af20 100644
--- a/spec/enterprise/controllers/twilio/voice_controller_spec.rb
+++ b/spec/enterprise/controllers/twilio/voice_controller_spec.rb
@@ -33,8 +33,8 @@ RSpec.describe 'Twilio::VoiceController', type: :request do
expect(Voice::InboundCallBuilder).to receive(:perform!).with(
inbox: inbox,
- from_number: from_number,
- call_sid: call_sid
+ call_sid: call_sid,
+ caller: { source_ids: [from_number], contact_attributes: { name: from_number, phone_number: from_number } }
).and_return(call)
post "/twilio/voice/call/#{digits}", params: {
diff --git a/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb b/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
index eb1cb641c..08bb2a50d 100644
--- a/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
+++ b/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
@@ -561,6 +561,22 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
expect(account.reload.usage_limits[:captain][:responses][:consumed]).to eq(0)
end
+ it 'attributes the handoff session to the private reason note when the tool recorded one' do
+ handoff_note = create(:message, conversation: conversation, account: account, message_type: :outgoing,
+ private: true, sender: assistant, content: 'Needs a human')
+ run_context[:state][:cw_metadata][:handoff_note_id] = handoff_note.id
+ allow(mock_agent_runner_service).to receive(:generate_response) do
+ conversation.update!(status: :open)
+ { 'response' => 'Let me connect you', 'handoff_tool_called' => true }
+ end
+
+ described_class.perform_now(conversation, assistant)
+
+ session = Captain::AgentSession.last
+ expect(session.credits_consumed).to eq(0.0)
+ expect(session.result_id).to eq(handoff_note.id)
+ end
+
it 'creates a zero-credit session when the handoff tool fired but failed to commit' do
allow(mock_agent_runner_service).to receive(:generate_response).and_return({
'response' => 'I tried to hand off',
diff --git a/spec/enterprise/lib/captain/tools/handoff_tool_spec.rb b/spec/enterprise/lib/captain/tools/handoff_tool_spec.rb
index 492d24f32..db5ee462c 100644
--- a/spec/enterprise/lib/captain/tools/handoff_tool_spec.rb
+++ b/spec/enterprise/lib/captain/tools/handoff_tool_spec.rb
@@ -86,6 +86,12 @@ RSpec.describe Captain::Tools::HandoffTool, type: :model do
tool.perform(tool_context, reason: reason)
end
+
+ it 'records the handoff note id in the run state for session capture' do
+ tool.perform(tool_context, reason: 'Customer needs specialized support')
+
+ expect(tool_context.state[:cw_metadata][:handoff_note_id]).to eq(Message.last.id)
+ end
end
context 'without reason provided' do
@@ -107,6 +113,12 @@ RSpec.describe Captain::Tools::HandoffTool, type: :model do
tool.perform(tool_context)
end
+
+ it 'does not record a handoff note id since the empty note never renders' do
+ tool.perform(tool_context)
+
+ expect(tool_context.state[:cw_metadata]).to be_nil
+ end
end
context 'when handoff fails' do
diff --git a/spec/enterprise/policies/captain/assistant_policy_spec.rb b/spec/enterprise/policies/captain/assistant_policy_spec.rb
index e04b680e4..b53d73a5e 100644
--- a/spec/enterprise/policies/captain/assistant_policy_spec.rb
+++ b/spec/enterprise/policies/captain/assistant_policy_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Captain::AssistantPolicy, type: :policy do
let(:administrator_context) { { user: administrator, account: account, account_user: account.account_users.first } }
let(:agent_context) { { user: agent, account: account, account_user: account.account_users.first } }
- permissions :index?, :show?, :playground? do
+ permissions :index?, :show?, :playground?, :metrics?, :faq_stats? do
context 'when administrator' do
it { expect(assistant_policy).to permit(administrator_context, assistant) }
end
diff --git a/spec/enterprise/services/captain/assistant/session_capture_service_spec.rb b/spec/enterprise/services/captain/assistant/session_capture_service_spec.rb
index ef25b1e2b..daf38c8d6 100644
--- a/spec/enterprise/services/captain/assistant/session_capture_service_spec.rb
+++ b/spec/enterprise/services/captain/assistant/session_capture_service_spec.rb
@@ -111,6 +111,25 @@ RSpec.describe Captain::Assistant::SessionCaptureService do
expect(history.first).to include('role' => 'user', 'content' => 'CUST001')
end
+ it 'stores multimodal content without cached attachment bytes' do
+ content = RubyLLM::Content.new('See image', ['https://example.com/image.jpg'])
+ content.attachments.first.instance_variable_set(:@content, "\xFF\xD8\xFF\xE0JFIF".b)
+ run_context[:conversation_history] = [
+ { role: :user, content: content },
+ { role: :assistant, content: 'I can see the image', agent_name: 'Assistant' }
+ ]
+
+ history = service.capture!.run_context
+
+ expect(history.first).to include(
+ 'role' => 'user',
+ 'content' => {
+ 'text' => 'See image',
+ 'attachments' => [{ 'type' => 'image', 'source' => 'https://example.com/image.jpg' }]
+ }
+ )
+ end
+
it 'stores the full history when it contains no user message' do
run_context[:conversation_history] = conversation_history.reject { |message| message[:role] == :user }
diff --git a/spec/enterprise/services/voice/inbound_call_builder_spec.rb b/spec/enterprise/services/voice/inbound_call_builder_spec.rb
index e36c9a1b7..c8c6b978e 100644
--- a/spec/enterprise/services/voice/inbound_call_builder_spec.rb
+++ b/spec/enterprise/services/voice/inbound_call_builder_spec.rb
@@ -17,8 +17,8 @@ RSpec.describe Voice::InboundCallBuilder do
def perform_builder
described_class.perform!(
inbox: inbox,
- from_number: from_number,
- call_sid: call_sid
+ call_sid: call_sid,
+ caller: { source_ids: [from_number], contact_attributes: { name: from_number, phone_number: from_number } }
)
end
@@ -100,26 +100,29 @@ RSpec.describe Voice::InboundCallBuilder do
end
end
- context 'when the WhatsApp wa_id needs Brazil normalization to match an existing ContactInbox' do
+ context 'when a WhatsApp call shares a BSUID with an existing ContactInbox' do
let(:whatsapp_channel) do
create(:channel_whatsapp, account: account, provider: 'whatsapp_cloud',
provider_config: { 'phone_number_id' => '123', 'source' => 'embedded_signup', 'calling_enabled' => true },
validate_provider_config: false, sync_templates: false)
end
let(:whatsapp_inbox) { whatsapp_channel.inbox }
- let!(:stored_contact) { create(:contact, account: account, phone_number: '+5541988887777') }
+ let!(:stored_contact) { create(:contact, account: account) }
let!(:stored_contact_inbox) do
- create(:contact_inbox, contact: stored_contact, inbox: whatsapp_inbox, source_id: '5541988887777')
+ create(:contact_inbox, contact: stored_contact, inbox: whatsapp_inbox, source_id: 'IN.2081978709342942')
end
before { account.enable_features!('channel_voice') }
- it 'reuses the contact via normalized wa_id rather than forking a new ContactInbox' do
+ # Closes the gap: the contact was keyed by BSUID, but the call also carries a phone.
+ # Matching across every source_id reuses the contact instead of forking on the phone.
+ it 'reuses the contact by matching any source_id, not just the first' do
call = described_class.perform!(
inbox: whatsapp_inbox,
- from_number: '+554188887777',
- call_sid: 'wacall_br_1',
- provider: :whatsapp
+ call_sid: 'wacall_bsuid_1',
+ provider: :whatsapp,
+ caller: { source_ids: ['5541988887777', 'IN.2081978709342942'],
+ contact_attributes: { name: 'Ada Lovelace', phone_number: '+5541988887777' } }
)
expect(call.contact).to eq(stored_contact)
diff --git a/spec/enterprise/services/whatsapp/incoming_call_service_spec.rb b/spec/enterprise/services/whatsapp/incoming_call_service_spec.rb
index a3c5246d2..cf031f1ca 100644
--- a/spec/enterprise/services/whatsapp/incoming_call_service_spec.rb
+++ b/spec/enterprise/services/whatsapp/incoming_call_service_spec.rb
@@ -74,6 +74,120 @@ describe Whatsapp::IncomingCallService do
end
end
+ describe 'inbound connect from a username (BSUID) caller' do
+ let(:sdp_offer) { "v=0\r\n...sdp..." }
+ let(:bsuid) { 'IN.2081978709342942' }
+ let!(:agent) { create(:user, account: account) }
+
+ before { create(:inbox_member, inbox: inbox, user: agent) }
+
+ it 'keys a phone caller by the phone (matching messaging) even when a BSUID is also present' do
+ allow(ActionCable.server).to receive(:broadcast)
+
+ params = {
+ calls: [{ id: provider_call_id, from: from_number, from_user_id: bsuid, event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ wa_id: from_number, user_id: bsuid, profile: { name: 'Ada Lovelace' } }]
+ }
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1).and change(Conversation, :count).by(1)
+
+ contact_inbox = Call.last.conversation.contact_inbox
+ expect(contact_inbox.source_id).to eq(from_number)
+ expect(contact_inbox.contact.name).to eq('Ada Lovelace')
+ end
+
+ it 'keys a username-only caller by the BSUID when no phone `from` is present' do
+ allow(ActionCable.server).to receive(:broadcast)
+
+ params = {
+ calls: [{ id: provider_call_id, from_user_id: bsuid, event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ user_id: bsuid, profile: { name: 'Ada Lovelace' } }]
+ }
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1)
+
+ contact_inbox = Call.last.conversation.contact_inbox
+ expect(contact_inbox.source_id).to eq(bsuid)
+ expect(contact_inbox.contact.name).to eq('Ada Lovelace')
+ end
+
+ it 'reuses the phone-keyed ContactInbox messaging created for a phone caller and backfills the BSUID alias' do
+ allow(ActionCable.server).to receive(:broadcast)
+ contact = create(:contact, account: account)
+ existing = create(:contact_inbox, inbox: inbox, contact: contact, source_id: from_number)
+
+ params = {
+ calls: [{ id: provider_call_id, from: from_number, from_user_id: bsuid, event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ wa_id: from_number, user_id: bsuid }]
+ }
+ # The conversation reuses the existing phone thread; the BSUID alias is backfilled onto the same contact.
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1).and change(ContactInbox, :count).by(1)
+
+ expect(Call.last.contact).to eq(contact)
+ expect(Call.last.conversation.contact_inbox).to eq(existing)
+ expect(inbox.contact_inboxes.find_by(source_id: bsuid).contact).to eq(contact)
+ end
+
+ it 'reuses a phone ContactInbox via the same wa_id normalization messaging uses' do
+ allow(ActionCable.server).to receive(:broadcast)
+ contact = create(:contact, account: account, phone_number: '+5541988887777')
+ existing = create(:contact_inbox, inbox: inbox, contact: contact, source_id: '5541988887777')
+
+ params = {
+ calls: [{ id: provider_call_id, from: '554188887777', event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ wa_id: '554188887777' }]
+ }
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1).and not_change(ContactInbox, :count)
+
+ expect(Call.last.conversation.contact_inbox).to eq(existing)
+ end
+
+ it 'reuses the BSUID-keyed ContactInbox messaging created for a username-only caller' do
+ allow(ActionCable.server).to receive(:broadcast)
+ contact = create(:contact, account: account)
+ existing = create(:contact_inbox, inbox: inbox, contact: contact, source_id: bsuid)
+
+ params = {
+ calls: [{ id: provider_call_id, from_user_id: bsuid, event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ user_id: bsuid }]
+ }
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1).and not_change(ContactInbox, :count)
+
+ expect(Call.last.contact).to eq(contact)
+ expect(Call.last.conversation.contact_inbox).to eq(existing)
+ end
+
+ # The gap: messaging created the contact username-only (BSUID-keyed), and the call now
+ # also exposes a phone. Matching across every source_id reuses the BSUID thread instead
+ # of forking a new phone-keyed contact.
+ it 'reuses a BSUID-keyed ContactInbox even when the call also carries a phone and backfills the phone alias' do
+ allow(ActionCable.server).to receive(:broadcast)
+ contact = create(:contact, account: account)
+ existing = create(:contact_inbox, inbox: inbox, contact: contact, source_id: bsuid)
+
+ params = {
+ calls: [{ id: provider_call_id, from: from_number, from_user_id: bsuid, event: 'connect',
+ session: { sdp: sdp_offer, sdp_type: 'offer' } }],
+ contacts: [{ wa_id: from_number, user_id: bsuid }]
+ }
+ # The conversation reuses the existing BSUID thread; the phone alias is backfilled onto the same contact.
+ expect { described_class.new(inbox: inbox, params: params).perform }
+ .to change(Call, :count).by(1).and change(ContactInbox, :count).by(1)
+
+ expect(Call.last.contact).to eq(contact)
+ expect(Call.last.conversation.contact_inbox).to eq(existing)
+ expect(inbox.contact_inboxes.find_by(source_id: from_number).contact).to eq(contact)
+ end
+ end
+
describe 'outbound connect (existing call)' do
let!(:call) do
conversation = create(:conversation, account: account, inbox: inbox)
diff --git a/spec/jobs/webhooks/whatsapp_events_job_spec.rb b/spec/jobs/webhooks/whatsapp_events_job_spec.rb
index 8d1b24b52..8310839da 100644
--- a/spec/jobs/webhooks/whatsapp_events_job_spec.rb
+++ b/spec/jobs/webhooks/whatsapp_events_job_spec.rb
@@ -345,6 +345,94 @@ RSpec.describe Webhooks::WhatsappEventsJob do
end.not_to change(Conversation, :count)
end
+ it 'finds channel using normalized Brazil phone number when display_phone_number is missing the 9 digit' do
+ brazil_channel = create(:channel_whatsapp, phone_number: '+5541999887766', provider: 'whatsapp_cloud',
+ sync_templates: false, validate_provider_config: false)
+ wb_params = {
+ object: 'whatsapp_business_account',
+ entry: [{
+ changes: [{
+ value: {
+ metadata: {
+ phone_number_id: brazil_channel.provider_config['phone_number_id'],
+ display_phone_number: '554199887766'
+ }
+ }
+ }]
+ }]
+ }
+ allow(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).and_return(process_service)
+ expect(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).with(inbox: brazil_channel.inbox, params: wb_params)
+ job.perform_now(wb_params)
+ end
+
+ it 'finds channel using normalized Argentina phone number when display_phone_number has extra 9 digit' do
+ argentina_channel = create(:channel_whatsapp, phone_number: '+541112345678', provider: 'whatsapp_cloud',
+ sync_templates: false, validate_provider_config: false)
+ wb_params = {
+ object: 'whatsapp_business_account',
+ entry: [{
+ changes: [{
+ value: {
+ metadata: {
+ phone_number_id: argentina_channel.provider_config['phone_number_id'],
+ display_phone_number: '5491112345678'
+ }
+ }
+ }]
+ }]
+ }
+ allow(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).and_return(process_service)
+ expect(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).with(inbox: argentina_channel.inbox, params: wb_params)
+ job.perform_now(wb_params)
+ end
+
+ it 'finds channel when display_phone_number contains formatting characters' do
+ formatted_channel = create(:channel_whatsapp, phone_number: '+14155552671', provider: 'whatsapp_cloud',
+ sync_templates: false, validate_provider_config: false)
+ wb_params = {
+ object: 'whatsapp_business_account',
+ entry: [{
+ changes: [{
+ value: {
+ metadata: {
+ phone_number_id: formatted_channel.provider_config['phone_number_id'],
+ display_phone_number: '+1 415-555-2671'
+ }
+ }
+ }]
+ }]
+ }
+ allow(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).and_return(process_service)
+ expect(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).with(inbox: formatted_channel.inbox, params: wb_params)
+ job.perform_now(wb_params)
+ end
+
+ it 'prefers the phone_number_id match when a raw display_phone_number collision exists' do
+ normalized_channel = create(:channel_whatsapp, phone_number: '+5541999887766', provider: 'whatsapp_cloud',
+ sync_templates: false, validate_provider_config: false)
+ create(:channel_whatsapp, phone_number: '+554199887766', provider: 'whatsapp_cloud',
+ sync_templates: false, validate_provider_config: false).tap do |raw_channel|
+ raw_channel.update!(provider_config: raw_channel.provider_config.merge('phone_number_id' => 'other-id'))
+ end
+ wb_params = {
+ object: 'whatsapp_business_account',
+ entry: [{
+ changes: [{
+ value: {
+ metadata: {
+ phone_number_id: normalized_channel.provider_config['phone_number_id'],
+ display_phone_number: '554199887766'
+ }
+ }
+ }]
+ }]
+ }
+ allow(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).and_return(process_service)
+ expect(Whatsapp::IncomingMessageWhatsappCloudService).to receive(:new).with(inbox: normalized_channel.inbox, params: wb_params)
+ job.perform_now(wb_params)
+ end
+
it 'will not enque Whatsapp::IncomingMessageWhatsappCloudService when invalid phone number id' do
other_channel = create(:channel_whatsapp, phone_number: '+1987654', provider: 'whatsapp_cloud', sync_templates: false,
validate_provider_config: false)
diff --git a/spec/services/whatsapp/incoming_message_service_spec.rb b/spec/services/whatsapp/incoming_message_service_spec.rb
index 430aa1561..01b569cb9 100644
--- a/spec/services/whatsapp/incoming_message_service_spec.rb
+++ b/spec/services/whatsapp/incoming_message_service_spec.rb
@@ -34,8 +34,8 @@ describe Whatsapp::IncomingMessageService do
it 'appends to last conversation when if conversation already exists' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
- 2.times.each { create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox) }
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ 2.times.each { create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact) }
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(3)
@@ -46,7 +46,7 @@ describe Whatsapp::IncomingMessageService do
it 'reopen last conversation if last conversation is resolved and lock to single conversation is enabled' do
whatsapp_channel.inbox.update(lock_to_single_conversation: true)
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
last_conversation.update(status: 'resolved')
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
@@ -59,7 +59,7 @@ describe Whatsapp::IncomingMessageService do
it 'creates a new conversation if last conversation is resolved and lock to single conversation is disabled' do
whatsapp_channel.inbox.update(lock_to_single_conversation: false)
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
last_conversation.update(status: 'resolved')
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# new conversation should be created
@@ -70,7 +70,7 @@ describe Whatsapp::IncomingMessageService do
it 'will not create a new conversation if last conversation is not resolved and lock to single conversation is disabled' do
whatsapp_channel.inbox.update(lock_to_single_conversation: false)
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
last_conversation.update(status: Conversation.statuses.except('resolved').keys.sample)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# new conversation should be created
@@ -238,7 +238,7 @@ describe Whatsapp::IncomingMessageService do
end
before do
- create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
end
@@ -453,7 +453,7 @@ describe Whatsapp::IncomingMessageService do
it 'appends to existing contact if contact inbox exists' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
@@ -468,7 +468,7 @@ describe Whatsapp::IncomingMessageService do
context 'when a contact inbox exists in the old format without 9 included' do
it 'appends to existing contact' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
@@ -480,7 +480,7 @@ describe Whatsapp::IncomingMessageService do
context 'when a contact inbox exists in the new format with 9 included' do
it 'appends to existing contact' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: '5541988887777')
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
@@ -515,7 +515,7 @@ describe Whatsapp::IncomingMessageService do
# Normalized format removes the 9 after country code
normalized_wa_id = '541123456789'
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: normalized_wa_id)
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
@@ -532,7 +532,7 @@ describe Whatsapp::IncomingMessageService do
context 'when a contact inbox exists with the same format' do
it 'appends to existing contact' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
- last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
+ last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox, contact: contact_inbox.contact)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
diff --git a/spec/services/whatsapp/send_on_whatsapp_service_spec.rb b/spec/services/whatsapp/send_on_whatsapp_service_spec.rb
index c27295b3e..850685718 100644
--- a/spec/services/whatsapp/send_on_whatsapp_service_spec.rb
+++ b/spec/services/whatsapp/send_on_whatsapp_service_spec.rb
@@ -72,6 +72,21 @@ describe Whatsapp::SendOnWhatsappService do
expect(message.reload.source_id).to eq('123456789')
end
+ it 'fails a free-form message without contacting the provider when outside the 24 hour limit' do
+ create(:message, message_type: :incoming, content: 'test', created_at: 25.hours.ago,
+ conversation: conversation, account: conversation.account)
+ message = create(:message, message_type: :outgoing, content: 'test',
+ conversation: conversation, account: conversation.account)
+
+ expect(Whatsapp::TemplateProcessorService).not_to receive(:new)
+
+ described_class.new(message: message).perform
+
+ expect(message.reload.status).to eq('failed')
+ expect(message.external_error).to eq(I18n.t('errors.whatsapp.message_outside_messaging_window'))
+ expect(a_request(:post, 'https://waba.360dialog.io/v1/messages')).not_to have_been_made
+ end
+
it 'marks message as failed when template name is blank' do
processor = instance_double(Whatsapp::TemplateProcessorService)
allow(Whatsapp::TemplateProcessorService).to receive(:new).and_return(processor)