- Invoer van een 'constanten' cache op niveau van useTranslation.js, om in de ProgressTracker de boodschappen in de juiste taal te zetten.
321 lines
10 KiB
JavaScript
321 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('nl');
|
|
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 || 'nl';
|
|
};
|
|
|
|
/**
|
|
* 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');
|
|
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
|
|
};
|
|
} |