- Translations completed for Front-End, Configs (e.g. Forms) and free text.

- Allowed_languages and default_language now part of Tenant Make iso Tenant
- Introduction of Translation into Traicie Selection Specialist
This commit is contained in:
Josako
2025-06-30 14:20:17 +02:00
parent 4338f09f5c
commit fbc9f44ac8
34 changed files with 1206 additions and 220 deletions

View File

@@ -5,6 +5,7 @@ import { DynamicForm } from '/static/assets/js/components/DynamicForm.js';
import { ChatMessage } from '/static/assets/js/components/ChatMessage.js';
import { MessageHistory } from '/static/assets/js/components/MessageHistory.js';
import { ProgressTracker } from '/static/assets/js/components/ProgressTracker.js';
import { LanguageSelector } from '/static/assets/js/components/LanguageSelector.js';
// Maak componenten globaal beschikbaar voordat andere componenten worden geladen
window.DynamicForm = DynamicForm;
@@ -33,9 +34,15 @@ export const ChatApp = {
// Maak een lokale kopie van de chatConfig om undefined errors te voorkomen
const chatConfig = window.chatConfig || {};
const settings = chatConfig.settings || {};
const initialLanguage = chatConfig.language || 'nl';
const originalExplanation = chatConfig.explanation || '';
return {
// Base template data (keeping existing functionality)
// Taal gerelateerde data
currentLanguage: '',
supportedLanguageDetails: chatConfig.supportedLanguageDetails || {},
allowedLanguages: chatConfig.allowedLanguages || ['nl', 'en', 'fr', 'de'],
originalExplanation: originalExplanation,
explanation: chatConfig.explanation || '',
// Chat-specific data
@@ -164,6 +171,14 @@ export const ChatApp = {
// Keyboard shortcuts
document.addEventListener('keydown', this.handleGlobalKeydown);
// Luister naar taalwijzigingen via custom events
document.addEventListener('language-changed', (event) => {
if (event.detail && event.detail.language) {
console.log('ChatApp received language-changed event:', event.detail.language);
this.handleLanguageChange(event.detail.language);
}
});
},
cleanup() {
@@ -171,6 +186,113 @@ export const ChatApp = {
document.removeEventListener('keydown', this.handleGlobalKeydown);
},
// Taal gerelateerde functionaliteit
handleLanguageChange(newLanguage) {
if (this.currentLanguage !== newLanguage) {
console.log(`ChatApp: Taal gewijzigd van ${this.currentLanguage} naar ${newLanguage}`);
this.currentLanguage = newLanguage;
// Vertaal de sidebar
this.translateSidebar(newLanguage);
// Sla de taalvoorkeur op voor toekomstige API calls
this.storeLanguagePreference(newLanguage);
// Stuur language-changed event voor andere componenten (zoals ChatInput)
// Dit wordt gedaan via het event systeem, waardoor we geen directe referentie nodig hebben
const event = new CustomEvent('language-changed', {
detail: { language: newLanguage }
});
document.dispatchEvent(event);
}
},
// Maak de handleLanguageChange methode toegankelijk van buitenaf
// Deze functie wordt opgeroepen door het externe LanguageSelector component
__handleExternalLanguageChange(newLanguage) {
this.handleLanguageChange(newLanguage);
},
storeLanguagePreference(language) {
// Sla op in localStorage voor persistentie
localStorage.setItem('preferredLanguage', language);
// Update chatConfig voor toekomstige API calls
if (window.chatConfig) {
window.chatConfig.language = language;
}
console.log(`Taalvoorkeur opgeslagen: ${language}`);
},
async translateSidebar(language) {
console.log(`Sidebar wordt vertaald naar: ${language}`);
// Haal de originele tekst op
const originalText = this.originalExplanation || this.explanation;
try {
// Controleer of TranslationClient beschikbaar is
if (!window.TranslationClient || typeof window.TranslationClient.translate !== 'function') {
console.error('TranslationClient.translate is niet beschikbaar');
this.showTranslationIndicator(language, 'Vertaling niet beschikbaar', false);
return;
}
// Toon loading indicator
this.showTranslationIndicator(language, 'Bezig met vertalen...');
console.log('API prefix voor vertaling:', this.apiPrefix);
// Gebruik TranslationClient met de juiste parameters
const response = await window.TranslationClient.translate(
originalText,
language,
null, // source_lang (auto-detect)
'sidebar_explanation', // context
this.apiPrefix // API prefix voor tenant routing
);
if (response.success) {
// Update de explanation variabele
console.log('Translated text: ' + response.translated_text);
this.explanation = response.translated_text;
// 1. Update de Vue instance
if (window.__vueApp && window.__vueApp._instance) {
window.__vueApp._instance.proxy.explanation = response.translated_text;
}
// 2. Update direct het DOM-element via marked voor onmiddellijke weergave
const sidebarElement = document.querySelector('.sidebar-explanation');
if (sidebarElement) {
console.log('DOM-element gevonden, directe update toepassen');
// Gebruik de marked library om de markdown naar HTML te converteren
let htmlContent;
if (typeof marked === 'function') {
htmlContent = marked(response.translated_text);
} else if (marked && typeof marked.parse === 'function') {
htmlContent = marked.parse(response.translated_text);
} else {
htmlContent = response.translated_text;
}
// Update de inhoud direct
sidebarElement.innerHTML = htmlContent;
} else {
console.error('Sidebar explanation element niet gevonden in DOM');
}
this.showTranslationIndicator(language, 'Vertaling voltooid!', true);
} else {
console.error('Vertaling mislukt:', response.error);
this.showTranslationIndicator(language, 'Vertaling mislukt', false);
}
} catch (error) {
console.error('Fout bij vertalen sidebar:', error);
this.showTranslationIndicator(language, 'Vertaling mislukt', false);
}
},
// Message management
addMessage(content, sender, type = 'text', formData = null, formValues = null) {
const message = {
@@ -206,6 +328,36 @@ export const ChatApp = {
return message;
},
showTranslationIndicator(language, message, success = null) {
const explanationElement = document.querySelector('.sidebar-explanation');
if (explanationElement) {
// Verwijder eventuele bestaande indicators
const existingIndicator = explanationElement.querySelector('.language-change-indicator');
if (existingIndicator) {
existingIndicator.remove();
}
// Voeg nieuwe indicator toe
const indicator = document.createElement('div');
indicator.className = 'language-change-indicator';
if (success === true) indicator.classList.add('success');
if (success === false) indicator.classList.add('error');
indicator.innerHTML = `<small>${message}</small>`;
explanationElement.prepend(indicator);
// Verwijder na 3 seconden, behalve bij loading
if (success !== null) {
setTimeout(() => {
if (explanationElement.contains(indicator)) {
indicator.remove();
}
}, 3000);
}
}
},
// Helper functie om formulierdata toe te voegen aan bestaande berichten
attachFormDataToMessage(messageId, formData, formValues) {
const message = this.allMessages.find(m => m.id === messageId);
@@ -243,7 +395,8 @@ export const ChatApp = {
const apiData = {
message: text,
conversation_id: this.conversationId,
user_id: this.userId
user_id: this.userId,
language: this.currentLanguage
};
const response = await this.callAPI('/api/send_message', apiData);
@@ -662,6 +815,7 @@ const initializeApp = () => {
window.__vueApp.component('MessageHistory', MessageHistory);
window.__vueApp.component('ChatInput', ChatInput);
window.__vueApp.component('ProgressTracker', ProgressTracker);
// NB: LanguageSelector wordt niet globaal geregistreerd omdat deze apart gemonteerd wordt
console.log('All chat components registered with existing Vue instance');
// Register the ChatApp component
@@ -677,5 +831,63 @@ const initializeApp = () => {
}
};
// Functie om LanguageSelector toe te voegen aan sidebar
const mountLanguageSelector = () => {
const container = document.getElementById('language-selector-container');
if (container) {
// Maak een eenvoudige Vue app die alleen de LanguageSelector component mount
const app = Vue.createApp({
components: { LanguageSelector },
data() {
return {
currentLanguage: window.chatConfig?.language || 'nl',
supportedLanguageDetails: window.chatConfig?.supportedLanguageDetails || {},
allowedLanguages: window.chatConfig?.allowedLanguages || ['nl', 'en', 'fr', 'de']
};
},
methods: {
handleLanguageChange(newLanguage) {
console.log(`LanguageSelector: Taal gewijzigd naar ${newLanguage}`);
// Gebruik ALLEEN de custom event benadering
const event = new CustomEvent('language-changed', {
detail: { language: newLanguage }
});
document.dispatchEvent(event);
}
},
template: `
<language-selector
:initial-language="currentLanguage"
:supported-language-details="supportedLanguageDetails"
:allowed-languages="allowedLanguages"
@language-changed="handleLanguageChange"
></language-selector>
`
});
app.component('LanguageSelector', LanguageSelector);
app.mount('#language-selector-container');
console.log('Language selector mounted in sidebar');
} else {
console.warn('Language selector container not found');
}
};
// Initialize app when DOM is ready
document.addEventListener('DOMContentLoaded', initializeApp);
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM content loaded, initializing application...');
// Eerst de hoofdapplicatie initialiseren
initializeApp();
// Dan de taal selector monteren met een kleine vertraging
// om er zeker van te zijn dat de container is aangemaakt
setTimeout(() => {
try {
mountLanguageSelector();
} catch (e) {
console.error('Fout bij het monteren van de taal selector:', e);
}
}, 200);
});