Files

246 lines
6.9 KiB
Vue

<template>
<div class="language-selector">
<label for="language-select">Taal / Language:</label>
<div class="select-wrapper">
<select
id="language-select"
v-model="selectedLanguage"
@change="changeLanguage(selectedLanguage)"
class="language-select"
>
<option
v-for="lang in getAvailableLanguages()"
:key="lang.code"
:value="lang.code"
>
{{ lang.flag }} {{ lang.name }}
</option>
</select>
</div>
</div>
</template>
<script>
import { useLanguageProvider } from '../js/services/LanguageProvider.js';
export default {
name: 'LanguageSelector',
setup() {
// Use provider for reactive current language and setLanguage method
try {
const provider = useLanguageProvider();
return {
providerLanguage: provider.currentLanguage,
providerSetLanguage: provider.setLanguage
};
} catch {
// Provider not available, use props
return {};
}
},
props: {
initialLanguage: {
type: String,
default: 'en'
},
currentLanguage: {
type: String,
default: null
},
supportedLanguageDetails: {
type: Object,
default: () => ({})
},
allowedLanguages: {
type: Array,
default: () => ['nl', 'en', 'fr', 'de']
},
},
data() {
const startLanguage = this.currentLanguage || this.initialLanguage;
return {
selectedLanguage: startLanguage,
internalCurrentLanguage: startLanguage
};
},
mounted() {
// Emit initial language
this.$emit('language-changed', this.selectedLanguage);
// DOM event
const event = new CustomEvent('language-changed', {
detail: { language: this.selectedLanguage }
});
document.dispatchEvent(event);
},
computed: {
// Use provider language if available, otherwise use props
effectiveCurrentLanguage() {
return this.providerLanguage || this.currentLanguage || this.initialLanguage;
}
},
methods: {
getAvailableLanguages() {
const languages = [];
const languagesToUse = (this.allowedLanguages && this.allowedLanguages.length > 0)
? this.allowedLanguages
: ['nl', 'en', 'fr', 'de'];
if (this.supportedLanguageDetails && Object.keys(this.supportedLanguageDetails).length > 0) {
for (const [langName, langDetails] of Object.entries(this.supportedLanguageDetails)) {
const isoCode = langDetails['iso 639-1'];
if (languagesToUse.includes(isoCode)) {
languages.push({
code: isoCode,
name: langName,
flag: langDetails.flag || ''
});
}
}
} else {
const defaultLanguages = {
'nl': { name: 'Nederlands', flag: '🇳🇱' },
'en': { name: 'English', flag: '🇬🇧' },
'fr': { name: 'Français', flag: '🇫🇷' },
'de': { name: 'Deutsch', flag: '🇩🇪' }
};
languagesToUse.forEach(code => {
if (defaultLanguages[code]) {
languages.push({
code: code,
name: defaultLanguages[code].name,
flag: defaultLanguages[code].flag
});
}
});
}
return languages;
},
changeLanguage(languageCode) {
console.log(`LanguageSelector: changeLanguage called with ${languageCode}`);
if (this.internalCurrentLanguage !== languageCode) {
this.internalCurrentLanguage = languageCode;
this.selectedLanguage = languageCode;
// Call LanguageProvider setLanguage method to trigger proper translation
if (this.providerSetLanguage) {
console.log(`LanguageSelector: Calling LanguageProvider.setLanguage(${languageCode})`);
this.providerSetLanguage(languageCode);
} else {
console.warn('LanguageSelector: LanguageProvider not available, using fallback DOM events only');
}
// Vue component emit (for backward compatibility)
this.$emit('language-changed', languageCode);
// DOM event (for backward compatibility)
const event = new CustomEvent('language-changed', {
detail: { language: languageCode }
});
document.dispatchEvent(event);
}
}
}
};
</script>
<style scoped>
/* Styling voor de taalselector */
.sidebar-language-section {
padding: 10px 15px;
margin-bottom: 15px;
}
#language-selector-container {
display: flex;
flex-direction: column;
padding: 15px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 5px;
}
#language-selector-container label {
margin-bottom: 5px;
color: var(--sidebar-color);
font-size: 0.9rem;
font-weight: 500;
}
.language-selector {
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
}
.language-selector:hover {
background-color: rgba(0, 0, 0, 0.3);
}
.language-selector:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}
.language-selector option {
background-color: #2c3e50;
color: white;
padding: 8px;
}
.select-wrapper {
position: relative;
}
.language-select {
padding: 8px 12px;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.2);
color: var(--sidebar-color);
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
}
.language-select:hover {
background-color: rgba(0, 0, 0, 0.3);
}
.language-select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}
.language-select option {
background-color: #2c3e50;
color: white;
padding: 8px;
}
/* Mobile-specific styling when used in mobile header */
@media (max-width: 768px) {
.language-selector {
margin: 0;
}
.language-selector label {
display: none; /* Hide label in mobile header */
}
.language-select {
padding: 6px 10px;
font-size: 0.85rem;
min-width: 120px;
margin: 0;
}
}
</style>