feat(localization): expand language support and enhance UI for user settings
- Added support for additional UI locales including Cebuano and Spanish, improving accessibility for a broader user base. - Updated language selection components in the AppHeader and SettingsWidget to reflect new language options, enhancing user experience. - Enhanced localization of various UI elements across components, ensuring consistent language representation and improved user engagement. - Implemented logic to synchronize user language preferences with backend settings, providing a seamless experience when changing languages.
This commit is contained in:
@@ -5,21 +5,34 @@
|
||||
<div class="logo"><img src="/images/logos/logo.png" alt="YourPart" /></div>
|
||||
<div class="brand-copy">
|
||||
<strong>YourPart</strong>
|
||||
<span>Community-Plattform</span>
|
||||
<span>{{ $t('appShell.header.tagline') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-meta">
|
||||
<div class="header-meta__context">
|
||||
<span class="header-pill">Beta</span>
|
||||
<span class="header-pill">{{ $t('appShell.header.beta') }}</span>
|
||||
<label class="header-lang">
|
||||
<span class="header-lang__label">{{ $t('appShell.header.language') }}</span>
|
||||
<select
|
||||
class="header-lang__select"
|
||||
:aria-label="$t('appShell.header.language')"
|
||||
:value="language"
|
||||
@change="onUiLanguageChange($event.target.value)"
|
||||
>
|
||||
<option v-for="opt in uiLocaleOptions" :key="opt.value" :value="opt.value">
|
||||
{{ $t(opt.labelTr) }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="connection-status" v-if="isLoggedIn">
|
||||
<div class="status-indicator" :class="backendStatusClass">
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text">Backend</span>
|
||||
<span class="status-text">{{ $t('appShell.header.backend') }}</span>
|
||||
</div>
|
||||
<div class="status-indicator" :class="daemonStatusClass">
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text">Daemon</span>
|
||||
<span class="status-text">{{ $t('appShell.header.daemon') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,11 +42,22 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'AppHeader',
|
||||
data() {
|
||||
return {
|
||||
uiLocaleOptions: [
|
||||
{ value: 'de', labelTr: 'settings.personal.language.de' },
|
||||
{ value: 'en', labelTr: 'settings.personal.language.en' },
|
||||
{ value: 'ceb', labelTr: 'settings.personal.language.ceb' },
|
||||
{ value: 'es', labelTr: 'settings.personal.language.es' },
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isLoggedIn', 'connectionStatus', 'daemonConnectionStatus']),
|
||||
...mapGetters(['isLoggedIn', 'user', 'language', 'connectionStatus', 'daemonConnectionStatus']),
|
||||
backendStatusClass() {
|
||||
return {
|
||||
'status-connected': this.connectionStatus === 'connected',
|
||||
@@ -50,7 +74,40 @@ export default {
|
||||
'status-error': this.daemonConnectionStatus === 'error'
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onUiLanguageChange(code) {
|
||||
const supported = ['de', 'en', 'ceb', 'es'];
|
||||
if (!supported.includes(code)) {
|
||||
return;
|
||||
}
|
||||
await this.$store.dispatch('setLanguage', code);
|
||||
if (!this.isLoggedIn || !this.user?.id) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { data } = await apiClient.post('/api/settings/filter', {
|
||||
userid: this.user.id,
|
||||
type: 'personal',
|
||||
});
|
||||
const langRow = data.find((s) => s.name === 'language');
|
||||
if (!langRow?.options?.length) {
|
||||
return;
|
||||
}
|
||||
const opt = langRow.options.find((o) => o.value === code);
|
||||
if (!opt) {
|
||||
return;
|
||||
}
|
||||
await apiClient.post('/api/settings/update', {
|
||||
userid: this.user.id,
|
||||
settingId: langRow.id,
|
||||
value: opt.id,
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn('AppHeader: profile language could not be synced', err);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -144,6 +201,38 @@ export default {
|
||||
color: #8a5411;
|
||||
}
|
||||
|
||||
.header-lang {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin: 0;
|
||||
font-size: 0.72rem;
|
||||
color: rgba(95, 75, 57, 0.85);
|
||||
}
|
||||
|
||||
.header-lang__label {
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-lang__select {
|
||||
min-width: 7.5rem;
|
||||
max-width: 11rem;
|
||||
padding: 4px 8px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(93, 64, 55, 0.18);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
color: #3a2a1b;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-lang__select:focus {
|
||||
outline: 2px solid rgba(248, 162, 43, 0.45);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.connection-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user