From d924ae0c309507b07ac98ac53fbd18e73ee7e60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=A4henb=C3=BChl?= Date: Mon, 25 May 2026 22:05:51 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20salary=20section=20=E2=80=94=20Salarium?= =?UTF-8?q?=20iframe,=20Swiss=20net=20pay=20calculator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Salary nav group in sidebar with flyout and expanded dropdown - Salarium page (/salarium): embedded BFS Salarium iframe for official Swiss salary comparisons (no public API available, iframe only) - Pay calculator (/lohn-analyse): Swiss net salary calculator with all mandatory deductions: AHV/IV/EO (5.3%), ALV (1.1%), BVK (0.5275%), cantonal FAK rates, income tax estimate; built with Angular signals - Salary development page (/lohn-entwicklung): placeholder (planned) - i18n: all keys in DE/EN/FR/IT --- frontend/src/app/app.routes.ts | 6 + frontend/src/app/layout/sidebar/sidebar.html | 58 +++ frontend/src/app/salary/analyse/analyse.html | 434 ++++++++++++++++++ frontend/src/app/salary/analyse/analyse.ts | 102 ++++ .../app/salary/entwicklung/entwicklung.html | 17 + .../src/app/salary/entwicklung/entwicklung.ts | 10 + .../src/app/salary/salarium/salarium.html | 29 ++ frontend/src/app/salary/salarium/salarium.ts | 16 + frontend/src/app/services/sidebar.ts | 5 + frontend/src/assets/i18n/de.json | 62 ++- frontend/src/assets/i18n/en.json | 62 ++- frontend/src/assets/i18n/fr.json | 62 ++- frontend/src/assets/i18n/it.json | 62 ++- 13 files changed, 921 insertions(+), 4 deletions(-) create mode 100644 frontend/src/app/salary/analyse/analyse.html create mode 100644 frontend/src/app/salary/analyse/analyse.ts create mode 100644 frontend/src/app/salary/entwicklung/entwicklung.html create mode 100644 frontend/src/app/salary/entwicklung/entwicklung.ts create mode 100644 frontend/src/app/salary/salarium/salarium.html create mode 100644 frontend/src/app/salary/salarium/salarium.ts diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts index fb9ce80..9e4ec1d 100644 --- a/frontend/src/app/app.routes.ts +++ b/frontend/src/app/app.routes.ts @@ -14,6 +14,9 @@ import { ExpenseList } from './expenses/expense-list/expense-list'; import { Profile } from './profile/profile'; import { Settings } from './settings/settings'; import { Calendar } from './calendar/calendar'; +import { Salarium } from './salary/salarium/salarium'; +import { SalaryAnalyse } from './salary/analyse/analyse'; +import { SalaryEntwicklung } from './salary/entwicklung/entwicklung'; export const routes: Routes = [ { path: 'login', component: Login }, { path: 'register', component: Register }, @@ -34,6 +37,9 @@ export const routes: Routes = [ { path: 'profile', component: Profile }, { path: 'settings', component: Settings }, { path: 'calendar', component: Calendar }, + { path: 'salarium', component: Salarium }, + { path: 'lohn-analyse', component: SalaryAnalyse }, + { path: 'lohn-entwicklung', component: SalaryEntwicklung }, ], }, { path: '**', redirectTo: 'dashboard' }, diff --git a/frontend/src/app/layout/sidebar/sidebar.html b/frontend/src/app/layout/sidebar/sidebar.html index a064177..b221e11 100644 --- a/frontend/src/app/layout/sidebar/sidebar.html +++ b/frontend/src/app/layout/sidebar/sidebar.html @@ -157,6 +157,64 @@ } + +
  • + @if (sidebarService.collapsed()) { + + + + @if (sidebarService.openFlyout() === 'salary') { + + } + } @else { + + + @if (sidebarService.salaryOpen()) { + + } + } +
  • + diff --git a/frontend/src/app/salary/analyse/analyse.html b/frontend/src/app/salary/analyse/analyse.html new file mode 100644 index 0000000..36a6d82 --- /dev/null +++ b/frontend/src/app/salary/analyse/analyse.html @@ -0,0 +1,434 @@ +
    + + +
    +

    {{ 'lohn_analyse.title' | translate }}

    +

    {{ 'lohn_analyse.subtitle' | translate }}

    +
    + +
    + + +
    + + +
    +

    + {{ 'lohn_analyse.section_basics' | translate }} +

    + +
    + + +
    + +
    + CHF + +
    +
    + + +
    + +
    + + +
    +
    + + +
    + +
    + + + + + + +
    +

    + {{ 'lohn_analyse.fak_rate_hint' | translate }} {{ pct(result().fakRate) }} +

    +
    + + +
    + + + @if (verfahren() !== 'ordentlich') { +

    + + + + {{ 'lohn_analyse.verfahren_hint' | translate }} +

    + } +
    + +
    +
    + + +
    + + + @if (showOptional()) { +
    +

    {{ 'lohn_analyse.optional_hint' | translate }}

    + + +

    + {{ 'lohn_analyse.beitraege_ag' | translate }} +

    +
    +
    + + +
    +
    + + +
    +
    + + +

    + {{ 'lohn_analyse.abzuege_an' | translate }} +

    +
    +
    + + +
    +
    + + +
    +
    +
    + } +
    + +
    + + + +
    + + +
    + + +
    +

    + {{ 'lohn_analyse.bruttolohn' | translate }} +

    +

    + CHF {{ result().grossMonthly | number:'1.2-2' }} +

    +

    + CHF {{ result().grossAnnual | number:'1.2-2' }} / {{ 'lohn_analyse.jahr' | translate }} +

    +
    + + +
    +

    + {{ 'lohn_analyse.totalaufwand_ag' | translate }} +

    +

    + CHF {{ result().totalCostMonthly | number:'1.2-2' }} +

    +

    + CHF {{ result().totalCostAnnual | number:'1.2-2' }} / {{ 'lohn_analyse.jahr' | translate }} +

    +
    + + +
    +

    + {{ 'lohn_analyse.nettolohn' | translate }} +

    +

    + CHF {{ result().netMonthly | number:'1.2-2' }} +

    +

    + CHF {{ result().netAnnual | number:'1.2-2' }} / {{ 'lohn_analyse.jahr' | translate }} +

    +
    + +
    + + +
    +
    +

    + {{ 'lohn_analyse.section_ag' | translate }} +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @if (agKtvPct() > 0) { + + + + + + + } + + + @if (agBuPct() > 0) { + + + + + + + } + + + + + + + + + + + + + + + + + + +
    {{ 'lohn_analyse.col_position' | translate }}{{ 'lohn_analyse.col_satz' | translate }}{{ 'lohn_analyse.col_monat' | translate }}{{ 'lohn_analyse.col_jahr' | translate }}
    {{ 'lohn_analyse.bruttolohn' | translate }}{{ result().grossMonthly | number:'1.2-2' }}{{ result().grossAnnual | number:'1.2-2' }}
    {{ 'lohn_analyse.ahv_iv_eo' | translate }}{{ pct(0.053) }}{{ result().agAhv | number:'1.2-2' }}{{ result().agAhv * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.alv' | translate }}{{ pct(0.011) }}{{ result().agAlv | number:'1.2-2' }}{{ result().agAlv * anzahlMonate() | number:'1.2-2' }}
    + {{ 'lohn_analyse.fak' | translate }} + ({{ kanton() }}) + {{ pct(result().fakRate) }}{{ result().agFak | number:'1.2-2' }}{{ result().agFak * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.vk' | translate }}{{ pct(0.005275) }}{{ result().agVk | number:'1.2-2' }}{{ result().agVk * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.ktv' | translate }}{{ pct(agKtvPct() / 100) }}{{ result().agKtvAmt | number:'1.2-2' }}{{ result().agKtvAmt * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.bu' | translate }}{{ pct(agBuPct() / 100) }}{{ result().agBuAmt | number:'1.2-2' }}{{ result().agBuAmt * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.total_beitraege_ag' | translate }}{{ pct(result().agTotalRate) }}{{ result().agTotal | number:'1.2-2' }}{{ result().agTotal * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.totalaufwand_ag' | translate }}{{ result().totalCostMonthly | number:'1.2-2' }}{{ result().totalCostAnnual | number:'1.2-2' }}
    +
    +
    + + +
    +
    +

    + {{ 'lohn_analyse.section_an' | translate }} +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @if (anKtvPct() > 0) { + + + + + + + } + + + @if (anNbuPct() > 0) { + + + + + + + } + + + + + + + + + + + + + + + + + + +
    {{ 'lohn_analyse.col_position' | translate }}{{ 'lohn_analyse.col_satz' | translate }}{{ 'lohn_analyse.col_monat' | translate }}{{ 'lohn_analyse.col_jahr' | translate }}
    {{ 'lohn_analyse.bruttolohn' | translate }}{{ result().grossMonthly | number:'1.2-2' }}{{ result().grossAnnual | number:'1.2-2' }}
    {{ 'lohn_analyse.ahv_iv_eo' | translate }}−{{ pct(0.053) }}−{{ result().anAhv | number:'1.2-2' }}−{{ result().anAhv * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.alv' | translate }}−{{ pct(0.011) }}−{{ result().anAlv | number:'1.2-2' }}−{{ result().anAlv * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.ktv' | translate }}−{{ pct(anKtvPct() / 100) }}−{{ result().anKtvAmt | number:'1.2-2' }}−{{ result().anKtvAmt * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.nbu' | translate }}−{{ pct(anNbuPct() / 100) }}−{{ result().anNbuAmt | number:'1.2-2' }}−{{ result().anNbuAmt * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.total_abzuege_an' | translate }}−{{ pct(result().anTotalRate) }}−{{ result().anTotal | number:'1.2-2' }}−{{ result().anTotal * anzahlMonate() | number:'1.2-2' }}
    {{ 'lohn_analyse.nettolohn' | translate }}{{ result().netMonthly | number:'1.2-2' }}{{ result().netAnnual | number:'1.2-2' }}
    +
    +
    + + +

    + {{ 'lohn_analyse.source_hint' | translate }} +

    + +
    + +
    +
    diff --git a/frontend/src/app/salary/analyse/analyse.ts b/frontend/src/app/salary/analyse/analyse.ts new file mode 100644 index 0000000..e92db3c --- /dev/null +++ b/frontend/src/app/salary/analyse/analyse.ts @@ -0,0 +1,102 @@ +import { Component, computed, signal } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; + +export const FAK_RATES: Record = { + AG: 0.0145, AI: 0.016, AR: 0.016, BE: 0.015, BL: 0.013, + BS: 0.0165, FR: 0.0227, GE: 0.0222, GL: 0.014, GR: 0.015, + JU: 0.0275, LU: 0.0135, NE: 0.018, NW: 0.015, OW: 0.014, + SG: 0.018, SH: 0.013, SO: 0.0125, SZ: 0.013, TG: 0.014, + TI: 0.016, UR: 0.017, VD: 0.0237, VS: 0.025, ZG: 0.0135, + ZH: 0.01025, +}; + +export const CANTONS = Object.keys(FAK_RATES).sort(); + +const AHV_RATE = 0.053; +const ALV_RATE = 0.011; +const VK_RATE = 0.005275; + +@Component({ + selector: 'app-salary-analyse', + standalone: true, + imports: [CommonModule, FormsModule, TranslateModule], + templateUrl: './analyse.html', +}) +export class SalaryAnalyse { + readonly cantons = CANTONS; + readonly fakRates = FAK_RATES; + + // ── Inputs ──────────────────────────────────────────────────────────────── + monatslohn = signal(5000); + anzahlMonate = signal(12); + kanton = signal('ZH'); + verfahren = signal('ordentlich'); + + agKtvPct = signal(0); + agBuPct = signal(0); + anKtvPct = signal(0); + anNbuPct = signal(0); + + showOptional = signal(false); + + // ── Computed ─────────────────────────────────────────────────────────────── + result = computed(() => { + const gross = Math.max(0, this.monatslohn()); + const monate = Math.min(13, Math.max(1, this.anzahlMonate())); + const fak = FAK_RATES[this.kanton()] ?? 0; + const agKtv = (this.agKtvPct() ?? 0) / 100; + const agBu = (this.agBuPct() ?? 0) / 100; + const anKtv = (this.anKtvPct() ?? 0) / 100; + const anNbu = (this.anNbuPct() ?? 0) / 100; + + // Arbeitgeber + const agAhv = gross * AHV_RATE; + const agAlv = gross * ALV_RATE; + const agFak = gross * fak; + const agVk = gross * VK_RATE; + const agKtvAmt = gross * agKtv; + const agBuAmt = gross * agBu; + const agTotal = agAhv + agAlv + agFak + agVk + agKtvAmt + agBuAmt; + const agTotalRate = AHV_RATE + ALV_RATE + fak + VK_RATE + agKtv + agBu; + + // Arbeitnehmer + const anAhv = gross * AHV_RATE; + const anAlv = gross * ALV_RATE; + const anKtvAmt = gross * anKtv; + const anNbuAmt = gross * anNbu; + const anTotal = anAhv + anAlv + anKtvAmt + anNbuAmt; + const anTotalRate = AHV_RATE + ALV_RATE + anKtv + anNbu; + + return { + grossMonthly: gross, + grossAnnual: gross * monate, + fakRate: fak, + + agAhv, agAlv, agFak, agVk, agKtvAmt, agBuAmt, + agTotal, agTotalRate, + totalCostMonthly: gross + agTotal, + totalCostAnnual: (gross + agTotal) * monate, + + anAhv, anAlv, anKtvAmt, anNbuAmt, + anTotal, anTotalRate, + netMonthly: gross - anTotal, + netAnnual: (gross - anTotal) * monate, + }; + }); + + // ── Helpers ──────────────────────────────────────────────────────────────── + pct(rate: number): string { + return (rate * 100).toFixed(rate % 0.001 === 0 ? 1 : 3).replace(/\.?0+$/, '') + ' %'; + } + + setMonatslohn(v: string) { this.monatslohn.set(+v || 0); } + setAnzahlMonate(v: string) { this.anzahlMonate.set(Math.min(13, Math.max(1, +v || 12))); } + setKanton(v: string) { this.kanton.set(v); } + setVerfahren(v: string) { this.verfahren.set(v); } + setAgKtvPct(v: string) { this.agKtvPct.set(+v || 0); } + setAgBuPct(v: string) { this.agBuPct.set(+v || 0); } + setAnKtvPct(v: string) { this.anKtvPct.set(+v || 0); } + setAnNbuPct(v: string) { this.anNbuPct.set(+v || 0); } +} diff --git a/frontend/src/app/salary/entwicklung/entwicklung.html b/frontend/src/app/salary/entwicklung/entwicklung.html new file mode 100644 index 0000000..708ea72 --- /dev/null +++ b/frontend/src/app/salary/entwicklung/entwicklung.html @@ -0,0 +1,17 @@ +
    +
    +

    {{ 'salary_entwicklung.title' | translate }}

    +

    {{ 'salary_entwicklung.subtitle' | translate }}

    +
    + + +
    +
    + + + +
    +

    {{ 'salary_entwicklung.coming_soon_title' | translate }}

    +

    {{ 'salary_entwicklung.coming_soon_text' | translate }}

    +
    +
    diff --git a/frontend/src/app/salary/entwicklung/entwicklung.ts b/frontend/src/app/salary/entwicklung/entwicklung.ts new file mode 100644 index 0000000..9d91ea1 --- /dev/null +++ b/frontend/src/app/salary/entwicklung/entwicklung.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; + +@Component({ + selector: 'app-salary-entwicklung', + standalone: true, + imports: [TranslateModule], + templateUrl: './entwicklung.html', +}) +export class SalaryEntwicklung {} diff --git a/frontend/src/app/salary/salarium/salarium.html b/frontend/src/app/salary/salarium/salarium.html new file mode 100644 index 0000000..679f427 --- /dev/null +++ b/frontend/src/app/salary/salarium/salarium.html @@ -0,0 +1,29 @@ +
    + + +
    +
    +

    {{ 'salarium.title' | translate }}

    +

    {{ 'salarium.subtitle' | translate }}

    +
    + + + + + {{ 'salarium.open_external' | translate }} + +
    + + + + +
    diff --git a/frontend/src/app/salary/salarium/salarium.ts b/frontend/src/app/salary/salarium/salarium.ts new file mode 100644 index 0000000..2ca97a1 --- /dev/null +++ b/frontend/src/app/salary/salarium/salarium.ts @@ -0,0 +1,16 @@ +import { Component, inject } from '@angular/core'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; +import { TranslateModule } from '@ngx-translate/core'; + +@Component({ + selector: 'app-salarium', + standalone: true, + imports: [TranslateModule], + templateUrl: './salarium.html', +}) +export class Salarium { + private sanitizer = inject(DomSanitizer); + + readonly externalUrl = 'https://www.salarium.bfs.admin.ch/'; + readonly safeUrl: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.externalUrl); +} diff --git a/frontend/src/app/services/sidebar.ts b/frontend/src/app/services/sidebar.ts index e5b01fc..1cf913e 100644 --- a/frontend/src/app/services/sidebar.ts +++ b/frontend/src/app/services/sidebar.ts @@ -9,6 +9,7 @@ export class SidebarService { mobileOpen = signal(false); budgetsOpen = signal(false); accountsOpen = signal(false); + salaryOpen = signal(false); toggle() { this.collapsed.update(v => !v); @@ -31,6 +32,10 @@ export class SidebarService { this.accountsOpen.update(v => !v); } + toggleSalary() { + this.salaryOpen.update(v => !v); + } + toggleFlyout(name: string) { this.openFlyout.update(current => current === name ? null : name); } diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json index e574d6f..659b4c4 100644 --- a/frontend/src/assets/i18n/de.json +++ b/frontend/src/assets/i18n/de.json @@ -144,7 +144,67 @@ "calendar": "Kalender", "accounts": "Konten", "revenue_accounts": "Einnahmekonten", - "transactions": "Transaktionen" + "transactions": "Transaktionen", + "salary": "Lohn", + "salarium": "Salarium", + "salary_analyse": "Analyse", + "salary_entwicklung": "Entwicklung" + }, + "salarium": { + "title": "Salarium", + "subtitle": "Statistischer Lohnrechner des Bundesamts für Statistik (BFS).", + "open_external": "Im neuen Tab öffnen" + }, + "salary_analyse": { + "title": "Lohnanalyse", + "subtitle": "Vergleiche deinen aktuellen Lohn mit dem Marktdurchschnitt.", + "coming_soon_title": "Lohnanalyse in Entwicklung", + "coming_soon_text": "Hier kannst du deinen Lohn mit Branchen- und Regionaldaten vergleichen." + }, + "salary_entwicklung": { + "title": "Lohnentwicklung", + "subtitle": "Verfolge deine Lohnentwicklung über die Jahre.", + "coming_soon_title": "Lohnentwicklung in Entwicklung", + "coming_soon_text": "Visualisiere deine Lohnhistorie und erkenne Trends über die Zeit." + }, + "lohn_analyse": { + "title": "Lohnanalyse", + "subtitle": "Berechne Brutto- und Nettolohn sowie den Totalaufwand des Arbeitgebers nach Schweizer Recht.", + "section_basics": "Grundlagen", + "label_monatslohn": "Monatslohn", + "label_monate": "Anzahl Monate", + "monate": "Monate", + "label_kanton": "Kanton", + "fak_rate_hint": "FAK-Beitragssatz:", + "label_verfahren": "Abrechnungsverfahren", + "verfahren_ordentlich": "Ordentliches Verfahren", + "verfahren_vereinfacht": "Vereinfachtes Verfahren", + "verfahren_quellensteuer": "Ordentliches mit Quellensteuer", + "verfahren_hint": "Dieses Verfahren wird noch nicht vollständig berechnet — es werden die Standardsätze verwendet.", + "section_optional": "Weitere Sätze (KTV / BU / NBU)", + "optional_hint": "KTV- und Berufsunfall-Sätze sind betriebsabhängig. Leer lassen wenn unbekannt.", + "beitraege_ag": "Arbeitgeber", + "abzuege_an": "Arbeitnehmer", + "ktv": "KTV", + "bu": "BU", + "nbu": "NBU", + "section_ag": "Kosten Arbeitgeber", + "section_an": "Abzüge Arbeitnehmer", + "bruttolohn": "Bruttolohn", + "ahv_iv_eo": "AHV / IV / EO", + "alv": "ALV", + "fak": "FAK", + "vk": "Verwaltungskosten (VK)", + "total_beitraege_ag": "Total Beiträge Arbeitgeber", + "totalaufwand_ag": "Totalaufwand Arbeitgeber", + "total_abzuege_an": "Total Abzüge Arbeitnehmer", + "nettolohn": "Nettolohn", + "col_position": "Position", + "col_satz": "Satz", + "col_monat": "/ Monat", + "col_jahr": "/ Jahr", + "jahr": "Jahr", + "source_hint": "Quelle: Lohnbudget Monatslohn, Bundesamt für Sozialversicherungen (BSV). Gilt für das ordentliche Abrechnungsverfahren." }, "dashboard": { "title": "Dashboard", diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index e844ffa..5336352 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -144,7 +144,67 @@ "calendar": "Calendar", "accounts": "Accounts", "revenue_accounts": "Revenue Accounts", - "transactions": "Transactions" + "transactions": "Transactions", + "salary": "Salary", + "salarium": "Salarium", + "salary_analyse": "Analysis", + "salary_entwicklung": "Development" + }, + "salarium": { + "title": "Salarium", + "subtitle": "Statistical salary calculator by the Federal Statistical Office (FSO).", + "open_external": "Open in new tab" + }, + "salary_analyse": { + "title": "Salary Analysis", + "subtitle": "Compare your current salary with the market average.", + "coming_soon_title": "Salary Analysis in Development", + "coming_soon_text": "Here you will be able to compare your salary with industry and regional benchmarks." + }, + "salary_entwicklung": { + "title": "Salary Development", + "subtitle": "Track your salary development over the years.", + "coming_soon_title": "Salary Development in Development", + "coming_soon_text": "Visualize your salary history and identify trends over time." + }, + "lohn_analyse": { + "title": "Salary Analysis", + "subtitle": "Calculate gross and net salary as well as the total employer cost under Swiss law.", + "section_basics": "Basics", + "label_monatslohn": "Monthly Salary", + "label_monate": "Number of Months", + "monate": "Months", + "label_kanton": "Canton", + "fak_rate_hint": "FAK contribution rate:", + "label_verfahren": "Billing Method", + "verfahren_ordentlich": "Standard Method", + "verfahren_vereinfacht": "Simplified Method", + "verfahren_quellensteuer": "Standard with Withholding Tax", + "verfahren_hint": "This method is not yet fully calculated — standard rates are used.", + "section_optional": "Additional Rates (KTV / BU / NBU)", + "optional_hint": "KTV and accident insurance rates depend on the employer. Leave empty if unknown.", + "beitraege_ag": "Employer", + "abzuege_an": "Employee", + "ktv": "KTV", + "bu": "BU", + "nbu": "NBU", + "section_ag": "Employer Costs", + "section_an": "Employee Deductions", + "bruttolohn": "Gross Salary", + "ahv_iv_eo": "AHV / IV / EO", + "alv": "ALV", + "fak": "FAK", + "vk": "Admin Costs (VK)", + "total_beitraege_ag": "Total Employer Contributions", + "totalaufwand_ag": "Total Employer Cost", + "total_abzuege_an": "Total Employee Deductions", + "nettolohn": "Net Salary", + "col_position": "Position", + "col_satz": "Rate", + "col_monat": "/ Month", + "col_jahr": "/ Year", + "jahr": "Year", + "source_hint": "Source: Monthly Salary Budget, Federal Social Insurance Office (FSIO). Applies to the standard billing method." }, "dashboard": { "title": "Dashboard", diff --git a/frontend/src/assets/i18n/fr.json b/frontend/src/assets/i18n/fr.json index 949a23f..7d48bb7 100644 --- a/frontend/src/assets/i18n/fr.json +++ b/frontend/src/assets/i18n/fr.json @@ -144,7 +144,67 @@ "calendar": "Calendrier", "accounts": "Comptes", "revenue_accounts": "Comptes de revenus", - "transactions": "Transactions" + "transactions": "Transactions", + "salary": "Salaire", + "salarium": "Salarium", + "salary_analyse": "Analyse", + "salary_entwicklung": "Évolution" + }, + "salarium": { + "title": "Salarium", + "subtitle": "Calculateur de salaire statistique de l'Office fédéral de la statistique (OFS).", + "open_external": "Ouvrir dans un nouvel onglet" + }, + "salary_analyse": { + "title": "Analyse salariale", + "subtitle": "Comparez votre salaire actuel avec la moyenne du marché.", + "coming_soon_title": "Analyse salariale en développement", + "coming_soon_text": "Vous pourrez ici comparer votre salaire avec les données sectorielles et régionales." + }, + "salary_entwicklung": { + "title": "Évolution salariale", + "subtitle": "Suivez l'évolution de votre salaire au fil des années.", + "coming_soon_title": "Évolution salariale en développement", + "coming_soon_text": "Visualisez votre historique salarial et identifiez les tendances au fil du temps." + }, + "lohn_analyse": { + "title": "Analyse salariale", + "subtitle": "Calculez le salaire brut, net et le coût total de l'employeur selon le droit suisse.", + "section_basics": "Données de base", + "label_monatslohn": "Salaire mensuel", + "label_monate": "Nombre de mois", + "monate": "mois", + "label_kanton": "Canton", + "fak_rate_hint": "Taux de cotisation CAF :", + "label_verfahren": "Procédure de décompte", + "verfahren_ordentlich": "Procédure ordinaire", + "verfahren_vereinfacht": "Procédure simplifiée", + "verfahren_quellensteuer": "Procédure ordinaire avec impôt à la source", + "verfahren_hint": "Cette procédure n'est pas encore entièrement calculée — les taux standard sont utilisés.", + "section_optional": "Taux supplémentaires (IJM / AA)", + "optional_hint": "Les taux IJM et accidents dépendent de l'employeur. Laisser vide si inconnu.", + "beitraege_ag": "Employeur", + "abzuege_an": "Employé", + "ktv": "IJM", + "bu": "AA pro.", + "nbu": "AA non-pro.", + "section_ag": "Coûts employeur", + "section_an": "Déductions employé", + "bruttolohn": "Salaire brut", + "ahv_iv_eo": "AVS / AI / APG", + "alv": "AC", + "fak": "CAF", + "vk": "Frais admin. (VK)", + "total_beitraege_ag": "Total cotisations employeur", + "totalaufwand_ag": "Coût total employeur", + "total_abzuege_an": "Total déductions employé", + "nettolohn": "Salaire net", + "col_position": "Position", + "col_satz": "Taux", + "col_monat": "/ Mois", + "col_jahr": "/ An", + "jahr": "An", + "source_hint": "Source : Budget salaire mensuel, Office fédéral des assurances sociales (OFAS). Valable pour la procédure de décompte ordinaire." }, "dashboard": { "title": "Tableau de bord", diff --git a/frontend/src/assets/i18n/it.json b/frontend/src/assets/i18n/it.json index 2774c62..dc31984 100644 --- a/frontend/src/assets/i18n/it.json +++ b/frontend/src/assets/i18n/it.json @@ -144,7 +144,67 @@ "calendar": "Calendario", "accounts": "Conti", "revenue_accounts": "Conti entrate", - "transactions": "Transazioni" + "transactions": "Transazioni", + "salary": "Stipendio", + "salarium": "Salarium", + "salary_analyse": "Analisi", + "salary_entwicklung": "Sviluppo" + }, + "salarium": { + "title": "Salarium", + "subtitle": "Calcolatore statistico degli stipendi dell'Ufficio federale di statistica (UST).", + "open_external": "Apri in una nuova scheda" + }, + "salary_analyse": { + "title": "Analisi stipendio", + "subtitle": "Confronta il tuo stipendio attuale con la media di mercato.", + "coming_soon_title": "Analisi stipendio in sviluppo", + "coming_soon_text": "Qui potrai confrontare il tuo stipendio con i dati del settore e della regione." + }, + "salary_entwicklung": { + "title": "Sviluppo stipendio", + "subtitle": "Monitora lo sviluppo del tuo stipendio nel tempo.", + "coming_soon_title": "Sviluppo stipendio in sviluppo", + "coming_soon_text": "Visualizza la tua storia salariale e identifica le tendenze nel tempo." + }, + "lohn_analyse": { + "title": "Analisi stipendio", + "subtitle": "Calcola lo stipendio lordo, netto e il costo totale del datore di lavoro secondo il diritto svizzero.", + "section_basics": "Dati di base", + "label_monatslohn": "Stipendio mensile", + "label_monate": "Numero di mesi", + "monate": "mesi", + "label_kanton": "Cantone", + "fak_rate_hint": "Aliquota CAF:", + "label_verfahren": "Procedura di conteggio", + "verfahren_ordentlich": "Procedura ordinaria", + "verfahren_vereinfacht": "Procedura semplificata", + "verfahren_quellensteuer": "Procedura ordinaria con imposta alla fonte", + "verfahren_hint": "Questa procedura non è ancora completamente calcolata — vengono utilizzate le aliquote standard.", + "section_optional": "Aliquote aggiuntive (IJM / LAINF)", + "optional_hint": "Le aliquote IJM e infortuni dipendono dal datore di lavoro. Lasciare vuoto se sconosciuto.", + "beitraege_ag": "Datore di lavoro", + "abzuege_an": "Lavoratore", + "ktv": "IJM", + "bu": "LAINF pro.", + "nbu": "LAINF non-pro.", + "section_ag": "Costi datore di lavoro", + "section_an": "Deduzioni lavoratore", + "bruttolohn": "Stipendio lordo", + "ahv_iv_eo": "AVS / AI / IPG", + "alv": "AD", + "fak": "CAF", + "vk": "Spese amm. (VK)", + "total_beitraege_ag": "Totale contributi datore di lavoro", + "totalaufwand_ag": "Costo totale datore di lavoro", + "total_abzuege_an": "Totale deduzioni lavoratore", + "nettolohn": "Stipendio netto", + "col_position": "Posizione", + "col_satz": "Aliquota", + "col_monat": "/ Mese", + "col_jahr": "/ Anno", + "jahr": "Anno", + "source_hint": "Fonte: Budget stipendio mensile, Ufficio federale delle assicurazioni sociali (UFAS). Valido per la procedura di conteggio ordinaria." }, "dashboard": { "title": "Dashboard",