Files
eveAI/eveai_chat_client/static/assets/js/composables/useTranslation.js
Josako 4ad621428e - verbeteringen client
- Enkel nog probleem met vertaling van de ProgressTracker constanten
2025-07-21 21:45:46 +02:00

323 lines
10 KiB
JavaScript

// eveai_chat_client/static/assets/js/composables/useTranslation.js
import { ref, computed, onMounted } from 'vue';
/**
* Vue 3 Composable for translation management
* Provides direct backend API communication for translations
*/
export function useTranslation() {
const isTranslationReady = ref(false);
const currentLanguage = ref('en');
const isTranslating = ref(false);
const lastError = ref(null);
// Check if translation system is available
const checkTranslationReady = () => {
// Translation is altijd ready omdat we de backend API gebruiken
// Controleer alleen of we in een browser environment zijn
if (typeof window !== 'undefined' && typeof fetch !== 'undefined') {
isTranslationReady.value = true;
return true;
}
return false;
};
onMounted(() => {
// Eenvoudige check - geen retry mechanism nodig
checkTranslationReady();
});
/**
* 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<object>} Translation result
*/
const translate = async (text, targetLang, sourceLang = null, context = null, apiPrefix = '') => {
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 {
// Bepaal de juiste API URL
const baseUrl = apiPrefix || window.chatConfig?.apiPrefix || '';
const apiUrl = `${baseUrl}/api/translate`;
// Maak de request payload
const payload = {
text: text,
target_lang: targetLang
};
// Voeg optionele parameters toe
if (sourceLang) payload.source_lang = sourceLang;
if (context) payload.context = context;
// Maak de HTTP request
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
credentials: 'same-origin', // Voor sessie cookies
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
// 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<string|null>} 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<string>} texts - Array of texts to translate
* @param {string} targetLang - Target language code
* @param {Object} options - Translation options
* @returns {Promise<Array<string>>} 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 || 'en';
};
/**
* 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
};
}
// Global cache for constants - shared across all component instances
const CONSTANTS_CACHE = {
currentLanguage: null,
translations: {}
};
/**
* Composable for translating application constants with global caching
* This ensures all component instances share the same cached translations
*/
export function useConstantsTranslation() {
const { translateSafe } = useTranslation();
/**
* Translate constants with global caching
* @param {Object} constants - Object with key-value pairs of constants to translate
* @param {string} targetLang - Target language code
* @param {Object} options - Translation options
* @returns {Promise<Object>} Object with translated constants
*/
const translateConstants = async (constants, targetLang, options = {}) => {
console.log('useConstantsTranslation: translateConstants called', { targetLang, currentCached: CONSTANTS_CACHE.currentLanguage });
// Check if we already have translations for this language
if (CONSTANTS_CACHE.currentLanguage === targetLang && CONSTANTS_CACHE.translations) {
console.log('useConstantsTranslation: Using cached translations for', targetLang);
return { ...CONSTANTS_CACHE.translations };
}
console.log('useConstantsTranslation: Translating constants to', targetLang);
try {
const translated = {};
// Translate each constant
for (const [key, originalText] of Object.entries(constants)) {
translated[key] = await translateSafe(originalText, targetLang, {
context: 'constants',
fallbackText: originalText,
...options
});
}
// Update global cache
CONSTANTS_CACHE.currentLanguage = targetLang;
CONSTANTS_CACHE.translations = translated;
console.log('useConstantsTranslation: Successfully translated and cached constants');
console.log('useConstantsTranslation: Current language:', CONSTANTS_CACHE.currentLanguage);
console.log('useConstantsTranslation: Cached translations:', CONSTANTS_CACHE.translations);
return translated;
} catch (error) {
console.error('useConstantsTranslation: Error translating constants:', error);
// Return original constants as fallback
return { ...constants };
}
};
/**
* Get cached translations for current language
* @returns {Object|null} Cached translations or null if not available
*/
const getCachedTranslations = () => {
return CONSTANTS_CACHE.currentLanguage ? { ...CONSTANTS_CACHE.translations } : null;
};
/**
* Clear the constants cache (useful for testing or language reset)
*/
const clearCache = () => {
CONSTANTS_CACHE.currentLanguage = null;
CONSTANTS_CACHE.translations = {};
console.log('useConstantsTranslation: Cache cleared');
};
/**
* Get current cached language
*/
const getCachedLanguage = () => {
return CONSTANTS_CACHE.currentLanguage;
};
return {
translateConstants,
getCachedTranslations,
clearCache,
getCachedLanguage
};
}
/**
* 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
};
}