Production deployment setup + feature complete

- Dockerfile + deploy.sh for Hetzner server
- Email verification via Better Auth + Resend
- Invite code flow (6-digit OTP, generate/join)
- Settlement share percent fix (payer vs debtor)
- OCR scanner fixes (date display, retry, viewfinder)
- app.json icon/splash/adaptive-icon configured
- iOS deployment target 15.5 (ML Kit requirement)
- DB migration 0014: household_invitations table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
René Schober
2026-03-20 11:54:22 +01:00
parent 4e34270786
commit 9ddc7c6d7a
194 changed files with 55961 additions and 305 deletions

View File

@@ -0,0 +1,18 @@
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import * as Localization from 'expo-localization'
import de from './locales/de.json'
import en from './locales/en.json'
const deviceLanguage = Localization.getLocales()[0]?.languageCode ?? 'de'
i18n
.use(initReactI18next)
.init({
resources: { de: { translation: de }, en: { translation: en } },
lng: deviceLanguage,
fallbackLng: 'de',
interpolation: { escapeValue: false },
})
export default i18n

View File

@@ -0,0 +1,443 @@
{
"common": {
"save": "Speichern",
"cancel": "Abbrechen",
"delete": "Löschen",
"edit": "Bearbeiten",
"add": "Hinzufügen",
"close": "Schließen",
"back": "Zurück",
"loading": "Lädt...",
"error": "Fehler",
"confirm": "Bestätigen",
"currency": "€",
"next": "Weiter",
"create": "Erstellen",
"book": "Buchen",
"yes": "Ja",
"no": "Nein",
"or": "oder",
"new": "Neu",
"today": "Heute",
"preview": "Vorschau",
"notice": "Hinweis",
"monthly": "monatlich",
"select": "Wählen…"
},
"tabs": {
"household": "Haushalt",
"me": "Ich",
"children": "Kinder",
"shopping": "Einkauf",
"more": "Mehr"
},
"mehr": {
"vacation": "Urlaub",
"vacationSubtitle": "Reisebudget & Ausgaben",
"settingsSubtitle": "Fixkosten, Kategorien, Haushalt"
},
"household": {
"title": "Haushalt",
"income": "Einnahmen",
"expenses": "Ausgaben",
"balance": "Bilanz",
"all": "Alle",
"noTransactions": "Noch keine Buchungen",
"noTransactionsHint": "Tippe auf + um eine gemeinsame Ausgabe einzutragen",
"nettoMonth": "Netto Monat",
"settlement": {
"youOwe": "Du schuldest {{name}}",
"theyOwe": "{{name}} schuldet dir",
"allSettled": "✓ Alles beglichen",
"book": "Buchen",
"alreadyTransferred": "Bereits überwiesen",
"monthlySettlement": "Monatsabrechnung",
"householdExpenses": "Haushalt Ausgaben",
"householdIncome": "Haushalt Einnahmen",
"yourShare": "Dein Anteil ({{percent}}%)",
"paidBy": "{{name}} gezahlt",
"fixedTransfers": "Feste Überweisungen",
"toTransfer": "Zu überweisen",
"closeMonth": "Monat abschließen",
"closed": "Abgeschlossen",
"recordTransfer": "Überweisung buchen",
"transferAmount": "Überwiesener Betrag",
"notePlaceholder": "Notiz (optional)"
}
},
"me": {
"title": "Ich",
"noTransactions": "Noch keine privaten Buchungen",
"noTransactionsHint": "Nur du siehst diese Einträge — niemand sonst im Haushalt"
},
"children": {
"title": "Kinder",
"addChild": "Kind hinzufügen",
"noChildren": "Noch keine Kinder angelegt",
"noChildrenHint": "Lege ein Kind an, um Ausgaben separat zu verfolgen.",
"noTransactions": "Noch keine Buchungen für {{name}}",
"noTransactionsHint": "Tippe auf + um die erste Buchung einzutragen"
},
"shopping": {
"title": "Einkaufsliste",
"empty": "Noch nichts auf der Liste",
"emptyHint": "Füge dein erstes Produkt unten hinzu",
"placeholder": "Produkt hinzufügen…",
"deleteChecked": "Erledigt löschen",
"offline": "offline",
"checkedBy": "von {{name}}",
"deleteCheckedConfirm": "Alle erledigten Items löschen?",
"reconnecting": "Verbindung wird hergestellt…",
"quantityPlaceholder": "Menge (optional)"
},
"debts": {
"title": "Schulden & Kredite",
"new": "+ Neu",
"open": "{{amount}} offen",
"payRate": "Rate buchen",
"noDebts": "Keine offenen Schulden",
"rateAutoBooked": "Diese Rate wird automatisch als private Ausgabe gebucht.",
"addTitle": "Schuld erfassen",
"totalAmount": "Gesamtbetrag",
"labelRequired": "Bezeichnung *",
"labelPlaceholder": "z.B. Autokredit",
"iOweMoneyTo": "Ich schulde das Geld…",
"selectMember": "Haushaltsmitglied wählen",
"orEnterName": "…oder Name eingeben (z.B. Sparkasse)",
"noteOptional": "Notiz (optional)",
"notePlaceholder": "z.B. Laufzeit bis 2026",
"remaining": "Noch offen: {{amount}}",
"overpayingWarning": "Betrag übersteigt den offenen Restbetrag",
"paid": "Bezahlt",
"total": "Gesamt",
"openAmount": "Noch offen",
"remainingLabel": "{{amount}} offen",
"toggleClosed_show": "{{count}} abgeschlossene{{plural}} anzeigen",
"toggleClosed_hide": "{{count}} abgeschlossene{{plural}} ausblenden",
"claims": "Offene Forderungen",
"received": "Erhalten",
"pendingLabel": "Ausstehend",
"fullyRepaid": "Vollständig zurückgezahlt ✓",
"noDebtsEntered": "Keine Schulden eingetragen.",
"fromDebtor": "von {{name}} · {{amount}} offen",
"unknown": "Unbekannt"
},
"fixedCosts": {
"title": "Fixkosten",
"household": "Haushalt",
"me": "Ich",
"children": "Kinder",
"expense": "Ausgabe · monatlich",
"income": "Einnahme · monatlich",
"noItems": "Keine Fixkosten eingetragen",
"editTitle": "Fixkosten bearbeiten",
"addTitle": "Neue Fixkosten",
"labelRequired": "Bezeichnung *",
"labelPlaceholder": "z.B. Miete",
"categoryOptional": "Kategorie (optional)",
"pauseTitle": "Fixkosten pausieren",
"pauseMessage": "\"{{label}}\" wird pausiert und nicht mehr monatlich gebucht.",
"pause": "Pausieren",
"expenseType": "Ausgabe",
"incomeType": "Einnahme"
},
"settings": {
"title": "Einstellungen",
"householdPartner": "Haushalt & Partner",
"fixedCosts": "Fixkosten verwalten",
"transferItems": "Feste Überweisungsposten",
"categories": "Kategorien",
"language": "Sprache",
"languageAuto": "Automatisch (Gerätesprache)",
"languageDe": "Deutsch",
"languageEn": "English",
"logout": "Abmelden",
"members": "Mitglieder",
"pending": "Ausstehend",
"account": "Konto",
"households": "Haushalte",
"youSuffix": "(du)",
"invitePerson": "Person einladen",
"invite": "Einladen",
"emailLabel": "E-Mail-Adresse",
"emailPlaceholder": "person@beispiel.de",
"inviteHint": "Die Person erhält eine E-Mail mit einem Einladungslink.",
"inviteSent": "Einladung gesendet",
"inviteError": "Fehler beim Einladen",
"revokeTitle": "Einladung widerrufen",
"revokeMessage": "Einladung an {{email}} widerrufen?",
"revoke": "Widerrufen",
"revokeSuccess": "Einladung widerrufen",
"saveError": "Einstellungen konnten nicht gespeichert werden.",
"switchedTo": "Zu {{name}} gewechselt",
"appSection": "App",
"household": {
"title": "Haushalt & Partner",
"yourName": "Dein Name",
"partnerName": "Partner / Partnerin",
"sharePercent": "Dein Anteil",
"sharePreview": "Du zahlst {{own}}% · {{partner}} zahlt {{rest}}%",
"monthlyBudget": "Monatsbudget",
"splitChildren": "Kinderkosten teilen",
"currency": "Währung",
"namesSection": "Namen",
"payerSection": "Wer zahlt die Ausgaben vor?",
"payerHint": "Diese Person schießt alle Haushaltsausgaben vor. Der Partner überweist am Monatsende seinen Anteil.",
"costSplitSection": "Kostenaufteilung",
"costSplitHint": "Dein Anteil an gemeinsamen Haushaltskosten",
"settingsSection": "Einstellungen",
"currencyOnlyEur": "Derzeit wird nur EUR unterstützt."
}
},
"monthClose": {
"title": "Monatsabschluss {{month}}",
"overview": "Übersicht",
"householdTotal": "Haushalt gesamt",
"householdIncome": "Haushalt Einnahmen",
"yourShare": "Dein Anteil ({{percent}}%)",
"totalTransfer": "Gesamte Überweisung",
"alreadyTransferred": "Bereits überwiesen",
"receives": "{{name}} bekommt noch",
"youReceive": "Du bekommst noch",
"settled": "Alles ausgeglichen",
"adjustAmount": "Betrag anpassen (optional)",
"adjustHint": "Falls ihr euch auf einen gerundeten Betrag geeinigt habt.",
"note": "Notiz (optional)",
"notePlaceholder": "z.B. Abschluss März — per Dauerauftrag",
"closeButton": "Monat abschließen & sperren",
"closeConfirmTitle": "{{month}} abschließen?",
"closeConfirmMessage": "Dieser Monat wird gesperrt. Keine weiteren Buchungen oder Änderungen möglich.",
"closeConfirmAction": "Jetzt abschließen",
"closedBanner": "🔒 Abgeschlossen am {{date}}"
},
"onboarding": {
"welcome": "Willkommen bei HausApp",
"subtitle": "Deine persönliche Haushalts-App für gemeinsame Finanzen",
"start": "Los geht's",
"step": "Schritt {{current}} von {{total}}",
"yourName": "Wie heißt du?",
"yourNamePlaceholder": "Dein Name",
"partnerName": "Wie heißt dein Partner / deine Partnerin?",
"partnerNamePlaceholder": "Name des Partners",
"costSplit": "Wie viel zahlst du von den gemeinsamen Kosten?",
"preview": "Du zahlst {{own}}% · {{partner}} zahlt {{rest}}%",
"done": "✓ Alles eingerichtet!",
"doneHint": "Du kannst diese Einstellungen jederzeit unter Einstellungen → Haushalt ändern.",
"startApp": "App starten",
"skip": "Überspringen",
"createHousehold": "Haushalt erstellen",
"joinHousehold": "Einladungslink eingeben",
"setupTitle": "Haushalt einrichten",
"setupSubtitle": "Erstelle deinen Haushalt oder tritt einem bestehenden bei",
"householdNameLabel": "Haushaltsname",
"householdNamePlaceholder": "z.B. Familie Müller",
"enterHouseholdName": "Bitte einen Haushaltsnamen eingeben",
"createError": "Haushalt konnte nicht erstellt werden",
"enterInviteCode": "Bitte einen Einladungscode eingeben",
"invitesComingSoon": "Einladungen werden in Kürze unterstützt",
"inviteCodeLabel": "Einladungscode",
"inviteCodePlaceholder": "Einladungscode eingeben",
"joinHouseholdAction": "Einladung annehmen"
},
"setup": {
"namesTitle": "Wie heißt ihr?",
"namesHint": "Diese Namen erscheinen in der Abrechnung und bei Schulden.",
"costSplitTitle": "Kostenaufteilung",
"costSplitHint": "Wie viel der gemeinsamen Haushaltskosten zahlst du?",
"monthlyBudgetLabel": "Gemeinsames Monatsbudget (variabel)",
"splitChildCostsLabel": "Kinderkosten gleich aufteilen?"
},
"vacation": {
"title": "Urlaub",
"comingSoon": "Bald verfügbar",
"comingSoonHint": "Urlaubsbudgets und Reiseausgaben — kommt in einer späteren Version."
},
"trips": {
"title": "Urlaub",
"new": "Neuer Urlaub",
"active": "Aktiv",
"past": "Vergangen",
"budget": "Budget",
"spent": "Ausgegeben",
"remaining": "Verbleibend",
"noTrips": "Noch kein Urlaub geplant",
"noTripsHint": "Tippe auf + um einen Urlaub anzulegen",
"overBudget": "Budget überschritten um {{amount}}",
"paidBy": "Gezahlt von {{name}}",
"complete": "Abschließen",
"completed": "Abgeschlossen",
"destination": "Reiseziel",
"startDate": "Von",
"endDate": "Bis",
"name": "Name",
"newExpense": "Neue Ausgabe",
"label": "Bezeichnung",
"note": "Notiz (optional)",
"categories": {
"unterkunft": "Unterkunft",
"essen": "Essen",
"transport": "Transport",
"aktivitaeten": "Aktivitäten",
"sonstiges": "Sonstiges"
},
"settlement": {
"title": "Abrechnung",
"total": "Gesamtausgaben",
"fairShare": "Fairer Anteil (50%)",
"paid": "gezahlt",
"owes": "{{from}} schuldet {{to}}",
"balanced": "Ausgeglichen — niemand schuldet was",
"closeTrip": "Urlaub abschließen",
"closedBanner": "Abgeschlossen",
"settledInfo": "{{from}} hat {{to}} {{amount}} überwiesen",
"noExpenses": "Füge zuerst Ausgaben hinzu"
}
},
"login": {
"welcome": "Willkommen zurück",
"subtitle": "Melde dich in deinem Konto an",
"fillAllFields": "Bitte alle Felder ausfüllen",
"signInError": "Anmeldung fehlgeschlagen",
"emailLabel": "E-Mail",
"emailPlaceholder": "deine@email.de",
"passwordLabel": "Passwort",
"passwordPlaceholder": "••••••••",
"signIn": "Anmelden",
"signInWithApple": "Mit Apple anmelden",
"noAccount": "Noch kein Konto?",
"register": "Registrieren",
"forgotPassword": "Passwort vergessen?",
"appleSignInError": "Apple-Anmeldung fehlgeschlagen"
},
"forgotPassword": {
"title": "Passwort vergessen?",
"subtitle": "Wir schicken dir einen Link zum Zurücksetzen deines Passworts.",
"sendButton": "Link senden",
"sentTitle": "E-Mail verschickt!",
"sentHint": "Check deine E-Mails — wir haben dir einen Link geschickt."
},
"resetPassword": {
"title": "Neues Passwort",
"subtitle": "Wähle ein sicheres Passwort mit mindestens 8 Zeichen.",
"newPassword": "Neues Passwort",
"confirmPassword": "Passwort bestätigen",
"mismatch": "Passwörter stimmen nicht überein",
"saveButton": "Passwort speichern",
"successMessage": "✓ Passwort geändert — du wirst weitergeleitet."
},
"categories": {
"editTitle": "Kategorie bearbeiten",
"addTitle": "Neue Kategorie",
"nameLabel": "Name",
"namePlaceholder": "z.B. Fitnessstudio",
"colorLabel": "Farbe",
"iconLabel": "Icon",
"selectIcon": "Icon wählen",
"defaultWarning": "Standardkategorien können umbenannt, aber nicht gelöscht werden.",
"default": "Standard",
"deleteTitle": "Kategorie löschen",
"deleteMessage": "\"{{name}}\" wirklich löschen?",
"addExpenseCategory": "+ Ausgaben-Kategorie hinzufügen",
"addIncomeCategory": "+ Einnahmen-Kategorie hinzufügen",
"expenseSection": "Ausgaben",
"incomeSection": "Einnahmen",
"expenseType": "Ausgabe",
"incomeType": "Einnahme"
},
"transferItems": {
"title": "Feste Überweisungsposten",
"addTitle": "Neuer Posten",
"monthlyFixedAmount": "Monatlicher Fixbetrag",
"labelRequired": "Bezeichnung *",
"labelPlaceholder": "z.B. Bausparer Noah",
"hint": "Diese Posten werden monatlich zur Haushaltsabrechnung addiert (z.B. Bausparer, Handy).",
"removeTitle": "Posten entfernen",
"removeMessage": "\"{{label}}\" wird aus der monatlichen Abrechnung entfernt.",
"remove": "Entfernen",
"empty": "Noch keine festen Posten eingetragen.",
"totalMonthly": "Gesamt monatlich",
"new": "Neu"
},
"carryOver": {
"title": "Saldo übertragen",
"confirmMessage": "Saldo von {{balance}} als {{type}} in {{month}} übertragen?",
"transfer": "Übertragen",
"openBalance": "{{month}} — offener Saldo",
"transferring": "Wird übertragen…",
"transferButton": "Saldo in {{month}} übertragen",
"expense": "Ausgabe",
"income": "Einnahme"
},
"scanner": {
"title": "Bon scannen",
"scanReceipt": "Bon scannen",
"manualEntry": "Manuelle Eingabe",
"hint": "Kassenbon in den Rahmen halten",
"capture": "Foto aufnehmen",
"scanning": "Wird erkannt...",
"detected": "Erkannt ✓",
"retry": "Nochmal scannen",
"book": "Buchen",
"permissionDenied": "Kamera-Zugriff verweigert. Bitte in den Einstellungen aktivieren.",
"openSettings": "Einstellungen öffnen",
"notRecognized": "Betrag konnte nicht erkannt werden.",
"merchant": "Händler",
"amount": "Betrag",
"date": "Datum",
"category": "Kategorie",
"scope": "Bereich",
"household": "Haushalt",
"private": "Privat",
"error": "Fehler beim Scannen. Bitte erneut versuchen."
},
"invite": {
"title": "Person einladen",
"shareText": "Ich lade dich zu HausApp ein! Gib diesen Code in der App ein: {{code}} (gültig 24h)",
"validFor": "Gültig für 24 Stunden",
"copyCode": "Code kopieren",
"copied": "Kopiert!",
"share": "Teilen",
"newCode": "Neuen Code generieren",
"joinTitle": "Einladungscode",
"joinHint": "Gib den 6-stelligen Code ein den du erhalten hast:",
"joinButton": "Haushalt beitreten",
"invalidCode": "Ungültiger oder abgelaufener Code",
"alreadyMember": "Du bist bereits Mitglied dieses Haushalts",
"success": "Willkommen im Haushalt!",
"setupTitle": "Haushalt einrichten",
"createNew": "Neuen Haushalt erstellen",
"createNewSub": "Du richtest alles ein",
"enterCode": "Einladungscode eingeben",
"enterCodeSub": "Du wurdest eingeladen",
"generating": "Wird generiert..."
},
"transaction": {
"booking": "Buchung",
"bookingType": "Buchungstyp",
"expense": "Ausgabe",
"income": "Einnahme",
"category": "Kategorie",
"description": "Beschreibung",
"date": "Datum",
"deleteTitle": "Buchung löschen?",
"deleteMessage": "Diese Buchung wird unwiderruflich gelöscht.",
"deleteFixed": "Diese Fixkostenbuchung wird nur für diesen Monat gelöscht. Im nächsten Monat wird sie wieder automatisch erstellt.",
"deleteDebt": "Diese Rate wird auch aus Schulden & Kredite entfernt.",
"fixedWarning": "Das ist eine Fixkostenbuchung. Änderungen gelten nur für diesen Monat.",
"carryOver": "Übertrag",
"newBooking": "Neue Buchung",
"editTitle": "Buchung bearbeiten",
"selectCategory": "Kategorie wählen (optional)",
"descriptionOptional": "Beschreibung (optional)",
"repeatMonthly": "Jeden Monat wiederholen",
"addNewCategory": "Neue Kategorie anlegen"
},
"verifyEmail": {
"title": "E-Mail bestätigen",
"hint": "Wir haben dir eine Bestätigungs-E-Mail geschickt an:",
"resend": "E-Mail erneut senden",
"resentConfirm": "✓ E-Mail wurde erneut gesendet",
"resendError": "Fehler beim Senden der E-Mail",
"backToLogin": "Zurück zur Anmeldung"
}
}

View File

@@ -0,0 +1,443 @@
{
"common": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"close": "Close",
"back": "Back",
"loading": "Loading...",
"error": "Error",
"confirm": "Confirm",
"currency": "€",
"next": "Next",
"create": "Create",
"book": "Book",
"yes": "Yes",
"no": "No",
"or": "or",
"new": "New",
"today": "Today",
"preview": "Preview",
"notice": "Notice",
"monthly": "monthly",
"select": "Select…"
},
"tabs": {
"household": "Household",
"me": "Me",
"children": "Kids",
"shopping": "Shopping",
"more": "More"
},
"mehr": {
"vacation": "Vacation",
"vacationSubtitle": "Travel budget & expenses",
"settingsSubtitle": "Fixed costs, categories, household"
},
"household": {
"title": "Household",
"income": "Income",
"expenses": "Expenses",
"balance": "Balance",
"all": "All",
"noTransactions": "No transactions yet",
"noTransactionsHint": "Tap + to add a shared expense",
"nettoMonth": "Net Month",
"settlement": {
"youOwe": "You owe {{name}}",
"theyOwe": "{{name}} owes you",
"allSettled": "✓ All settled",
"book": "Book",
"alreadyTransferred": "Already transferred",
"monthlySettlement": "Monthly settlement",
"householdExpenses": "Household expenses",
"householdIncome": "Household income",
"yourShare": "Your share ({{percent}}%)",
"paidBy": "{{name}} paid",
"fixedTransfers": "Fixed transfers",
"toTransfer": "To transfer",
"closeMonth": "Close month",
"closed": "Closed",
"recordTransfer": "Record transfer",
"transferAmount": "Transfer amount",
"notePlaceholder": "Note (optional)"
}
},
"me": {
"title": "Me",
"noTransactions": "No private transactions yet",
"noTransactionsHint": "Only you can see these — nobody else in the household"
},
"children": {
"title": "Kids",
"addChild": "Add child",
"noChildren": "No children added yet",
"noChildrenHint": "Add a child to track expenses separately.",
"noTransactions": "No transactions for {{name}} yet",
"noTransactionsHint": "Tap + to add the first transaction"
},
"shopping": {
"title": "Shopping List",
"empty": "Nothing on the list yet",
"emptyHint": "Add your first item below",
"placeholder": "Add item…",
"deleteChecked": "Delete checked",
"offline": "offline",
"checkedBy": "by {{name}}",
"deleteCheckedConfirm": "Delete all checked items?",
"reconnecting": "Reconnecting…",
"quantityPlaceholder": "Quantity (optional)"
},
"debts": {
"title": "Debts & Loans",
"new": "+ New",
"open": "{{amount}} remaining",
"payRate": "Book payment",
"noDebts": "No open debts",
"rateAutoBooked": "This payment will automatically be booked as a private expense.",
"addTitle": "Record debt",
"totalAmount": "Total amount",
"labelRequired": "Label *",
"labelPlaceholder": "e.g. Car loan",
"iOweMoneyTo": "I owe the money to…",
"selectMember": "Select household member",
"orEnterName": "…or enter name (e.g. Bank)",
"noteOptional": "Note (optional)",
"notePlaceholder": "e.g. Term until 2026",
"remaining": "Remaining: {{amount}}",
"overpayingWarning": "Amount exceeds the open remaining balance",
"paid": "Paid",
"total": "Total",
"openAmount": "Remaining",
"remainingLabel": "{{amount}} remaining",
"toggleClosed_show": "Show {{count}} closed",
"toggleClosed_hide": "Hide {{count}} closed",
"claims": "Open claims",
"received": "Received",
"pendingLabel": "Pending",
"fullyRepaid": "Fully repaid ✓",
"noDebtsEntered": "No debts recorded.",
"fromDebtor": "from {{name}} · {{amount}} remaining",
"unknown": "Unknown"
},
"fixedCosts": {
"title": "Fixed Costs",
"household": "Household",
"me": "Me",
"children": "Kids",
"expense": "Expense · monthly",
"income": "Income · monthly",
"noItems": "No fixed costs added",
"editTitle": "Edit fixed cost",
"addTitle": "New fixed cost",
"labelRequired": "Label *",
"labelPlaceholder": "e.g. Rent",
"categoryOptional": "Category (optional)",
"pauseTitle": "Pause fixed cost",
"pauseMessage": "\"{{label}}\" will be paused and no longer booked monthly.",
"pause": "Pause",
"expenseType": "Expense",
"incomeType": "Income"
},
"settings": {
"title": "Settings",
"householdPartner": "Household & Partner",
"fixedCosts": "Manage fixed costs",
"transferItems": "Fixed transfer items",
"categories": "Categories",
"language": "Language",
"languageAuto": "Automatic (device language)",
"languageDe": "Deutsch",
"languageEn": "English",
"logout": "Sign out",
"members": "Members",
"pending": "Pending",
"account": "Account",
"households": "Households",
"youSuffix": "(you)",
"invitePerson": "Invite person",
"invite": "Invite",
"emailLabel": "Email address",
"emailPlaceholder": "person@example.com",
"inviteHint": "The person will receive an email with an invitation link.",
"inviteSent": "Invitation sent",
"inviteError": "Error sending invitation",
"revokeTitle": "Revoke invitation",
"revokeMessage": "Revoke invitation for {{email}}?",
"revoke": "Revoke",
"revokeSuccess": "Invitation revoked",
"saveError": "Could not save settings.",
"switchedTo": "Switched to {{name}}",
"appSection": "App",
"household": {
"title": "Household & Partner",
"yourName": "Your name",
"partnerName": "Partner",
"sharePercent": "Your share",
"sharePreview": "You pay {{own}}% · {{partner}} pays {{rest}}%",
"monthlyBudget": "Monthly budget",
"splitChildren": "Split child costs",
"currency": "Currency",
"namesSection": "Names",
"payerSection": "Who pays expenses upfront?",
"payerHint": "This person pays all household expenses. The partner transfers their share at month end.",
"costSplitSection": "Cost split",
"costSplitHint": "Your share of shared household costs",
"settingsSection": "Settings",
"currencyOnlyEur": "Currently only EUR is supported."
}
},
"monthClose": {
"title": "Month close {{month}}",
"overview": "Overview",
"householdTotal": "Household total",
"householdIncome": "Household income",
"yourShare": "Your share ({{percent}}%)",
"totalTransfer": "Total transfer",
"alreadyTransferred": "Already transferred",
"receives": "{{name}} receives",
"youReceive": "You receive",
"settled": "All settled",
"adjustAmount": "Adjust amount (optional)",
"adjustHint": "In case you agreed on a rounded amount.",
"note": "Note (optional)",
"notePlaceholder": "e.g. March close — standing order",
"closeButton": "Close & lock month",
"closeConfirmTitle": "Close {{month}}?",
"closeConfirmMessage": "This month will be locked. No further bookings or changes possible.",
"closeConfirmAction": "Close now",
"closedBanner": "🔒 Closed on {{date}}"
},
"onboarding": {
"welcome": "Welcome to HausApp",
"subtitle": "Your personal household app for shared finances",
"start": "Get started",
"step": "Step {{current}} of {{total}}",
"yourName": "What's your name?",
"yourNamePlaceholder": "Your name",
"partnerName": "What's your partner's name?",
"partnerNamePlaceholder": "Partner's name",
"costSplit": "How much of the shared costs do you pay?",
"preview": "You pay {{own}}% · {{partner}} pays {{rest}}%",
"done": "✓ All set up!",
"doneHint": "You can change these settings anytime under Settings → Household.",
"startApp": "Start app",
"skip": "Skip",
"createHousehold": "Create household",
"joinHousehold": "Enter invitation link",
"setupTitle": "Set up household",
"setupSubtitle": "Create your household or join an existing one",
"householdNameLabel": "Household name",
"householdNamePlaceholder": "e.g. Smith Family",
"enterHouseholdName": "Please enter a household name",
"createError": "Could not create household",
"enterInviteCode": "Please enter an invitation code",
"invitesComingSoon": "Invitations will be supported soon",
"inviteCodeLabel": "Invitation code",
"inviteCodePlaceholder": "Enter invitation code",
"joinHouseholdAction": "Accept invitation"
},
"setup": {
"namesTitle": "What are your names?",
"namesHint": "These names appear in statements and debts.",
"costSplitTitle": "Cost split",
"costSplitHint": "How much of the shared household costs do you pay?",
"monthlyBudgetLabel": "Shared monthly budget (variable)",
"splitChildCostsLabel": "Split child costs equally?"
},
"vacation": {
"title": "Vacation",
"comingSoon": "Coming soon",
"comingSoonHint": "Vacation budgets and travel expenses — coming in a later version."
},
"trips": {
"title": "Vacation",
"new": "New trip",
"active": "Active",
"past": "Past",
"budget": "Budget",
"spent": "Spent",
"remaining": "Remaining",
"noTrips": "No trips planned yet",
"noTripsHint": "Tap + to add a trip",
"overBudget": "Over budget by {{amount}}",
"paidBy": "Paid by {{name}}",
"complete": "Complete",
"completed": "Completed",
"destination": "Destination",
"startDate": "From",
"endDate": "To",
"name": "Name",
"newExpense": "New expense",
"label": "Label",
"note": "Note (optional)",
"categories": {
"unterkunft": "Accommodation",
"essen": "Food",
"transport": "Transport",
"aktivitaeten": "Activities",
"sonstiges": "Other"
},
"settlement": {
"title": "Settlement",
"total": "Total expenses",
"fairShare": "Fair share (50%)",
"paid": "paid",
"owes": "{{from}} owes {{to}}",
"balanced": "Balanced — nobody owes anything",
"closeTrip": "Complete trip",
"closedBanner": "Completed",
"settledInfo": "{{from}} transferred {{amount}} to {{to}}",
"noExpenses": "Add expenses first"
}
},
"login": {
"welcome": "Welcome back",
"subtitle": "Sign in to your account",
"fillAllFields": "Please fill in all fields",
"signInError": "Sign in failed",
"emailLabel": "Email",
"emailPlaceholder": "your@email.com",
"passwordLabel": "Password",
"passwordPlaceholder": "••••••••",
"signIn": "Sign in",
"signInWithApple": "Sign in with Apple",
"noAccount": "Don't have an account?",
"register": "Register",
"forgotPassword": "Forgot password?",
"appleSignInError": "Apple sign-in failed"
},
"forgotPassword": {
"title": "Forgot password?",
"subtitle": "We'll send you a link to reset your password.",
"sendButton": "Send link",
"sentTitle": "Email sent!",
"sentHint": "Check your emails — we sent you a reset link."
},
"resetPassword": {
"title": "New password",
"subtitle": "Choose a secure password with at least 8 characters.",
"newPassword": "New password",
"confirmPassword": "Confirm password",
"mismatch": "Passwords don't match",
"saveButton": "Save password",
"successMessage": "✓ Password changed — redirecting you now."
},
"categories": {
"editTitle": "Edit category",
"addTitle": "New category",
"nameLabel": "Name",
"namePlaceholder": "e.g. Gym",
"colorLabel": "Color",
"iconLabel": "Icon",
"selectIcon": "Select icon",
"defaultWarning": "Default categories can be renamed but not deleted.",
"default": "Default",
"deleteTitle": "Delete category",
"deleteMessage": "Really delete \"{{name}}\"?",
"addExpenseCategory": "+ Add expense category",
"addIncomeCategory": "+ Add income category",
"expenseSection": "Expenses",
"incomeSection": "Income",
"expenseType": "Expense",
"incomeType": "Income"
},
"transferItems": {
"title": "Fixed transfer items",
"addTitle": "New item",
"monthlyFixedAmount": "Monthly fixed amount",
"labelRequired": "Label *",
"labelPlaceholder": "e.g. Savings plan Noah",
"hint": "These items are added monthly to the household statement (e.g. savings plans, phone).",
"removeTitle": "Remove item",
"removeMessage": "\"{{label}}\" will be removed from the monthly statement.",
"remove": "Remove",
"empty": "No fixed items added yet.",
"totalMonthly": "Total monthly",
"new": "New"
},
"carryOver": {
"title": "Transfer balance",
"confirmMessage": "Transfer balance of {{balance}} as {{type}} to {{month}}?",
"transfer": "Transfer",
"openBalance": "{{month}} — open balance",
"transferring": "Transferring…",
"transferButton": "Transfer balance to {{month}}",
"expense": "expense",
"income": "income"
},
"scanner": {
"title": "Scan Receipt",
"scanReceipt": "Scan Receipt",
"manualEntry": "Manual Entry",
"hint": "Hold receipt in frame",
"capture": "Take Photo",
"scanning": "Recognizing...",
"detected": "Detected ✓",
"retry": "Scan Again",
"book": "Book",
"permissionDenied": "Camera access denied. Please enable in settings.",
"openSettings": "Open Settings",
"notRecognized": "Could not recognize amount.",
"merchant": "Merchant",
"amount": "Amount",
"date": "Date",
"category": "Category",
"scope": "Scope",
"household": "Household",
"private": "Private",
"error": "Scan failed. Please try again."
},
"invite": {
"title": "Invite Person",
"shareText": "I'm inviting you to HausApp! Enter this code in the app: {{code}} (valid 24h)",
"validFor": "Valid for 24 hours",
"copyCode": "Copy code",
"copied": "Copied!",
"share": "Share",
"newCode": "Generate new code",
"joinTitle": "Invitation Code",
"joinHint": "Enter the 6-digit code you received:",
"joinButton": "Join Household",
"invalidCode": "Invalid or expired code",
"alreadyMember": "You are already a member of this household",
"success": "Welcome to the household!",
"setupTitle": "Set up household",
"createNew": "Create new household",
"createNewSub": "You set everything up",
"enterCode": "Enter invitation code",
"enterCodeSub": "You were invited",
"generating": "Generating..."
},
"transaction": {
"booking": "Booking",
"bookingType": "Type",
"expense": "Expense",
"income": "Income",
"category": "Category",
"description": "Description",
"date": "Date",
"deleteTitle": "Delete booking?",
"deleteMessage": "This booking will be permanently deleted.",
"deleteFixed": "This fixed cost booking will only be deleted for this month. It will be recreated automatically next month.",
"deleteDebt": "This payment will also be removed from Debts & Loans.",
"fixedWarning": "This is a fixed cost booking. Changes only apply to this month.",
"carryOver": "Carry over",
"newBooking": "New booking",
"editTitle": "Edit booking",
"selectCategory": "Select category (optional)",
"descriptionOptional": "Description (optional)",
"repeatMonthly": "Repeat every month",
"addNewCategory": "Add new category"
},
"verifyEmail": {
"title": "Verify your email",
"hint": "We sent a verification email to:",
"resend": "Resend email",
"resentConfirm": "✓ Email sent again",
"resendError": "Failed to send email",
"backToLogin": "Back to sign in"
}
}