Show translation diagnostics in admin
This commit is contained in:
@@ -163,6 +163,7 @@ function initDb() {
|
||||
translated_body TEXT,
|
||||
translated_language TEXT,
|
||||
translation_status TEXT,
|
||||
translation_error TEXT,
|
||||
body TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
@@ -227,6 +228,7 @@ function initDb() {
|
||||
ensureColumn("messages", "translated_body", "TEXT");
|
||||
ensureColumn("messages", "translated_language", "TEXT");
|
||||
ensureColumn("messages", "translation_status", "TEXT");
|
||||
ensureColumn("messages", "translation_error", "TEXT");
|
||||
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_client_id ON messages(conversation_id, client_message_id) WHERE client_message_id IS NOT NULL");
|
||||
}
|
||||
|
||||
@@ -776,17 +778,17 @@ function normalizeClientMessageId(value) {
|
||||
|
||||
async function translateStoredMessage(conversationId, messageId, senderType, body) {
|
||||
const message = db.prepare("SELECT * FROM messages WHERE id = ? AND conversation_id = ?").get(messageId, conversationId);
|
||||
if (!message || !message.body.trim()) return markMessageTranslation(messageId, null, null, null, "skipped");
|
||||
if (!message || !message.body.trim()) return markMessageTranslation(messageId, null, null, null, "skipped", null);
|
||||
|
||||
const conversation = findConversationById(conversationId);
|
||||
const settings = getTranslationSettings();
|
||||
if (!settings.enabled) return markMessageTranslation(messageId, null, null, null, "disabled");
|
||||
if (!settings.openaiApiKey) return markMessageTranslation(messageId, null, null, null, "missing_key");
|
||||
if (!settings.enabled) return markMessageTranslation(messageId, null, null, null, "disabled", null);
|
||||
if (!settings.openaiApiKey) return markMessageTranslation(messageId, null, null, null, "missing_key", null);
|
||||
|
||||
const targetLanguage = senderType === "visitor"
|
||||
? settings.operatorLanguage
|
||||
: normalizeLanguage(conversation.customer_language || conversation.language || body.language || settings.operatorLanguage);
|
||||
if (!targetLanguage) return markMessageTranslation(messageId, null, null, null, "skipped");
|
||||
if (!targetLanguage) return markMessageTranslation(messageId, null, null, null, "skipped", null);
|
||||
|
||||
try {
|
||||
const result = await translateText(message.body, targetLanguage, settings.model, settings.openaiApiKey);
|
||||
@@ -800,24 +802,25 @@ async function translateStoredMessage(conversationId, messageId, senderType, bod
|
||||
}
|
||||
|
||||
if (!translatedText || sameLanguage) {
|
||||
return markMessageTranslation(messageId, sourceLanguage, null, translatedLanguage, sameLanguage ? "same_language" : "empty");
|
||||
return markMessageTranslation(messageId, sourceLanguage, null, translatedLanguage, sameLanguage ? "same_language" : "empty", null);
|
||||
}
|
||||
markMessageTranslation(messageId, sourceLanguage, translatedText, translatedLanguage, "translated");
|
||||
markMessageTranslation(messageId, sourceLanguage, translatedText, translatedLanguage, "translated", null);
|
||||
} catch (error) {
|
||||
console.error("translation_failed", error.message);
|
||||
markMessageTranslation(messageId, null, null, targetLanguage, "failed");
|
||||
markMessageTranslation(messageId, null, null, targetLanguage, "failed", error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function markMessageTranslation(messageId, sourceLanguage, translatedBody, translatedLanguage, status) {
|
||||
function markMessageTranslation(messageId, sourceLanguage, translatedBody, translatedLanguage, status, error) {
|
||||
db.prepare(`
|
||||
UPDATE messages
|
||||
SET original_language = ?,
|
||||
translated_body = ?,
|
||||
translated_language = ?,
|
||||
translation_status = ?
|
||||
translation_status = ?,
|
||||
translation_error = ?
|
||||
WHERE id = ?
|
||||
`).run(sourceLanguage, translatedBody, translatedLanguage, status, messageId);
|
||||
`).run(sourceLanguage, translatedBody, translatedLanguage, status, truncateText(error, 500), messageId);
|
||||
}
|
||||
|
||||
async function translateText(text, targetLanguage, model, apiKey) {
|
||||
@@ -948,6 +951,13 @@ function normalizeLanguage(value) {
|
||||
return text.split("-")[0].slice(0, 8);
|
||||
}
|
||||
|
||||
function truncateText(value, maxLength) {
|
||||
const text = String(value || "").trim();
|
||||
if (!text) return null;
|
||||
if (text.length <= maxLength) return text;
|
||||
return `${text.slice(0, maxLength - 3)}...`;
|
||||
}
|
||||
|
||||
function saveAttachments(conversationId, messageId, attachments) {
|
||||
for (const attachment of attachments.slice(0, 3)) {
|
||||
if (!attachment.dataBase64 || !attachment.name) continue;
|
||||
@@ -1072,6 +1082,7 @@ function conversationDetails(conversation) {
|
||||
translatedBody: message.translated_body,
|
||||
translatedLanguage: message.translated_language,
|
||||
translationStatus: message.translation_status,
|
||||
translationError: message.translation_error,
|
||||
createdAt: message.created_at,
|
||||
attachments: attachments
|
||||
.filter((item) => item.message_id === message.id)
|
||||
|
||||
Reference in New Issue
Block a user