diff --git a/src/token_estimator.js b/src/token_estimator.js index bd5f176..4019402 100644 --- a/src/token_estimator.js +++ b/src/token_estimator.js @@ -169,11 +169,11 @@ export class SimpleBPETokenizer { // Check token type and split if needed if (this.isWord(trimmed)) { return this.splitWord(trimmed); - } else if (this.isNumber(trimmed)) { - return this.splitNumber(trimmed); - } else { - return [token]; // Punctuation, symbols, etc. } + if (this.isNumber(trimmed)) { + return this.splitNumber(trimmed); + } + return [token]; // Punctuation, symbols, etc. } isWord(token) { @@ -210,12 +210,11 @@ export class SimpleBPETokenizer { if (remaining.length <= 4) { tokens.push(remaining); break; - } else { - // Take first 3-4 characters - const chunkSize = Math.min(4, Math.ceil(remaining.length / 2)); - tokens.push(remaining.substring(0, chunkSize)); - remaining = remaining.substring(chunkSize); } + // Take first 3-4 characters + const chunkSize = Math.min(4, Math.ceil(remaining.length / 2)); + tokens.push(remaining.substring(0, chunkSize)); + remaining = remaining.substring(chunkSize); } } diff --git a/src/translation.js b/src/translation.js index 5755751..d2b4f65 100644 --- a/src/translation.js +++ b/src/translation.js @@ -245,7 +245,7 @@ export async function translateText(text, targetLanguage) { console.log(`Input tokens: ${tokenInfo.totalTokens}`); console.log(`Text length: ${tokenInfo.textLength} characters`); console.log(`Estimated processing time: ${estimatedSeconds} seconds`); - console.log(`Token breakdown:`, tokenInfo.breakdown); + console.log("Token breakdown:", tokenInfo.breakdown); const { preservedText, preservations } = preserveSpecialContent(text); diff --git a/src/ui.js b/src/ui.js index 28bffd8..eaec88d 100644 --- a/src/ui.js +++ b/src/ui.js @@ -76,10 +76,9 @@ async function detectPageLanguage() { if (/^[a-z]{2,3}$/.test(detectedLang)) { console.log("AI detected language:", detectedLang); return detectedLang; - } else { - console.warn("Invalid language code from AI:", detectedLang); - return fallbackLanguageDetection(); } + console.warn("Invalid language code from AI:", detectedLang); + return fallbackLanguageDetection(); } catch (error) { console.warn("Language detection error:", error); return fallbackLanguageDetection(); @@ -126,6 +125,8 @@ const UI_TRANSLATIONS = { refreshModels: "🔄 Refresh Models", clearChat: "🗑️ Clear Chat", fullChatRaw: "📋 Full Chat Raw", + fullChatHTML: "📄 Full Chat HTML", + fullPageRaw: "📝 Full Page Raw", downloadChat: "💾 Download Chat", // Chat UI @@ -133,21 +134,51 @@ const UI_TRANSLATIONS = { typePlaceholder: "Type your message...", clearChatConfirm: "Clear all conversation history?", + // Modal headers + aiAssistantTitle: "AI Assistant", + ttsModalTitle: "Text-to-Speech", + translateModalTitle: "Translate Page", + // System messages pageContentPrefix: "Here's the content of the webpage:", additionalContext: "You are embedded on this page. When answering questions, consider the page content and context.", - // Notifications + // Notifications and alerts languageChanged: "Language set to {lang}. Refresh the page to see all interface elements in your preferred language.", translationFailed: "Translation failed: {error}", ttsFailed: "TTS failed: {error}", + fullChatCopied: "Full chat copied as raw markdown!", + fullChatHTMLCopied: "Full chat copied as HTML!", + fullPageCopied: "Full page copied as markdown!", + failedToCopy: "Failed to copy: {error}", + failedToCopyPage: "Failed to copy page: {error}", + failedToCopyCode: "Failed to copy code: {error}", + errorOpeningModal: "Error opening AI modal: {error}", + failedToReadPage: "Failed to read page: {error}", + languageDetectionFailed: "Language detection failed: {error}", // Dropdown labels currentPage: "Current page: {lang}", translatingTo: "Translating...", detectingLanguage: "🔍 Detecting...", + + // Intro/header text + hermesIntro: + 'presents nous research\'s hermes large language model', + discussingPage: "You are discussing", + + // TTS placeholder + ttsPlaceholder: + "text-to-speech: write any message & have the artificial intelligence speak it!", + translatePlaceholder: "Enter any text to translate...", + + // More alerts and messages + pleaseEnterText: "Please enter some text first!", + pleaseSelectFile: "Please select a file first!", + pleaseEnterTranslateText: "Please enter some text to translate!", + aiModalNotAvailable: "AI modal not available in this context", }, // Chinese (Simplified) @@ -164,19 +195,42 @@ const UI_TRANSLATIONS = { refreshModels: "🔄 刷新模型", clearChat: "🗑️ 清除聊天", fullChatRaw: "📋 完整聊天记录", + fullChatHTML: "📄 完整聊天HTML", + fullPageRaw: "📝 完整页面原始", downloadChat: "💾 下载聊天", sendButton: "发送", typePlaceholder: "输入您的消息...", clearChatConfirm: "清除所有对话历史记录?", + aiAssistantTitle: "AI助手", + ttsModalTitle: "文本转语音", + translateModalTitle: "翻译页面", pageContentPrefix: "以下是网页内容:", additionalContext: "您已嵌入此页面。回答问题时,请考虑页面内容和上下文。", languageChanged: "语言设置为 {lang}。刷新页面以查看所有界面元素的首选语言。", translationFailed: "翻译失败:{error}", ttsFailed: "语音合成失败:{error}", + fullChatCopied: "完整聊天记录已复制为markdown!", + fullChatHTMLCopied: "完整聊天记录已复制为HTML!", + fullPageCopied: "完整页面已复制为markdown!", + failedToCopy: "复制失败:{error}", + failedToCopyPage: "复制页面失败:{error}", + failedToCopyCode: "复制代码失败:{error}", + errorOpeningModal: "打开AI模态框时出错:{error}", + failedToReadPage: "读取页面失败:{error}", + languageDetectionFailed: "语言检测失败:{error}", currentPage: "当前页面:{lang}", translatingTo: "翻译中...", detectingLanguage: "🔍 检测中...", + hermesIntro: + '呈现nous research的hermes大型语言模型', + discussingPage: "您正在讨论", + ttsPlaceholder: "文本转语音:写任何消息,让人工智能朗读出来!", + translatePlaceholder: "输入任何要翻译的文本...", + pleaseEnterText: "请先输入一些文本!", + pleaseSelectFile: "请先选择一个文件!", + pleaseEnterTranslateText: "请输入一些要翻译的文本!", + aiModalNotAvailable: "AI模态框在此上下文中不可用", }, // Hindi @@ -783,8 +837,7 @@ function refreshUILanguage() { function detectCurrentTheme() { const isDark = document.documentElement.getAttribute("data-theme") === "dark" || - (window.matchMedia && - window.matchMedia("(prefers-color-scheme: dark)").matches && + (window.matchMedia?.("(prefers-color-scheme: dark)").matches && !document.documentElement.getAttribute("data-theme")); return isDark ? "dark" : "light"; @@ -926,7 +979,7 @@ function addCodeBlockCopyButtons(element) { copyBtn.textContent = originalText; }, 1000); } catch (error) { - alert("Failed to copy code: " + error.message); + alert(getUIText("failedToCopyCode", { error: error.message })); } }; @@ -1241,7 +1294,7 @@ export async function handleTTSFromElement(button) { const text = textarea?.value?.trim(); if (!text) { - alert("Please enter some text first!"); + alert(getUIText("pleaseEnterText")); return; } @@ -1271,7 +1324,7 @@ export async function handleTTSFromElement(button) { resultDiv.appendChild(result.audio); resultDiv.appendChild(audioControls); } catch (error) { - resultDiv.innerHTML = "Error: " + error.message; + resultDiv.innerHTML = `Error: ${error.message}`; } finally { button.disabled = false; button.textContent = "🔊 Convert to Speech"; @@ -1284,7 +1337,7 @@ export async function handleUploadFromElement(button) { const resultDiv = container.querySelector("[data-upload-result]"); if (!fileInput.files[0]) { - alert("Please select a file first!"); + alert(getUIText("pleaseSelectFile")); return; } @@ -1302,7 +1355,7 @@ export async function handleUploadFromElement(button) { fileInput.value = ""; } catch (error) { hideProgressIndicator(); - resultDiv.innerHTML = "Error: " + error.message; + resultDiv.innerHTML = `Error: ${error.message}`; } finally { button.disabled = false; button.textContent = "📁 Upload & Analyze"; @@ -1463,7 +1516,7 @@ export async function handleSmartTranslate(button) { } catch (error) { button.textContent = getUIText("smartTranslate"); button.disabled = false; - alert(`Language detection failed: ${error.message}`); + alert(getUIText("languageDetectionFailed", { error: error.message })); } } @@ -1672,11 +1725,11 @@ function setupFloatingButtonHandler(floatingButton) { console.error( "toggleUncloseaiEmbeddedModal function not available in any form", ); - alert("AI modal not available in this context"); + alert(getUIText("aiModalNotAvailable")); } } catch (error) { console.error("Error opening modal:", error); - alert("Error opening AI modal: " + error.message); + alert(getUIText("errorOpeningModal", { error: error.message })); } finally { // Restore button state floatingButton.textContent = originalText; @@ -1774,8 +1827,8 @@ async function openUncloseaiEmbeddedModalNew() { const pageTitle = document.title || window.location.hostname; subtitle.innerHTML = `