feat(i18n): add French language support and enhance localization
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s

- Introduced French as a supported language across the application, updating locale files and adding translations for various components.
- Enhanced language handling logic to accommodate French, ensuring proper detection and fallback mechanisms.
- Updated UI elements to include French language options, improving accessibility for French-speaking users.
- Refactored SEO handling to include French in hreflang links, enhancing search engine indexing for multilingual content.
- Added new scripts for managing French translations and ensuring consistency across language files.
This commit is contained in:
Torsten Schulz (local)
2026-04-07 18:04:03 +02:00
parent f715c6125d
commit f7030bbabe
56 changed files with 5220 additions and 175 deletions

View File

@@ -3,9 +3,9 @@
<StatusBar />
<section class="falukant-hero surface-card">
<div>
<span class="falukant-kicker">Falukant</span>
<span class="falukant-kicker">{{ $t('sectionBar.sections.falukant') }}</span>
<h2>{{ $t('falukant.overview.title') }}</h2>
<p>Dein Stand in Wirtschaft, Familie und Besitz in einer verdichteten Übersicht.</p>
<p>{{ $t('falukant.overview.heroIntro') }}</p>
</div>
</section>
@@ -54,22 +54,22 @@
<article class="summary-card surface-card">
<span class="summary-card__label">{{ $t('falukant.overview.metadata.certificate') }}</span>
<strong>{{ falukantUser?.certificate ?? '---' }}</strong>
<p>Bestimmt, welche Produktkategorien du derzeit herstellen darfst.</p>
<p>{{ $t('falukant.overview.summary.certificateHint') }}</p>
</article>
<article class="summary-card surface-card">
<span class="summary-card__label">Niederlassungen</span>
<span class="summary-card__label">{{ $t('falukant.overview.summary.branches') }}</span>
<strong>{{ branchCount }}</strong>
<p>Direkter Zugriff auf deine wichtigsten Geschäftsstandorte.</p>
<p>{{ $t('falukant.overview.summary.branchesHint') }}</p>
</article>
<article class="summary-card surface-card">
<span class="summary-card__label">Produktionen aktiv</span>
<span class="summary-card__label">{{ $t('falukant.overview.summary.productions') }}</span>
<strong>{{ productionCount }}</strong>
<p>Laufende Produktionen, die zeitnah Abschluss oder Kontrolle brauchen.</p>
<p>{{ $t('falukant.overview.summary.productionsHint') }}</p>
</article>
<article class="summary-card surface-card">
<span class="summary-card__label">Lagerpositionen</span>
<span class="summary-card__label">{{ $t('falukant.overview.summary.stock') }}</span>
<strong>{{ stockEntryCount }}</strong>
<p>Verdichteter Blick auf Warenbestand über alle Regionen.</p>
<p>{{ $t('falukant.overview.summary.stockHint') }}</p>
</article>
<article v-if="falukantUser?.debtorsPrison?.active" class="summary-card surface-card">
<span class="summary-card__label">{{ $t('falukant.bank.debtorsPrison.creditworthiness') }}</span>
@@ -85,7 +85,7 @@
<section v-if="falukantUser?.character" class="falukant-routine-grid">
<article
v-for="action in routineActions"
:key="action.title"
:key="action.route"
class="routine-card surface-card"
>
<span class="routine-card__eyebrow">{{ action.kicker }}</span>
@@ -309,7 +309,7 @@
<span>{{ $t(`falukant.overview.branches.level.${branch.branchType.labelTr}`) }}</span>
</div>
</div>
<button type="button" class="button-secondary" @click="openBranch(branch.id)">Öffnen</button>
<button type="button" class="button-secondary" @click="openBranch(branch.id)">{{ $t('falukant.overview.summary.open') }}</button>
</article>
</div>
</section>
@@ -495,33 +495,33 @@ export default {
routineActions() {
return [
{
kicker: 'Routine',
title: 'Niederlassung öffnen',
description: 'Die schnellste Route zu Produktion, Lager, Verkauf und Transport.',
cta: 'Zu den Betrieben',
kicker: this.$t('falukant.overview.routine.branch.kicker'),
title: this.$t('falukant.overview.routine.branch.title'),
description: this.$t('falukant.overview.routine.branch.description'),
cta: this.$t('falukant.overview.routine.branch.cta'),
route: 'BranchView',
},
{
kicker: 'Überblick',
title: 'Finanzen prüfen',
description: 'Kontostand, Verlauf und wirtschaftliche Entwicklung ohne lange Suche.',
cta: 'Geldhistorie',
kicker: this.$t('falukant.overview.routine.finance.kicker'),
title: this.$t('falukant.overview.routine.finance.title'),
description: this.$t('falukant.overview.routine.finance.description'),
cta: this.$t('falukant.overview.routine.finance.cta'),
route: 'MoneyHistoryView',
secondary: true,
},
{
kicker: 'Charakter',
title: 'Familie und Nachfolge',
description: 'Wichtige persönliche Entscheidungen und Haushaltsstatus gesammelt.',
cta: 'Familie öffnen',
kicker: this.$t('falukant.overview.routine.family.kicker'),
title: this.$t('falukant.overview.routine.family.title'),
description: this.$t('falukant.overview.routine.family.description'),
cta: this.$t('falukant.overview.routine.family.cta'),
route: 'FalukantFamily',
secondary: true,
},
{
kicker: 'Besitz',
title: 'Haus und Umfeld',
description: 'Wohnsitz und alltäglicher Status als eigener Arbeitsbereich.',
cta: 'Zum Haus',
kicker: this.$t('falukant.overview.routine.house.kicker'),
title: this.$t('falukant.overview.routine.house.title'),
description: this.$t('falukant.overview.routine.house.description'),
cta: this.$t('falukant.overview.routine.house.cta'),
route: 'HouseView',
secondary: true,
},
@@ -774,7 +774,7 @@ export default {
await this.fetchAllStock();
await this.fetchProductions();
}
showSuccess(this, 'Erbe wurde übernommen.');
showSuccess(this, this.$t('falukant.overview.heirSelection.success'));
} catch (error) {
console.error('Error selecting heir:', error);
showError(this, this.$t('falukant.overview.heirSelection.error'));