Adds localization support across application views

Implements localization for dashboard, cash register, account, and profile sections

Adds localization keys for various UI elements, improving internationalization support
Refactors view components to use ILocalizationService for dynamic text rendering
Prepares ground for multi-language support with translation-ready markup
This commit is contained in:
Janus C. H. Knudsen 2026-01-12 15:42:18 +01:00
parent 1f400dcc6e
commit ef174af0e1
36 changed files with 821 additions and 263 deletions

View file

@ -24,10 +24,197 @@
"close": "Luk",
"delete": "Slet",
"edit": "Rediger",
"add": "Tilføj"
"add": "Tilføj",
"from": "Fra",
"to": "Til",
"all": "Alle",
"reset": "Nulstil",
"status": "Status"
},
"sidebar": {
"lockScreen": "Lås skærm",
"appName": "Salon OS"
},
"dashboard": {
"title": "Dashboard",
"subtitle": "Overblik over dagens aktivitet",
"stats": {
"bookingsToday": "Bookinger i dag",
"bookingsTrend": "4 gennemført, 2 i gang",
"expectedRevenue": "Forventet omsætning",
"revenueTrend": "+12% vs. gennemsnit",
"occupancyRate": "Belægningsgrad",
"occupancyTrend": "God kapacitet",
"needsAttention": "Kræver handling"
},
"ai": {
"header": "AI Analyse"
},
"bookings": {
"title": "Dagens bookinger",
"viewAll": "Se alle",
"currentTime": "Nu:",
"status": {
"confirmed": "Bekræftet",
"pending": "Afventer",
"inProgress": "I gang",
"completed": "Gennemført"
}
},
"notifications": {
"title": "Notifikationer",
"viewAll": "Se alle",
"markAllRead": "Marker alle som læst"
},
"attentions": {
"title": "Kræver opmærksomhed",
"viewAll": "Se alle"
},
"quickStats": {
"title": "Denne uge",
"bookings": "Bookinger",
"revenue": "Omsætning",
"newCustomers": "Nye kunder",
"cancellations": "Aflysninger",
"avgOccupancy": "Gns. belægning"
},
"quickActions": {
"title": "Hurtige handlinger",
"newBooking": "Ny booking",
"newCustomer": "Ny kunde"
},
"waitlist": {
"title": "Venteliste",
"count": "{count} venter"
}
},
"cash": {
"title": "Kasse",
"tabs": {
"overview": "Oversigt",
"reconciliation": "Kasseafstemning"
},
"stats": {
"reconciliationsInPeriod": "Afstemninger i periode",
"totalRevenue": "Total omsætning",
"cashSales": "Kontantsalg",
"totalDifference": "Samlet difference",
"transactionsToday": "Transaktioner i dag",
"revenueToday": "Omsætning i dag",
"lastReconciliation": "Sidste afstemning",
"openedRegister": "Åbnede kassen"
},
"filter": {
"register": "Kassepunkt",
"approved": "Godkendt",
"draft": "Kladde"
},
"table": {
"date": "Dato",
"id": "ID",
"period": "Periode",
"register": "Kassepunkt",
"closedBy": "Afsluttet af",
"revenue": "Omsætning",
"difference": "Difference",
"selected": "{count} valgt",
"noneSelected": "0 valgt",
"showingCount": "Viser {count} afstemninger",
"exportSaft": "Eksporter SAF-T",
"downloadCsv": "Download CSV",
"downloadPdf": "Download PDF",
"viewTransactions": "Se transaktioner"
},
"revenue": {
"title": "Periodens omsætning",
"subtitle": "Systemtal vs. kontrol",
"cardPayments": "Kortbetalinger",
"mobilePay": "MobilePay / Online",
"cashSales": "Kontantsalg",
"hint": "Kort og MobilePay afstemmes mod bank/indløser. Kontanter tælles op nedenfor."
},
"balance": {
"title": "Kontanter i kassen",
"startBalance": "Startbeholdning",
"startHint": "Overført fra sidste afstemning",
"payouts": "Udbetalinger / Bilag",
"payoutsHint": "Sammentæl bilag betalt kontant",
"toBank": "Udtaget til bank",
"toBankHint": "Kontanter lagt til side",
"expected": "Forventet kontantbeholdning",
"counted": "Optalt kontantbeholdning",
"countedHint": "Hvad ligger der faktisk i kassen?"
},
"difference": {
"title": "Kassedifference",
"match": "Kassen stemmer",
"over": "Overskud",
"under": "Underskud"
},
"period": {
"title": "Periodeoplysninger",
"dateRange": "Periode",
"register": "Kassepunkt",
"employee": "Medarbejder"
},
"note": {
"title": "Note til afstemning",
"placeholder": "Beskriv evt. årsag til difference..."
},
"approval": {
"title": "Afslut dagen",
"approvedBy": "Godkendt af (valgfrit)",
"selectPlaceholder": "Vælg...",
"confirmation": "Jeg bekræfter, at kassen er talt op, og at tallene er indtastet efter bedste evne.",
"saveDraft": "Gem som kladde",
"approve": "Godkend & lås"
},
"status": {
"draft": "Kladde",
"approved": "Godkendt"
},
"systemNote": "Systemet gemmer hvornår og af hvem der er godkendt enkelt kontrolspor."
},
"profile": {
"title": "Profil",
"myProfile": "Min profil",
"settings": "Indstillinger",
"darkMode": "Mørk tilstand",
"logout": "Log ud"
},
"account": {
"title": "Abonnement & Konto",
"subtitle": "Administrer dit abonnement og betalingsinfo",
"subscription": {
"title": "Dit abonnement",
"currentPlan": "Nuværende plan",
"switchTo": "Skift til {plan}",
"contactSales": "Kontakt salg",
"contactUs": "Kontakt os",
"pricePerMonth": "kr/md"
},
"billing": {
"title": "Betaling & Fakturaer"
},
"payment": {
"frequency": "Betalingsfrekvens",
"monthly": "Månedlig",
"yearly": "Årlig",
"nextPayment": "Næste betaling",
"amount": "Beløb",
"cardExpiry": "Kortudløb",
"change": "Skift",
"switchToYearly": "Skift til årlig betaling (spar 15%)"
},
"invoices": {
"title": "Faktura-historik",
"date": "Dato",
"invoiceNumber": "Fakturanr.",
"amount": "Beløb",
"download": "PDF",
"paid": "Betalt",
"pending": "Afventer",
"overdue": "Forfalden"
}
}
}

View file

@ -24,10 +24,197 @@
"close": "Close",
"delete": "Delete",
"edit": "Edit",
"add": "Add"
"add": "Add",
"from": "From",
"to": "To",
"all": "All",
"reset": "Reset",
"status": "Status"
},
"sidebar": {
"lockScreen": "Lock screen",
"appName": "Salon OS"
},
"dashboard": {
"title": "Dashboard",
"subtitle": "Overview of today's activity",
"stats": {
"bookingsToday": "Bookings today",
"bookingsTrend": "4 completed, 2 in progress",
"expectedRevenue": "Expected revenue",
"revenueTrend": "+12% vs. average",
"occupancyRate": "Occupancy rate",
"occupancyTrend": "Good capacity",
"needsAttention": "Needs attention"
},
"ai": {
"header": "AI Analysis"
},
"bookings": {
"title": "Today's bookings",
"viewAll": "View all",
"currentTime": "Now:",
"status": {
"confirmed": "Confirmed",
"pending": "Pending",
"inProgress": "In progress",
"completed": "Completed"
}
},
"notifications": {
"title": "Notifications",
"viewAll": "View all",
"markAllRead": "Mark all as read"
},
"attentions": {
"title": "Needs attention",
"viewAll": "View all"
},
"quickStats": {
"title": "This week",
"bookings": "Bookings",
"revenue": "Revenue",
"newCustomers": "New customers",
"cancellations": "Cancellations",
"avgOccupancy": "Avg. occupancy"
},
"quickActions": {
"title": "Quick actions",
"newBooking": "New booking",
"newCustomer": "New customer"
},
"waitlist": {
"title": "Waitlist",
"count": "{count} waiting"
}
},
"cash": {
"title": "Cash Register",
"tabs": {
"overview": "Overview",
"reconciliation": "Reconciliation"
},
"stats": {
"reconciliationsInPeriod": "Reconciliations in period",
"totalRevenue": "Total revenue",
"cashSales": "Cash sales",
"totalDifference": "Total difference",
"transactionsToday": "Transactions today",
"revenueToday": "Revenue today",
"lastReconciliation": "Last reconciliation",
"openedRegister": "Opened register"
},
"filter": {
"register": "Register",
"approved": "Approved",
"draft": "Draft"
},
"table": {
"date": "Date",
"id": "ID",
"period": "Period",
"register": "Register",
"closedBy": "Closed by",
"revenue": "Revenue",
"difference": "Difference",
"selected": "{count} selected",
"noneSelected": "0 selected",
"showingCount": "Showing {count} reconciliations",
"exportSaft": "Export SAF-T",
"downloadCsv": "Download CSV",
"downloadPdf": "Download PDF",
"viewTransactions": "View transactions"
},
"revenue": {
"title": "Period revenue",
"subtitle": "System vs. control",
"cardPayments": "Card payments",
"mobilePay": "MobilePay / Online",
"cashSales": "Cash sales",
"hint": "Card and MobilePay are reconciled against bank/acquirer. Cash is counted below."
},
"balance": {
"title": "Cash in register",
"startBalance": "Starting balance",
"startHint": "Carried over from last reconciliation",
"payouts": "Payouts / Receipts",
"payoutsHint": "Total receipts paid in cash",
"toBank": "Withdrawn to bank",
"toBankHint": "Cash set aside",
"expected": "Expected cash balance",
"counted": "Counted cash balance",
"countedHint": "What is actually in the register?"
},
"difference": {
"title": "Cash difference",
"match": "Register balanced",
"over": "Overage",
"under": "Shortage"
},
"period": {
"title": "Period information",
"dateRange": "Period",
"register": "Register",
"employee": "Employee"
},
"note": {
"title": "Reconciliation note",
"placeholder": "Describe reason for difference..."
},
"approval": {
"title": "Close the day",
"approvedBy": "Approved by (optional)",
"selectPlaceholder": "Select...",
"confirmation": "I confirm that the register has been counted and the figures have been entered to the best of my ability.",
"saveDraft": "Save as draft",
"approve": "Approve & lock"
},
"status": {
"draft": "Draft",
"approved": "Approved"
},
"systemNote": "The system records when and by whom approval was made simple audit trail."
},
"profile": {
"title": "Profile",
"myProfile": "My profile",
"settings": "Settings",
"darkMode": "Dark mode",
"logout": "Log out"
},
"account": {
"title": "Subscription & Account",
"subtitle": "Manage your subscription and payment info",
"subscription": {
"title": "Your subscription",
"currentPlan": "Current plan",
"switchTo": "Switch to {plan}",
"contactSales": "Contact sales",
"contactUs": "Contact us",
"pricePerMonth": "/mo"
},
"billing": {
"title": "Payment & Invoices"
},
"payment": {
"frequency": "Payment frequency",
"monthly": "Monthly",
"yearly": "Yearly",
"nextPayment": "Next payment",
"amount": "Amount",
"cardExpiry": "Card expiry",
"change": "Change",
"switchToYearly": "Switch to yearly billing (save 15%)"
},
"invoices": {
"title": "Invoice history",
"date": "Date",
"invoiceNumber": "Invoice no.",
"amount": "Amount",
"download": "PDF",
"paid": "Paid",
"pending": "Pending",
"overdue": "Overdue"
}
}
}