// eveai_chat_client/static/assets/js/composables/useTranslation.js import { ref, computed, onMounted } from 'vue'; /** * Vue 3 Composable for translation management * Provides modern alternative to window.TranslationClient */ export function useTranslation() { const isTranslationReady = ref(false); const currentLanguage = ref('nl'); const isTranslating = ref(false); const lastError = ref(null); // Check if translation system is available with retry mechanism const checkTranslationReady = () => { if (window.TranslationClient && typeof window.TranslationClient.translate === 'function') { isTranslationReady.value = true; return true; } return false; }; onMounted(() => { // Initial check if (checkTranslationReady()) { return; } // Retry mechanism - wait for TranslationClient to become available let retryCount = 0; const maxRetries = 10; const retryInterval = 100; // 100ms const retryCheck = () => { if (checkTranslationReady()) { return; // Success! } retryCount++; if (retryCount < maxRetries) { setTimeout(retryCheck, retryInterval); } else { console.warn('TranslationClient is not available after retries'); isTranslationReady.value = false; } }; // Start retry process setTimeout(retryCheck, retryInterval); }); /** * Translate text to target language * @param {string} text - Text to translate * @param {string} targetLang - Target language code * @param {string|null} sourceLang - Source language code (optional) * @param {string|null} context - Translation context (optional) * @param {string} apiPrefix - API prefix for tenant routing * @returns {Promise} Translation result */ const translate = async (text, targetLang, sourceLang = null, context = null, apiPrefix = '') => { if (!isTranslationReady.value || !window.TranslationClient) { const error = new Error('Translation system not ready'); lastError.value = error; throw error; } if (!text || !text.trim()) { const error = new Error('No text provided for translation'); lastError.value = error; throw error; } isTranslating.value = true; lastError.value = null; try { const result = await window.TranslationClient.translate( text, targetLang, sourceLang, context, apiPrefix ); // Update current language if translation was successful if (result.success) { currentLanguage.value = targetLang; } return result; } catch (error) { console.error('Translation error in composable:', error); lastError.value = error; throw error; } finally { isTranslating.value = false; } }; /** * Translate text with automatic error handling and loading state * @param {string} text - Text to translate * @param {string} targetLang - Target language code * @param {Object} options - Translation options * @returns {Promise} Translated text or null on error */ const translateSafe = async (text, targetLang, options = {}) => { const { sourceLang = null, context = null, apiPrefix = '', fallbackText = text } = options; try { const result = await translate(text, targetLang, sourceLang, context, apiPrefix); return result.success ? result.translated_text : fallbackText; } catch (error) { console.warn('Safe translation failed, using fallback:', error.message); return fallbackText; } }; /** * Batch translate multiple texts * @param {Array} texts - Array of texts to translate * @param {string} targetLang - Target language code * @param {Object} options - Translation options * @returns {Promise>} Array of translated texts */ const translateBatch = async (texts, targetLang, options = {}) => { const results = await Promise.allSettled( texts.map(text => translateSafe(text, targetLang, options)) ); return results.map((result, index) => result.status === 'fulfilled' ? result.value : texts[index] ); }; /** * Get current language from chatConfig or fallback */ const getCurrentLanguage = () => { return window.chatConfig?.language || currentLanguage.value; }; /** * Get API prefix from chatConfig or fallback */ const getApiPrefix = () => { return window.chatConfig?.apiPrefix || ''; }; return { // State isTranslationReady, currentLanguage: computed(() => getCurrentLanguage()), isTranslating, lastError, // Methods translate, translateSafe, translateBatch, // Utilities getCurrentLanguage, getApiPrefix }; } /** * Simplified composable for basic translation needs * Use this when you only need simple text translation */ export function useTranslationClient() { const { translate, translateSafe, isTranslationReady, isTranslating, lastError } = useTranslation(); return { translate, translateSafe, isTranslationReady, isTranslating, lastError }; } /** * Composable for reactive text translation * Automatically translates text when language changes */ export function useReactiveTranslation(text, options = {}) { const { translateSafe, currentLanguage } = useTranslation(); const translatedText = ref(text); const isLoading = ref(false); const { context = null, sourceLang = null, autoTranslate = true } = options; // Watch for language changes and auto-translate if (autoTranslate) { // We'll implement this when we have proper reactivity setup // For now, provide manual translation method } const updateTranslation = async (newLanguage = null) => { const targetLang = newLanguage || currentLanguage.value; if (!text || targetLang === sourceLang) { translatedText.value = text; return; } isLoading.value = true; try { const result = await translateSafe(text, targetLang, { sourceLang, context, apiPrefix: window.chatConfig?.apiPrefix || '' }); translatedText.value = result; } finally { isLoading.value = false; } }; return { translatedText, isLoading, updateTranslation }; }