diff --git a/public/i18n.js b/public/i18n.js index b45a0fe..fc7f077 100644 --- a/public/i18n.js +++ b/public/i18n.js @@ -87,9 +87,11 @@ function isDateOnlyString(value) { return typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value); } +const VALID_DATE_FORMATS = ['mdy', 'dmy', 'ymd', 'mdy_dot', 'dmy_dot', 'dmy_slash', 'ymd_dot', 'ymd_slash']; + function getDateFormatPreference() { const stored = localStorage.getItem(DATE_FORMAT_KEY); - return ['mdy', 'dmy', 'ymd'].includes(stored) ? stored : DEFAULT_DATE_FORMAT; + return VALID_DATE_FORMATS.includes(stored) ? stored : DEFAULT_DATE_FORMAT; } export function getDateFormat() { @@ -113,7 +115,12 @@ function formatDateParts(date, useUtc = false) { const day = String(useUtc ? d.getUTCDate() : d.getDate()).padStart(2, '0'); switch (getDateFormatPreference()) { case 'dmy': return `${day}.${month}.${year}`; + case 'mdy_dot': return `${month}.${day}.${year}`; + case 'dmy_dot': return `${day}.${month}.${year}`; + case 'dmy_slash': return `${day}/${month}/${year}`; case 'ymd': return `${year}-${month}-${day}`; + case 'ymd_dot': return `${year}.${month}.${day}`; + case 'ymd_slash': return `${year}/${month}/${day}`; default: return `${month}/${day}/${year}`; } } @@ -140,7 +147,12 @@ export function formatDate(date) { export function dateInputPlaceholder() { switch (getDateFormatPreference()) { case 'dmy': return 'DD.MM.YYYY'; + case 'mdy_dot': return 'MM.DD.YYYY'; + case 'dmy_dot': return 'DD.MM.YYYY'; + case 'dmy_slash': return 'DD/MM/YYYY'; case 'ymd': return 'YYYY-MM-DD'; + case 'ymd_dot': return 'YYYY.MM.DD'; + case 'ymd_slash': return 'YYYY/MM/DD'; default: return 'MM/DD/YYYY'; } } @@ -157,11 +169,18 @@ export function parseDateInput(value) { const isoMatch = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/); if (isoMatch) return isValidDateParts(isoMatch[1], isoMatch[2], isoMatch[3]) ? raw : ''; + const ymdSeparatorMatch = raw.match(/^(\d{4})[\/.](\d{1,2})[\/.](\d{1,2})$/); + if (ymdSeparatorMatch && getDateFormatPreference().startsWith('ymd')) { + const [, year, month, day] = ymdSeparatorMatch; + if (!isValidDateParts(year, month, day)) return ''; + return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; + } + const slashMatch = raw.match(/^(\d{1,2})[\/.](\d{1,2})[\/.](\d{4})$/); if (!slashMatch) return ''; const [, first, second, year] = slashMatch; - const [month, day] = getDateFormatPreference() === 'dmy' + const [month, day] = getDateFormatPreference().startsWith('dmy') ? [second, first] : [first, second]; diff --git a/public/locales/ar.json b/public/locales/ar.json index 2ca8c8d..ff71833 100644 --- a/public/locales/ar.json +++ b/public/locales/ar.json @@ -112,7 +112,13 @@ "customizeMoveUp": "للأعلى", "customizeMoveDown": "للأسفل", "overdueTasksChip": "{{count}} مهمة متأخرة", - "overdueTasksChipPlural": "{{count}} مهام متأخرة" + "overdueTasksChipPlural": "{{count}} مهام متأخرة", + "customizeManage": "الأدوات", + "customizeExit": "إنهاء التخصيص", + "customizeDrag": "اسحب الأداة", + "customizeSize": "الحجم", + "customizeSizeFor": "حجم {{widget}}", + "customizeHide": "إخفاء {{widget}}" }, "tasks": { "title": "المهام", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "القروض / الفوائد", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "إضافة إدخال" + "emptyAction": "إضافة إدخال", + "loansTitle": "القروض", + "loansSummary": "{{count}} نشط · المتبقي {{amount}}", + "newLoan": "قرض جديد", + "createLoan": "إنشاء قرض", + "editLoan": "تعديل القرض", + "deleteLoan": "حذف القرض", + "deleteLoanConfirm": "هل تريد حذف القرض \"{{title}}\"؟ ستتم إزالة الدفعات المسجلة في الميزانية أيضًا.", + "deleteLoanPaymentConfirm": "هل تريد حذف دفعة القرض هذه؟", + "loanRemainingAmount": "المتبقي", + "loanRemainingInstallments": "الأقساط المتبقية", + "loanPaidAmount": "المدفوع", + "loansEmpty": "لا توجد قروض نشطة.", + "loanInstallmentMeta": "تم دفع {{paid}} من {{total}} أقساط", + "loanRemainingOf": "من {{total}}", + "loanNextDue": "التالي: {{month}}", + "loanPaidStatus": "مدفوع", + "markLoanPaid": "تسجيل الدفع", + "loanBorrowerLabel": "الشخص *", + "loanBorrowerPlaceholder": "مثال: Lais", + "loanTitleLabel": "عنوان القرض", + "loanTitlePlaceholder": "مثال: قرض شخصي", + "loanAmountLabel": "المبلغ الإجمالي *", + "loanInstallmentsLabel": "الأقساط *", + "loanStartMonthLabel": "أول شهر استحقاق *", + "loanNotesLabel": "ملاحظات", + "loanBorrowerRequired": "الشخص مطلوب", + "loanInstallmentsRequired": "أدخل عدد الأقساط", + "loanStartMonthRequired": "أدخل أول شهر استحقاق", + "loanAddedToast": "تمت إضافة القرض", + "loanSavedToast": "تم حفظ القرض", + "loanDeletedToast": "تم حذف القرض", + "loanPaymentAddedToast": "تم تسجيل الدفع", + "loanPaymentTitle": "سداد القرض: {{borrower}}", + "typeLoan": "قرض", + "tabsLabel": "أقسام الميزانية", + "budgetTab": "الميزانية", + "loansTab": "القروض", + "filteredTransactions": "المعاملات المصفاة", + "clearLoanFilter": "مسح الفلتر", + "loanFilterActive": "القرض: {{title}}", + "filterLoanTransactions": "عرض معاملات هذا القرض", + "loansEmptyDescription": "أنشئ قرضًا من زر + واختر قرض.", + "newCategoryTitle": "فئة جديدة", + "newCategoryPlaceholder": "اسم الفئة", + "newSubcategoryTitle": "فئة فرعية جديدة", + "newSubcategoryPlaceholder": "اسم الفئة الفرعية", + "loanStatusFilterLabel": "فلتر حالة القرض", + "loanStatusActive": "نشطة", + "loanStatusPaid": "مدفوعة", + "loanStatusAll": "الكل", + "loanTransactions": "معاملات القرض", + "loanInstallmentNumber": "القسط {{number}} من {{total}}", + "loanReportTitle": "تقرير القرض", + "loanNoTransactions": "لم يتم تسجيل أي دفعات بعد." }, "settings": { "title": "الإعدادات", diff --git a/public/locales/de.json b/public/locales/de.json index aec8962..661f0c0 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -118,7 +118,13 @@ "customizeMoveUp": "Nach oben", "customizeMoveDown": "Nach unten", "overdueTasksChip": "{{count}} überfällige Aufgabe", - "overdueTasksChipPlural": "{{count}} überfällige Aufgaben" + "overdueTasksChipPlural": "{{count}} überfällige Aufgaben", + "customizeManage": "Widgets", + "customizeExit": "Anpassung beenden", + "customizeDrag": "Widget ziehen", + "customizeSize": "Größe", + "customizeSizeFor": "Größe für {{widget}}", + "customizeHide": "{{widget}} ausblenden" }, "tasks": { "title": "Aufgaben", @@ -590,7 +596,61 @@ "newCategoryPrompt": "Name der neuen Kategorie:", "newSubcategoryPrompt": "Name der neuen Unterkategorie:", "categoryAddedToast": "Kategorie hinzugefügt.", - "subcategoryAddedToast": "Unterkategorie hinzugefügt." + "subcategoryAddedToast": "Unterkategorie hinzugefügt.", + "loansTitle": "Darlehen", + "loansSummary": "{{count}} aktiv · {{amount}} offen", + "newLoan": "Neues Darlehen", + "createLoan": "Darlehen erstellen", + "editLoan": "Darlehen bearbeiten", + "deleteLoan": "Darlehen löschen", + "deleteLoanConfirm": "Darlehen \"{{title}}\" löschen? Bereits im Budget verbuchte Zahlungen werden ebenfalls entfernt.", + "deleteLoanPaymentConfirm": "Diese Darlehenszahlung löschen?", + "loanRemainingAmount": "Offen", + "loanRemainingInstallments": "Raten offen", + "loanPaidAmount": "Bezahlt", + "loansEmpty": "Keine aktiven Darlehen.", + "loanInstallmentMeta": "{{paid}} von {{total}} Raten bezahlt", + "loanRemainingOf": "von {{total}}", + "loanNextDue": "Nächste: {{month}}", + "loanPaidStatus": "Bezahlt", + "markLoanPaid": "Als bezahlt markieren", + "loanBorrowerLabel": "Person *", + "loanBorrowerPlaceholder": "z. B. Lais", + "loanTitleLabel": "Darlehenstitel", + "loanTitlePlaceholder": "z. B. Persönliches Darlehen", + "loanAmountLabel": "Gesamtbetrag *", + "loanInstallmentsLabel": "Raten *", + "loanStartMonthLabel": "Erster Fälligkeitsmonat *", + "loanNotesLabel": "Notizen", + "loanBorrowerRequired": "Person ist erforderlich", + "loanInstallmentsRequired": "Anzahl der Raten eingeben", + "loanStartMonthRequired": "Ersten Fälligkeitsmonat eingeben", + "loanAddedToast": "Darlehen hinzugefügt", + "loanSavedToast": "Darlehen gespeichert", + "loanDeletedToast": "Darlehen gelöscht", + "loanPaymentAddedToast": "Zahlung erfasst", + "loanPaymentTitle": "Darlehensrückzahlung: {{borrower}}", + "typeLoan": "Darlehen", + "tabsLabel": "Budgetbereiche", + "budgetTab": "Budget", + "loansTab": "Darlehen", + "filteredTransactions": "Gefilterte Transaktionen", + "clearLoanFilter": "Filter löschen", + "loanFilterActive": "Darlehen: {{title}}", + "filterLoanTransactions": "Transaktionen dieses Darlehens anzeigen", + "loansEmptyDescription": "Erstelle ein Darlehen über die +-Schaltfläche und wähle Darlehen.", + "newCategoryTitle": "Neue Kategorie", + "newCategoryPlaceholder": "Kategoriename", + "newSubcategoryTitle": "Neue Unterkategorie", + "newSubcategoryPlaceholder": "Name der Unterkategorie", + "loanStatusFilterLabel": "Darlehensstatus filtern", + "loanStatusActive": "Aktiv", + "loanStatusPaid": "Bezahlt", + "loanStatusAll": "Alle", + "loanTransactions": "Darlehenstransaktionen", + "loanInstallmentNumber": "Rate {{number}} von {{total}}", + "loanReportTitle": "Darlehensbericht", + "loanNoTransactions": "Noch keine Zahlungen erfasst." }, "settings": { "title": "Einstellungen", diff --git a/public/locales/el.json b/public/locales/el.json index 1d9229f..a6a3ad4 100644 --- a/public/locales/el.json +++ b/public/locales/el.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Πάνω", "customizeMoveDown": "Κάτω", "overdueTasksChip": "{{count}} εκπρόθεσμη εργασία", - "overdueTasksChipPlural": "{{count}} εκπρόθεσμες εργασίες" + "overdueTasksChipPlural": "{{count}} εκπρόθεσμες εργασίες", + "customizeManage": "Widget", + "customizeExit": "Έξοδος από προσαρμογή", + "customizeDrag": "Σύρετε widget", + "customizeSize": "Μέγεθος", + "customizeSizeFor": "Μέγεθος για {{widget}}", + "customizeHide": "Απόκρυψη {{widget}}" }, "tasks": { "title": "Εργασίες", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "Δάνεια / Τόκοι", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "Προσθήκη εγγραφής" + "emptyAction": "Προσθήκη εγγραφής", + "loansTitle": "Δάνεια", + "loansSummary": "{{count}} ενεργά · απομένουν {{amount}}", + "newLoan": "Νέο δάνειο", + "createLoan": "Δημιουργία δανείου", + "editLoan": "Επεξεργασία δανείου", + "deleteLoan": "Διαγραφή δανείου", + "deleteLoanConfirm": "Να διαγραφεί το δάνειο «{{title}}»; Οι πληρωμές που έχουν ήδη περαστεί στον προϋπολογισμό θα αφαιρεθούν επίσης.", + "deleteLoanPaymentConfirm": "Διαγραφή αυτής της πληρωμής δανείου;", + "loanRemainingAmount": "Υπόλοιπο", + "loanRemainingInstallments": "Δόσεις που απομένουν", + "loanPaidAmount": "Πληρωμένο", + "loansEmpty": "Δεν υπάρχουν ενεργά δάνεια.", + "loanInstallmentMeta": "{{paid}} από {{total}} δόσεις πληρωμένες", + "loanRemainingOf": "από {{total}}", + "loanNextDue": "Επόμενη: {{month}}", + "loanPaidStatus": "Πληρωμένο", + "markLoanPaid": "Σήμανση πληρωμής", + "loanBorrowerLabel": "Άτομο *", + "loanBorrowerPlaceholder": "π.χ. Lais", + "loanTitleLabel": "Τίτλος δανείου", + "loanTitlePlaceholder": "π.χ. Προσωπικό δάνειο", + "loanAmountLabel": "Συνολικό ποσό *", + "loanInstallmentsLabel": "Δόσεις *", + "loanStartMonthLabel": "Πρώτος μήνας λήξης *", + "loanNotesLabel": "Σημειώσεις", + "loanBorrowerRequired": "Το άτομο είναι υποχρεωτικό", + "loanInstallmentsRequired": "Εισαγάγετε τον αριθμό δόσεων", + "loanStartMonthRequired": "Εισαγάγετε τον πρώτο μήνα λήξης", + "loanAddedToast": "Το δάνειο προστέθηκε", + "loanSavedToast": "Το δάνειο αποθηκεύτηκε", + "loanDeletedToast": "Το δάνειο διαγράφηκε", + "loanPaymentAddedToast": "Η πληρωμή καταγράφηκε", + "loanPaymentTitle": "Πληρωμή δανείου: {{borrower}}", + "typeLoan": "Δάνειο", + "tabsLabel": "Ενότητες προϋπολογισμού", + "budgetTab": "Προϋπολογισμός", + "loansTab": "Δάνεια", + "filteredTransactions": "Φιλτραρισμένες συναλλαγές", + "clearLoanFilter": "Καθαρισμός φίλτρου", + "loanFilterActive": "Δάνειο: {{title}}", + "filterLoanTransactions": "Εμφάνιση συναλλαγών αυτού του δανείου", + "loansEmptyDescription": "Δημιουργήστε δάνειο από το κουμπί + και επιλέξτε Δάνειο.", + "newCategoryTitle": "Νέα κατηγορία", + "newCategoryPlaceholder": "Όνομα κατηγορίας", + "newSubcategoryTitle": "Νέα υποκατηγορία", + "newSubcategoryPlaceholder": "Όνομα υποκατηγορίας", + "loanStatusFilterLabel": "Φίλτρο κατάστασης δανείων", + "loanStatusActive": "Ενεργά", + "loanStatusPaid": "Πληρωμένα", + "loanStatusAll": "Όλα", + "loanTransactions": "Συναλλαγές δανείου", + "loanInstallmentNumber": "Δόση {{number}} από {{total}}", + "loanReportTitle": "Αναφορά δανείου", + "loanNoTransactions": "Δεν έχουν καταγραφεί πληρωμές ακόμα." }, "settings": { "title": "Ρυθμίσεις", diff --git a/public/locales/en.json b/public/locales/en.json index aecf24a..764229c 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Move up", "customizeMoveDown": "Move down", "overdueTasksChip": "{{count}} overdue task", - "overdueTasksChipPlural": "{{count}} overdue tasks" + "overdueTasksChipPlural": "{{count}} overdue tasks", + "customizeManage": "Widgets", + "customizeExit": "Exit customization", + "customizeDrag": "Drag widget", + "customizeSize": "Size", + "customizeSizeFor": "Size for {{widget}}", + "customizeHide": "Hide {{widget}}" }, "tasks": { "title": "Tasks", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "Add entry" + "emptyAction": "Add entry", + "loansTitle": "Loans", + "loansSummary": "{{count}} active · {{amount}} remaining", + "newLoan": "New loan", + "createLoan": "Create loan", + "editLoan": "Edit loan", + "deleteLoan": "Delete loan", + "deleteLoanConfirm": "Delete loan \"{{title}}\"? Payments already posted to the budget will also be removed.", + "deleteLoanPaymentConfirm": "Delete this loan payment?", + "loanRemainingAmount": "Remaining", + "loanRemainingInstallments": "Installments left", + "loanPaidAmount": "Paid", + "loansEmpty": "No active loans.", + "loanInstallmentMeta": "{{paid}} of {{total}} installments paid", + "loanRemainingOf": "of {{total}}", + "loanNextDue": "Next: {{month}}", + "loanPaidStatus": "Paid", + "markLoanPaid": "Mark paid", + "loanBorrowerLabel": "Borrower *", + "loanBorrowerPlaceholder": "e.g. Lais", + "loanTitleLabel": "Loan title", + "loanTitlePlaceholder": "e.g. Personal loan", + "loanAmountLabel": "Total amount *", + "loanInstallmentsLabel": "Installments *", + "loanStartMonthLabel": "First due month *", + "loanNotesLabel": "Notes", + "loanBorrowerRequired": "Borrower is required", + "loanInstallmentsRequired": "Enter the number of installments", + "loanStartMonthRequired": "Enter the first due month", + "loanAddedToast": "Loan added", + "loanSavedToast": "Loan saved", + "loanDeletedToast": "Loan deleted", + "loanPaymentAddedToast": "Payment recorded", + "loanPaymentTitle": "Loan repayment: {{borrower}}", + "typeLoan": "Loan", + "tabsLabel": "Budget sections", + "budgetTab": "Budget", + "loansTab": "Loans", + "filteredTransactions": "Filtered transactions", + "clearLoanFilter": "Clear filter", + "loanFilterActive": "Loan: {{title}}", + "filterLoanTransactions": "Show transactions for this loan", + "loansEmptyDescription": "Create a loan from the + button and choose Loan.", + "newCategoryTitle": "New category", + "newCategoryPlaceholder": "Category name", + "newSubcategoryTitle": "New subcategory", + "newSubcategoryPlaceholder": "Subcategory name", + "loanStatusFilterLabel": "Loan status filter", + "loanStatusActive": "Active", + "loanStatusPaid": "Paid", + "loanStatusAll": "All", + "loanTransactions": "Loan transactions", + "loanInstallmentNumber": "Installment {{number}} of {{total}}", + "loanReportTitle": "Loan report", + "loanNoTransactions": "No payments recorded yet." }, "settings": { "title": "Settings", diff --git a/public/locales/es.json b/public/locales/es.json index 407dcab..126c08a 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Subir", "customizeMoveDown": "Bajar", "overdueTasksChip": "{{count}} tarea vencida", - "overdueTasksChipPlural": "{{count}} tareas vencidas" + "overdueTasksChipPlural": "{{count}} tareas vencidas", + "customizeManage": "Widgets", + "customizeExit": "Salir de personalización", + "customizeDrag": "Arrastrar widget", + "customizeSize": "Tamaño", + "customizeSizeFor": "Tamaño de {{widget}}", + "customizeHide": "Ocultar {{widget}}" }, "tasks": { "title": "Tareas", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Nombre de la nueva subcategoría:", "categoryAddedToast": "Categoría añadida.", "subcategoryAddedToast": "Subcategoría añadida.", - "emptyAction": "Agregar entrada" + "emptyAction": "Agregar entrada", + "loansTitle": "Préstamos", + "loansSummary": "{{count}} activos · {{amount}} restantes", + "newLoan": "Nuevo préstamo", + "createLoan": "Crear préstamo", + "editLoan": "Editar préstamo", + "deleteLoan": "Eliminar préstamo", + "deleteLoanConfirm": "¿Eliminar el préstamo \"{{title}}\"? También se eliminarán los pagos ya registrados en el presupuesto.", + "deleteLoanPaymentConfirm": "¿Eliminar este pago del préstamo?", + "loanRemainingAmount": "Restante", + "loanRemainingInstallments": "Cuotas restantes", + "loanPaidAmount": "Pagado", + "loansEmpty": "No hay préstamos activos.", + "loanInstallmentMeta": "{{paid}} de {{total}} cuotas pagadas", + "loanRemainingOf": "de {{total}}", + "loanNextDue": "Siguiente: {{month}}", + "loanPaidStatus": "Pagado", + "markLoanPaid": "Marcar pagado", + "loanBorrowerLabel": "Persona *", + "loanBorrowerPlaceholder": "Ej. Lais", + "loanTitleLabel": "Título del préstamo", + "loanTitlePlaceholder": "Ej. Préstamo personal", + "loanAmountLabel": "Importe total *", + "loanInstallmentsLabel": "Cuotas *", + "loanStartMonthLabel": "Primer mes de vencimiento *", + "loanNotesLabel": "Notas", + "loanBorrowerRequired": "La persona es obligatoria", + "loanInstallmentsRequired": "Introduce el número de cuotas", + "loanStartMonthRequired": "Introduce el primer mes de vencimiento", + "loanAddedToast": "Préstamo añadido", + "loanSavedToast": "Préstamo guardado", + "loanDeletedToast": "Préstamo eliminado", + "loanPaymentAddedToast": "Pago registrado", + "loanPaymentTitle": "Pago del préstamo: {{borrower}}", + "typeLoan": "Préstamo", + "tabsLabel": "Secciones del presupuesto", + "budgetTab": "Presupuesto", + "loansTab": "Préstamos", + "filteredTransactions": "Transacciones filtradas", + "clearLoanFilter": "Limpiar filtro", + "loanFilterActive": "Préstamo: {{title}}", + "filterLoanTransactions": "Mostrar transacciones de este préstamo", + "loansEmptyDescription": "Crea un préstamo con el botón + y elige Préstamo.", + "newCategoryTitle": "Nueva categoría", + "newCategoryPlaceholder": "Nombre de la categoría", + "newSubcategoryTitle": "Nueva subcategoría", + "newSubcategoryPlaceholder": "Nombre de la subcategoría", + "loanStatusFilterLabel": "Filtro de estado de préstamos", + "loanStatusActive": "Activos", + "loanStatusPaid": "Pagados", + "loanStatusAll": "Todos", + "loanTransactions": "Transacciones del préstamo", + "loanInstallmentNumber": "Cuota {{number}} de {{total}}", + "loanReportTitle": "Informe del préstamo", + "loanNoTransactions": "Aún no hay pagos registrados." }, "settings": { "title": "Ajustes", diff --git a/public/locales/fr.json b/public/locales/fr.json index 0733002..fb5764f 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Monter", "customizeMoveDown": "Descendre", "overdueTasksChip": "{{count}} tâche en retard", - "overdueTasksChipPlural": "{{count}} tâches en retard" + "overdueTasksChipPlural": "{{count}} tâches en retard", + "customizeManage": "Widgets", + "customizeExit": "Quitter la personnalisation", + "customizeDrag": "Faire glisser le widget", + "customizeSize": "Taille", + "customizeSizeFor": "Taille de {{widget}}", + "customizeHide": "Masquer {{widget}}" }, "tasks": { "title": "Tâches", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Nom de la nouvelle sous-catégorie :", "categoryAddedToast": "Catégorie ajoutée.", "subcategoryAddedToast": "Sous-catégorie ajoutée.", - "emptyAction": "Ajouter une entrée" + "emptyAction": "Ajouter une entrée", + "loansTitle": "Prêts", + "loansSummary": "{{count}} actifs · {{amount}} restants", + "newLoan": "Nouveau prêt", + "createLoan": "Créer le prêt", + "editLoan": "Modifier le prêt", + "deleteLoan": "Supprimer le prêt", + "deleteLoanConfirm": "Supprimer le prêt \"{{title}}\" ? Les paiements déjà enregistrés dans le budget seront aussi supprimés.", + "deleteLoanPaymentConfirm": "Supprimer ce paiement de prêt ?", + "loanRemainingAmount": "Restant", + "loanRemainingInstallments": "Échéances restantes", + "loanPaidAmount": "Payé", + "loansEmpty": "Aucun prêt actif.", + "loanInstallmentMeta": "{{paid}} sur {{total}} échéances payées", + "loanRemainingOf": "sur {{total}}", + "loanNextDue": "Prochaine : {{month}}", + "loanPaidStatus": "Payé", + "markLoanPaid": "Marquer payé", + "loanBorrowerLabel": "Personne *", + "loanBorrowerPlaceholder": "Ex. Lais", + "loanTitleLabel": "Titre du prêt", + "loanTitlePlaceholder": "Ex. Prêt personnel", + "loanAmountLabel": "Montant total *", + "loanInstallmentsLabel": "Échéances *", + "loanStartMonthLabel": "Premier mois d’échéance *", + "loanNotesLabel": "Notes", + "loanBorrowerRequired": "La personne est obligatoire", + "loanInstallmentsRequired": "Indiquez le nombre d’échéances", + "loanStartMonthRequired": "Indiquez le premier mois d’échéance", + "loanAddedToast": "Prêt ajouté", + "loanSavedToast": "Prêt enregistré", + "loanDeletedToast": "Prêt supprimé", + "loanPaymentAddedToast": "Paiement enregistré", + "loanPaymentTitle": "Remboursement du prêt : {{borrower}}", + "typeLoan": "Prêt", + "tabsLabel": "Sections du budget", + "budgetTab": "Budget", + "loansTab": "Prêts", + "filteredTransactions": "Transactions filtrées", + "clearLoanFilter": "Effacer le filtre", + "loanFilterActive": "Prêt : {{title}}", + "filterLoanTransactions": "Afficher les transactions de ce prêt", + "loansEmptyDescription": "Créez un prêt avec le bouton + puis choisissez Prêt.", + "newCategoryTitle": "Nouvelle catégorie", + "newCategoryPlaceholder": "Nom de la catégorie", + "newSubcategoryTitle": "Nouvelle sous-catégorie", + "newSubcategoryPlaceholder": "Nom de la sous-catégorie", + "loanStatusFilterLabel": "Filtre de statut des prêts", + "loanStatusActive": "Actifs", + "loanStatusPaid": "Payés", + "loanStatusAll": "Tous", + "loanTransactions": "Transactions du prêt", + "loanInstallmentNumber": "Échéance {{number}} sur {{total}}", + "loanReportTitle": "Rapport du prêt", + "loanNoTransactions": "Aucun paiement enregistré." }, "settings": { "title": "Paramètres", diff --git a/public/locales/hi.json b/public/locales/hi.json index 4ac5f3a..2530042 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -112,7 +112,13 @@ "customizeMoveUp": "ऊपर ले जाएं", "customizeMoveDown": "नीचे ले जाएं", "overdueTasksChip": "{{count}} विलंबित कार्य", - "overdueTasksChipPlural": "{{count}} विलंबित कार्य" + "overdueTasksChipPlural": "{{count}} विलंबित कार्य", + "customizeManage": "विजेट", + "customizeExit": "अनुकूलन से बाहर निकलें", + "customizeDrag": "विजेट खींचें", + "customizeSize": "आकार", + "customizeSizeFor": "{{widget}} का आकार", + "customizeHide": "{{widget}} छिपाएँ" }, "tasks": { "title": "कार्य", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "उधार / ब्याज", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "प्रविष्टि जोड़ें" + "emptyAction": "प्रविष्टि जोड़ें", + "loansTitle": "उधार", + "loansSummary": "{{count}} सक्रिय · {{amount}} बाकी", + "newLoan": "नया उधार", + "createLoan": "उधार बनाएं", + "editLoan": "उधार संपादित करें", + "deleteLoan": "उधार हटाएं", + "deleteLoanConfirm": "उधार \"{{title}}\" हटाएं? बजट में दर्ज भुगतान भी हटा दिए जाएंगे।", + "deleteLoanPaymentConfirm": "यह ऋण भुगतान हटाएँ?", + "loanRemainingAmount": "बाकी", + "loanRemainingInstallments": "बाकी किस्तें", + "loanPaidAmount": "भुगतान किया", + "loansEmpty": "कोई सक्रिय उधार नहीं।", + "loanInstallmentMeta": "{{total}} में से {{paid}} किस्तें चुकाई गईं", + "loanRemainingOf": "{{total}} में से", + "loanNextDue": "अगली: {{month}}", + "loanPaidStatus": "चुकाया गया", + "markLoanPaid": "भुगतान दर्ज करें", + "loanBorrowerLabel": "व्यक्ति *", + "loanBorrowerPlaceholder": "जैसे Lais", + "loanTitleLabel": "उधार का शीर्षक", + "loanTitlePlaceholder": "जैसे व्यक्तिगत उधार", + "loanAmountLabel": "कुल राशि *", + "loanInstallmentsLabel": "किस्तें *", + "loanStartMonthLabel": "पहला देय महीना *", + "loanNotesLabel": "नोट्स", + "loanBorrowerRequired": "व्यक्ति आवश्यक है", + "loanInstallmentsRequired": "किस्तों की संख्या दर्ज करें", + "loanStartMonthRequired": "पहला देय महीना दर्ज करें", + "loanAddedToast": "उधार जोड़ा गया", + "loanSavedToast": "उधार सहेजा गया", + "loanDeletedToast": "उधार हटाया गया", + "loanPaymentAddedToast": "भुगतान दर्ज किया गया", + "loanPaymentTitle": "ऋण भुगतान: {{borrower}}", + "typeLoan": "उधार", + "tabsLabel": "बजट अनुभाग", + "budgetTab": "बजट", + "loansTab": "उधार", + "filteredTransactions": "फ़िल्टर किए गए लेन-देन", + "clearLoanFilter": "फ़िल्टर हटाएं", + "loanFilterActive": "उधार: {{title}}", + "filterLoanTransactions": "इस उधार के लेन-देन दिखाएं", + "loansEmptyDescription": "+ बटन से उधार चुनकर नया उधार बनाएं।", + "newCategoryTitle": "नई श्रेणी", + "newCategoryPlaceholder": "श्रेणी का नाम", + "newSubcategoryTitle": "नई उपश्रेणी", + "newSubcategoryPlaceholder": "उपश्रेणी का नाम", + "loanStatusFilterLabel": "उधार स्थिति फ़िल्टर", + "loanStatusActive": "सक्रिय", + "loanStatusPaid": "चुकाया गया", + "loanStatusAll": "सभी", + "loanTransactions": "उधार लेन-देन", + "loanInstallmentNumber": "{{total}} में से किस्त {{number}}", + "loanReportTitle": "उधार रिपोर्ट", + "loanNoTransactions": "अभी कोई भुगतान दर्ज नहीं है।" }, "settings": { "title": "सेटिंग्स", diff --git a/public/locales/it.json b/public/locales/it.json index 815a04e..8b42816 100644 --- a/public/locales/it.json +++ b/public/locales/it.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Su", "customizeMoveDown": "Giù", "overdueTasksChip": "{{count}} compito scaduto", - "overdueTasksChipPlural": "{{count}} compiti scaduti" + "overdueTasksChipPlural": "{{count}} compiti scaduti", + "customizeManage": "Widget", + "customizeExit": "Esci dalla personalizzazione", + "customizeDrag": "Trascina widget", + "customizeSize": "Dimensione", + "customizeSizeFor": "Dimensione di {{widget}}", + "customizeHide": "Nascondi {{widget}}" }, "tasks": { "title": "Compiti", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Nome della nuova sottocategoria:", "categoryAddedToast": "Categoria aggiunta.", "subcategoryAddedToast": "Sottocategoria aggiunta.", - "emptyAction": "Aggiungi voce" + "emptyAction": "Aggiungi voce", + "loansTitle": "Prestiti", + "loansSummary": "{{count}} attivi · {{amount}} rimanenti", + "newLoan": "Nuovo prestito", + "createLoan": "Crea prestito", + "editLoan": "Modifica prestito", + "deleteLoan": "Elimina prestito", + "deleteLoanConfirm": "Eliminare il prestito \"{{title}}\"? Verranno rimossi anche i pagamenti già registrati nel bilancio.", + "deleteLoanPaymentConfirm": "Eliminare questo pagamento del prestito?", + "loanRemainingAmount": "Rimanente", + "loanRemainingInstallments": "Rate rimanenti", + "loanPaidAmount": "Pagato", + "loansEmpty": "Nessun prestito attivo.", + "loanInstallmentMeta": "{{paid}} di {{total}} rate pagate", + "loanRemainingOf": "di {{total}}", + "loanNextDue": "Prossima: {{month}}", + "loanPaidStatus": "Pagato", + "markLoanPaid": "Segna pagato", + "loanBorrowerLabel": "Persona *", + "loanBorrowerPlaceholder": "Es. Lais", + "loanTitleLabel": "Titolo del prestito", + "loanTitlePlaceholder": "Es. Prestito personale", + "loanAmountLabel": "Importo totale *", + "loanInstallmentsLabel": "Rate *", + "loanStartMonthLabel": "Primo mese di scadenza *", + "loanNotesLabel": "Note", + "loanBorrowerRequired": "La persona è obbligatoria", + "loanInstallmentsRequired": "Inserisci il numero di rate", + "loanStartMonthRequired": "Inserisci il primo mese di scadenza", + "loanAddedToast": "Prestito aggiunto", + "loanSavedToast": "Prestito salvato", + "loanDeletedToast": "Prestito eliminato", + "loanPaymentAddedToast": "Pagamento registrato", + "loanPaymentTitle": "Rimborso del prestito: {{borrower}}", + "typeLoan": "Prestito", + "tabsLabel": "Sezioni del bilancio", + "budgetTab": "Bilancio", + "loansTab": "Prestiti", + "filteredTransactions": "Movimenti filtrati", + "clearLoanFilter": "Cancella filtro", + "loanFilterActive": "Prestito: {{title}}", + "filterLoanTransactions": "Mostra i movimenti di questo prestito", + "loansEmptyDescription": "Crea un prestito dal pulsante + e scegli Prestito.", + "newCategoryTitle": "Nuova categoria", + "newCategoryPlaceholder": "Nome categoria", + "newSubcategoryTitle": "Nuova sottocategoria", + "newSubcategoryPlaceholder": "Nome sottocategoria", + "loanStatusFilterLabel": "Filtro stato prestiti", + "loanStatusActive": "Attivi", + "loanStatusPaid": "Pagati", + "loanStatusAll": "Tutti", + "loanTransactions": "Movimenti del prestito", + "loanInstallmentNumber": "Rata {{number}} di {{total}}", + "loanReportTitle": "Report del prestito", + "loanNoTransactions": "Nessun pagamento registrato." }, "settings": { "title": "Impostazioni", diff --git a/public/locales/ja.json b/public/locales/ja.json index e0099a1..87df852 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -112,7 +112,13 @@ "customizeMoveUp": "上へ", "customizeMoveDown": "下へ", "overdueTasksChip": "期限超過のタスク {{count}} 件", - "overdueTasksChipPlural": "期限超過のタスク {{count}} 件" + "overdueTasksChipPlural": "期限超過のタスク {{count}} 件", + "customizeManage": "ウィジェット", + "customizeExit": "カスタマイズを終了", + "customizeDrag": "ウィジェットをドラッグ", + "customizeSize": "サイズ", + "customizeSizeFor": "{{widget}} のサイズ", + "customizeHide": "{{widget}} を非表示" }, "tasks": { "title": "タスク", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "貸付 / 利息", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "エントリを追加" + "emptyAction": "エントリを追加", + "loansTitle": "貸付", + "loansSummary": "{{count}} 件が進行中 · 残り {{amount}}", + "newLoan": "新しい貸付", + "createLoan": "貸付を作成", + "editLoan": "貸付を編集", + "deleteLoan": "貸付を削除", + "deleteLoanConfirm": "貸付「{{title}}」を削除しますか?予算に記録済みの返済も削除されます。", + "deleteLoanPaymentConfirm": "このローン支払いを削除しますか?", + "loanRemainingAmount": "残額", + "loanRemainingInstallments": "残り回数", + "loanPaidAmount": "返済済み", + "loansEmpty": "進行中の貸付はありません。", + "loanInstallmentMeta": "{{total}} 回中 {{paid}} 回返済済み", + "loanRemainingOf": "{{total}} のうち", + "loanNextDue": "次回:{{month}}", + "loanPaidStatus": "完済", + "markLoanPaid": "返済済みにする", + "loanBorrowerLabel": "相手 *", + "loanBorrowerPlaceholder": "例:Lais", + "loanTitleLabel": "貸付タイトル", + "loanTitlePlaceholder": "例:個人貸付", + "loanAmountLabel": "合計金額 *", + "loanInstallmentsLabel": "分割回数 *", + "loanStartMonthLabel": "初回支払月 *", + "loanNotesLabel": "メモ", + "loanBorrowerRequired": "相手を入力してください", + "loanInstallmentsRequired": "分割回数を入力してください", + "loanStartMonthRequired": "初回支払月を入力してください", + "loanAddedToast": "貸付を追加しました", + "loanSavedToast": "貸付を保存しました", + "loanDeletedToast": "貸付を削除しました", + "loanPaymentAddedToast": "返済を記録しました", + "loanPaymentTitle": "ローン返済: {{borrower}}", + "typeLoan": "貸付", + "tabsLabel": "予算セクション", + "budgetTab": "予算", + "loansTab": "貸付", + "filteredTransactions": "絞り込み済み取引", + "clearLoanFilter": "フィルター解除", + "loanFilterActive": "貸付:{{title}}", + "filterLoanTransactions": "この貸付の取引を表示", + "loansEmptyDescription": "+ ボタンから貸付を選んで作成します。", + "newCategoryTitle": "新しいカテゴリ", + "newCategoryPlaceholder": "カテゴリ名", + "newSubcategoryTitle": "新しいサブカテゴリ", + "newSubcategoryPlaceholder": "サブカテゴリ名", + "loanStatusFilterLabel": "貸付ステータスフィルター", + "loanStatusActive": "進行中", + "loanStatusPaid": "完済", + "loanStatusAll": "すべて", + "loanTransactions": "貸付取引", + "loanInstallmentNumber": "{{total}} 回中 {{number}} 回目", + "loanReportTitle": "貸付レポート", + "loanNoTransactions": "返済はまだ記録されていません。" }, "settings": { "title": "設定", diff --git a/public/locales/pt.json b/public/locales/pt.json index 0bba398..845b74f 100644 --- a/public/locales/pt.json +++ b/public/locales/pt.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Mover para cima", "customizeMoveDown": "Mover para baixo", "overdueTasksChip": "{{count}} tarefa vencida", - "overdueTasksChipPlural": "{{count}} tarefas vencidas" + "overdueTasksChipPlural": "{{count}} tarefas vencidas", + "customizeManage": "Widgets", + "customizeExit": "Sair da personalização", + "customizeDrag": "Arrastar widget", + "customizeSize": "Tamanho", + "customizeSizeFor": "Tamanho de {{widget}}", + "customizeHide": "Ocultar {{widget}}" }, "tasks": { "title": "Tarefas", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Nome da nova subcategoria:", "categoryAddedToast": "Categoria adicionada.", "subcategoryAddedToast": "Subcategoria adicionada.", - "emptyAction": "Adicionar entrada" + "emptyAction": "Adicionar entrada", + "loansTitle": "Empréstimos", + "loansSummary": "{{count}} ativos · {{amount}} restantes", + "newLoan": "Novo empréstimo", + "createLoan": "Criar empréstimo", + "editLoan": "Editar empréstimo", + "deleteLoan": "Excluir empréstimo", + "deleteLoanConfirm": "Excluir empréstimo \"{{title}}\"? Pagamentos já lançados no orçamento também serão removidos.", + "deleteLoanPaymentConfirm": "Excluir este pagamento do empréstimo?", + "loanRemainingAmount": "Restante", + "loanRemainingInstallments": "Parcelas restantes", + "loanPaidAmount": "Pago", + "loansEmpty": "Nenhum empréstimo ativo.", + "loanInstallmentMeta": "{{paid}} de {{total}} parcelas pagas", + "loanRemainingOf": "de {{total}}", + "loanNextDue": "Próxima: {{month}}", + "loanPaidStatus": "Pago", + "markLoanPaid": "Dar baixa", + "loanBorrowerLabel": "Pessoa *", + "loanBorrowerPlaceholder": "Ex.: Lais", + "loanTitleLabel": "Título do empréstimo", + "loanTitlePlaceholder": "Ex.: Empréstimo pessoal", + "loanAmountLabel": "Valor total *", + "loanInstallmentsLabel": "Parcelas *", + "loanStartMonthLabel": "Primeiro mês de vencimento *", + "loanNotesLabel": "Observações", + "loanBorrowerRequired": "Informe a pessoa", + "loanInstallmentsRequired": "Informe a quantidade de parcelas", + "loanStartMonthRequired": "Informe o primeiro mês de vencimento", + "loanAddedToast": "Empréstimo adicionado", + "loanSavedToast": "Empréstimo salvo", + "loanDeletedToast": "Empréstimo excluído", + "loanPaymentAddedToast": "Pagamento registrado", + "loanPaymentTitle": "Pagamento do empréstimo: {{borrower}}", + "typeLoan": "Empréstimo", + "tabsLabel": "Seções do orçamento", + "budgetTab": "Orçamento", + "loansTab": "Empréstimos", + "filteredTransactions": "Transações filtradas", + "clearLoanFilter": "Limpar filtro", + "loanFilterActive": "Empréstimo: {{title}}", + "filterLoanTransactions": "Mostrar transações deste empréstimo", + "loansEmptyDescription": "Crie um empréstimo pelo botão + e escolha Empréstimo.", + "newCategoryTitle": "Nova categoria", + "newCategoryPlaceholder": "Nome da categoria", + "newSubcategoryTitle": "Nova subcategoria", + "newSubcategoryPlaceholder": "Nome da subcategoria", + "loanStatusFilterLabel": "Filtro de status dos empréstimos", + "loanStatusActive": "Ativos", + "loanStatusPaid": "Pagos", + "loanStatusAll": "Todos", + "loanTransactions": "Transações do empréstimo", + "loanInstallmentNumber": "Parcela {{number}} de {{total}}", + "loanReportTitle": "Relatório do empréstimo", + "loanNoTransactions": "Nenhum pagamento registrado ainda." }, "settings": { "title": "Configurações", diff --git a/public/locales/ru.json b/public/locales/ru.json index dafba6e..bdeb66c 100644 --- a/public/locales/ru.json +++ b/public/locales/ru.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Вверх", "customizeMoveDown": "Вниз", "overdueTasksChip": "{{count}} просроченная задача", - "overdueTasksChipPlural": "{{count}} просроченных задач" + "overdueTasksChipPlural": "{{count}} просроченных задач", + "customizeManage": "Виджеты", + "customizeExit": "Выйти из настройки", + "customizeDrag": "Перетащить виджет", + "customizeSize": "Размер", + "customizeSizeFor": "Размер для {{widget}}", + "customizeHide": "Скрыть {{widget}}" }, "tasks": { "title": "Задачи", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "Займы / Проценты", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "Добавить запись" + "emptyAction": "Добавить запись", + "loansTitle": "Займы", + "loansSummary": "{{count}} активных · осталось {{amount}}", + "newLoan": "Новый займ", + "createLoan": "Создать займ", + "editLoan": "Изменить займ", + "deleteLoan": "Удалить займ", + "deleteLoanConfirm": "Удалить займ «{{title}}»? Платежи, уже добавленные в бюджет, тоже будут удалены.", + "deleteLoanPaymentConfirm": "Удалить этот платеж по займу?", + "loanRemainingAmount": "Осталось", + "loanRemainingInstallments": "Осталось платежей", + "loanPaidAmount": "Оплачено", + "loansEmpty": "Нет активных займов.", + "loanInstallmentMeta": "Оплачено {{paid}} из {{total}} платежей", + "loanRemainingOf": "из {{total}}", + "loanNextDue": "Следующий: {{month}}", + "loanPaidStatus": "Оплачено", + "markLoanPaid": "Отметить оплату", + "loanBorrowerLabel": "Человек *", + "loanBorrowerPlaceholder": "Напр. Lais", + "loanTitleLabel": "Название займа", + "loanTitlePlaceholder": "Напр. Личный займ", + "loanAmountLabel": "Общая сумма *", + "loanInstallmentsLabel": "Платежи *", + "loanStartMonthLabel": "Первый месяц оплаты *", + "loanNotesLabel": "Заметки", + "loanBorrowerRequired": "Укажите человека", + "loanInstallmentsRequired": "Укажите количество платежей", + "loanStartMonthRequired": "Укажите первый месяц оплаты", + "loanAddedToast": "Займ добавлен", + "loanSavedToast": "Займ сохранён", + "loanDeletedToast": "Займ удалён", + "loanPaymentAddedToast": "Платёж записан", + "loanPaymentTitle": "Платеж по займу: {{borrower}}", + "typeLoan": "Займ", + "tabsLabel": "Разделы бюджета", + "budgetTab": "Бюджет", + "loansTab": "Займы", + "filteredTransactions": "Отфильтрованные операции", + "clearLoanFilter": "Сбросить фильтр", + "loanFilterActive": "Займ: {{title}}", + "filterLoanTransactions": "Показать операции этого займа", + "loansEmptyDescription": "Создайте займ кнопкой + и выберите Займ.", + "newCategoryTitle": "Новая категория", + "newCategoryPlaceholder": "Название категории", + "newSubcategoryTitle": "Новая подкатегория", + "newSubcategoryPlaceholder": "Название подкатегории", + "loanStatusFilterLabel": "Фильтр статуса займов", + "loanStatusActive": "Активные", + "loanStatusPaid": "Оплаченные", + "loanStatusAll": "Все", + "loanTransactions": "Операции займа", + "loanInstallmentNumber": "Платёж {{number}} из {{total}}", + "loanReportTitle": "Отчёт по займу", + "loanNoTransactions": "Платежи ещё не записаны." }, "settings": { "title": "Настройки", diff --git a/public/locales/sv.json b/public/locales/sv.json index 1c7ab10..54e94cc 100644 --- a/public/locales/sv.json +++ b/public/locales/sv.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Flytta upp", "customizeMoveDown": "Flytta ner", "overdueTasksChip": "{{count}} förfallen uppgift", - "overdueTasksChipPlural": "{{count}} förfallna uppgifter" + "overdueTasksChipPlural": "{{count}} förfallna uppgifter", + "customizeManage": "Widgetar", + "customizeExit": "Avsluta anpassning", + "customizeDrag": "Dra widget", + "customizeSize": "Storlek", + "customizeSizeFor": "Storlek för {{widget}}", + "customizeHide": "Dölj {{widget}}" }, "tasks": { "title": "Uppgifter", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Namn på den nya underkategorin:", "categoryAddedToast": "Kategori tillagd.", "subcategoryAddedToast": "Underkategori har lagts till.", - "emptyAction": "Lägg till post" + "emptyAction": "Lägg till post", + "loansTitle": "Lån", + "loansSummary": "{{count}} aktiva · {{amount}} kvar", + "newLoan": "Nytt lån", + "createLoan": "Skapa lån", + "editLoan": "Redigera lån", + "deleteLoan": "Ta bort lån", + "deleteLoanConfirm": "Ta bort lånet \"{{title}}\"? Betalningar som redan bokförts i budgeten tas också bort.", + "deleteLoanPaymentConfirm": "Ta bort den här lånebetalningen?", + "loanRemainingAmount": "Kvar", + "loanRemainingInstallments": "Delbetalningar kvar", + "loanPaidAmount": "Betalt", + "loansEmpty": "Inga aktiva lån.", + "loanInstallmentMeta": "{{paid}} av {{total}} delbetalningar betalda", + "loanRemainingOf": "av {{total}}", + "loanNextDue": "Nästa: {{month}}", + "loanPaidStatus": "Betalt", + "markLoanPaid": "Markera betalt", + "loanBorrowerLabel": "Person *", + "loanBorrowerPlaceholder": "t.ex. Lais", + "loanTitleLabel": "Lånetitel", + "loanTitlePlaceholder": "t.ex. Privat lån", + "loanAmountLabel": "Totalbelopp *", + "loanInstallmentsLabel": "Delbetalningar *", + "loanStartMonthLabel": "Första förfallomånaden *", + "loanNotesLabel": "Anteckningar", + "loanBorrowerRequired": "Person krävs", + "loanInstallmentsRequired": "Ange antal delbetalningar", + "loanStartMonthRequired": "Ange första förfallomånaden", + "loanAddedToast": "Lån tillagt", + "loanSavedToast": "Lån sparat", + "loanDeletedToast": "Lån borttaget", + "loanPaymentAddedToast": "Betalning registrerad", + "loanPaymentTitle": "Låneåterbetalning: {{borrower}}", + "typeLoan": "Lån", + "tabsLabel": "Budgetsektioner", + "budgetTab": "Budget", + "loansTab": "Lån", + "filteredTransactions": "Filtrerade transaktioner", + "clearLoanFilter": "Rensa filter", + "loanFilterActive": "Lån: {{title}}", + "filterLoanTransactions": "Visa transaktioner för detta lån", + "loansEmptyDescription": "Skapa ett lån med +-knappen och välj Lån.", + "newCategoryTitle": "Ny kategori", + "newCategoryPlaceholder": "Kategorinamn", + "newSubcategoryTitle": "Ny underkategori", + "newSubcategoryPlaceholder": "Underkategorinamn", + "loanStatusFilterLabel": "Filter för lånestatus", + "loanStatusActive": "Aktiva", + "loanStatusPaid": "Betalda", + "loanStatusAll": "Alla", + "loanTransactions": "Lånetransaktioner", + "loanInstallmentNumber": "Delbetalning {{number}} av {{total}}", + "loanReportTitle": "Lånrapport", + "loanNoTransactions": "Inga betalningar registrerade ännu." }, "settings": { "title": "Inställningar", diff --git a/public/locales/tr.json b/public/locales/tr.json index 4175e73..b76bd3d 100644 --- a/public/locales/tr.json +++ b/public/locales/tr.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Yukarı", "customizeMoveDown": "Aşağı", "overdueTasksChip": "{{count}} gecikmiş görev", - "overdueTasksChipPlural": "{{count}} gecikmiş görev" + "overdueTasksChipPlural": "{{count}} gecikmiş görev", + "customizeManage": "Widgetlar", + "customizeExit": "Özelleştirmeden çık", + "customizeDrag": "Widgetı sürükle", + "customizeSize": "Boyut", + "customizeSizeFor": "{{widget}} boyutu", + "customizeHide": "{{widget}} gizle" }, "tasks": { "title": "Görevler", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "Borçlar / Faiz", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "Giriş ekle" + "emptyAction": "Giriş ekle", + "loansTitle": "Borçlar", + "loansSummary": "{{count}} aktif · {{amount}} kaldı", + "newLoan": "Yeni borç", + "createLoan": "Borç oluştur", + "editLoan": "Borcu düzenle", + "deleteLoan": "Borcu sil", + "deleteLoanConfirm": "\"{{title}}\" borcu silinsin mi? Bütçeye işlenmiş ödemeler de kaldırılır.", + "deleteLoanPaymentConfirm": "Bu kredi ödemesi silinsin mi?", + "loanRemainingAmount": "Kalan", + "loanRemainingInstallments": "Kalan taksit", + "loanPaidAmount": "Ödenen", + "loansEmpty": "Aktif borç yok.", + "loanInstallmentMeta": "{{paid}} / {{total}} taksit ödendi", + "loanRemainingOf": "{{total}} içinden", + "loanNextDue": "Sonraki: {{month}}", + "loanPaidStatus": "Ödendi", + "markLoanPaid": "Ödendi işaretle", + "loanBorrowerLabel": "Kişi *", + "loanBorrowerPlaceholder": "Örn. Lais", + "loanTitleLabel": "Borç başlığı", + "loanTitlePlaceholder": "Örn. Kişisel borç", + "loanAmountLabel": "Toplam tutar *", + "loanInstallmentsLabel": "Taksitler *", + "loanStartMonthLabel": "İlk vade ayı *", + "loanNotesLabel": "Notlar", + "loanBorrowerRequired": "Kişi gerekli", + "loanInstallmentsRequired": "Taksit sayısını girin", + "loanStartMonthRequired": "İlk vade ayını girin", + "loanAddedToast": "Borç eklendi", + "loanSavedToast": "Borç kaydedildi", + "loanDeletedToast": "Borç silindi", + "loanPaymentAddedToast": "Ödeme kaydedildi", + "loanPaymentTitle": "Kredi geri ödemesi: {{borrower}}", + "typeLoan": "Borç", + "tabsLabel": "Bütçe bölümleri", + "budgetTab": "Bütçe", + "loansTab": "Borçlar", + "filteredTransactions": "Filtrelenmiş işlemler", + "clearLoanFilter": "Filtreyi temizle", + "loanFilterActive": "Borç: {{title}}", + "filterLoanTransactions": "Bu borcun işlemlerini göster", + "loansEmptyDescription": "+ düğmesinden Borç seçerek yeni bir borç oluşturun.", + "newCategoryTitle": "Yeni kategori", + "newCategoryPlaceholder": "Kategori adı", + "newSubcategoryTitle": "Yeni alt kategori", + "newSubcategoryPlaceholder": "Alt kategori adı", + "loanStatusFilterLabel": "Borç durumu filtresi", + "loanStatusActive": "Aktif", + "loanStatusPaid": "Ödendi", + "loanStatusAll": "Tümü", + "loanTransactions": "Borç işlemleri", + "loanInstallmentNumber": "{{total}} taksitten {{number}}.", + "loanReportTitle": "Borç raporu", + "loanNoTransactions": "Henüz ödeme kaydedilmedi." }, "settings": { "title": "Ayarlar", diff --git a/public/locales/uk.json b/public/locales/uk.json index c2d66a7..88f277e 100644 --- a/public/locales/uk.json +++ b/public/locales/uk.json @@ -112,7 +112,13 @@ "customizeMoveUp": "Перемістити вгору", "customizeMoveDown": "Перемістити вниз", "overdueTasksChip": "{{count}} прострочене завдання", - "overdueTasksChipPlural": "{{count}} прострочених завдань" + "overdueTasksChipPlural": "{{count}} прострочених завдань", + "customizeManage": "Віджети", + "customizeExit": "Вийти з налаштування", + "customizeDrag": "Перетягнути віджет", + "customizeSize": "Розмір", + "customizeSizeFor": "Розмір для {{widget}}", + "customizeHide": "Приховати {{widget}}" }, "tasks": { "title": "Завдання", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "Позики / Відсотки", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "Додати запис" + "emptyAction": "Додати запис", + "loansTitle": "Позики", + "loansSummary": "{{count}} активних · залишилось {{amount}}", + "newLoan": "Нова позика", + "createLoan": "Створити позику", + "editLoan": "Редагувати позику", + "deleteLoan": "Видалити позику", + "deleteLoanConfirm": "Видалити позику «{{title}}»? Платежі, вже додані до бюджету, також буде видалено.", + "deleteLoanPaymentConfirm": "Видалити цей платіж за позикою?", + "loanRemainingAmount": "Залишилось", + "loanRemainingInstallments": "Залишилось платежів", + "loanPaidAmount": "Сплачено", + "loansEmpty": "Немає активних позик.", + "loanInstallmentMeta": "Сплачено {{paid}} з {{total}} платежів", + "loanRemainingOf": "з {{total}}", + "loanNextDue": "Наступний: {{month}}", + "loanPaidStatus": "Сплачено", + "markLoanPaid": "Позначити сплату", + "loanBorrowerLabel": "Людина *", + "loanBorrowerPlaceholder": "Напр. Lais", + "loanTitleLabel": "Назва позики", + "loanTitlePlaceholder": "Напр. Особиста позика", + "loanAmountLabel": "Загальна сума *", + "loanInstallmentsLabel": "Платежі *", + "loanStartMonthLabel": "Перший місяць сплати *", + "loanNotesLabel": "Нотатки", + "loanBorrowerRequired": "Вкажіть людину", + "loanInstallmentsRequired": "Вкажіть кількість платежів", + "loanStartMonthRequired": "Вкажіть перший місяць сплати", + "loanAddedToast": "Позику додано", + "loanSavedToast": "Позику збережено", + "loanDeletedToast": "Позику видалено", + "loanPaymentAddedToast": "Платіж записано", + "loanPaymentTitle": "Платіж за позикою: {{borrower}}", + "typeLoan": "Позика", + "tabsLabel": "Розділи бюджету", + "budgetTab": "Бюджет", + "loansTab": "Позики", + "filteredTransactions": "Відфільтровані операції", + "clearLoanFilter": "Очистити фільтр", + "loanFilterActive": "Позика: {{title}}", + "filterLoanTransactions": "Показати операції цієї позики", + "loansEmptyDescription": "Створіть позику кнопкою + і виберіть Позика.", + "newCategoryTitle": "Нова категорія", + "newCategoryPlaceholder": "Назва категорії", + "newSubcategoryTitle": "Нова підкатегорія", + "newSubcategoryPlaceholder": "Назва підкатегорії", + "loanStatusFilterLabel": "Фільтр статусу позик", + "loanStatusActive": "Активні", + "loanStatusPaid": "Сплачені", + "loanStatusAll": "Усі", + "loanTransactions": "Операції позики", + "loanInstallmentNumber": "Платіж {{number}} з {{total}}", + "loanReportTitle": "Звіт по позиці", + "loanNoTransactions": "Платежі ще не записано." }, "settings": { "title": "Налаштування", diff --git a/public/locales/zh.json b/public/locales/zh.json index e12f0c5..0220a8b 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -112,7 +112,13 @@ "customizeMoveUp": "上移", "customizeMoveDown": "下移", "overdueTasksChip": "{{count}} 个逾期任务", - "overdueTasksChipPlural": "{{count}} 个逾期任务" + "overdueTasksChipPlural": "{{count}} 个逾期任务", + "customizeManage": "小组件", + "customizeExit": "退出自定义", + "customizeDrag": "拖动小组件", + "customizeSize": "大小", + "customizeSizeFor": "{{widget}} 的大小", + "customizeHide": "隐藏 {{widget}}" }, "tasks": { "title": "任务", @@ -572,7 +578,7 @@ "subcatCoursesCollege": "Courses / College", "subcatSchoolSupplies": "School supplies", "subcatLanguages": "Languages", - "subcatLoansInterest": "Loans / Interest", + "subcatLoansInterest": "借款 / 利息", "subcatBankFees": "Bank fees", "subcatInsuranceOther": "Insurance", "subcatInvestments": "Investments", @@ -584,7 +590,61 @@ "newSubcategoryPrompt": "Name of the new subcategory:", "categoryAddedToast": "Category added.", "subcategoryAddedToast": "Subcategory added.", - "emptyAction": "添加记录" + "emptyAction": "添加记录", + "loansTitle": "借款", + "loansSummary": "{{count}} 笔进行中 · 剩余 {{amount}}", + "newLoan": "新建借款", + "createLoan": "创建借款", + "editLoan": "编辑借款", + "deleteLoan": "删除借款", + "deleteLoanConfirm": "删除借款“{{title}}”?已记入预算的还款也会被删除。", + "deleteLoanPaymentConfirm": "删除这笔借款还款?", + "loanRemainingAmount": "剩余金额", + "loanRemainingInstallments": "剩余期数", + "loanPaidAmount": "已还金额", + "loansEmpty": "没有进行中的借款。", + "loanInstallmentMeta": "已还 {{paid}} / {{total}} 期", + "loanRemainingOf": "共 {{total}}", + "loanNextDue": "下一期:{{month}}", + "loanPaidStatus": "已还清", + "markLoanPaid": "标记已还", + "loanBorrowerLabel": "借款人 *", + "loanBorrowerPlaceholder": "例如:Lais", + "loanTitleLabel": "借款标题", + "loanTitlePlaceholder": "例如:个人借款", + "loanAmountLabel": "总金额 *", + "loanInstallmentsLabel": "期数 *", + "loanStartMonthLabel": "首期月份 *", + "loanNotesLabel": "备注", + "loanBorrowerRequired": "请填写借款人", + "loanInstallmentsRequired": "请输入期数", + "loanStartMonthRequired": "请输入首期月份", + "loanAddedToast": "借款已添加", + "loanSavedToast": "借款已保存", + "loanDeletedToast": "借款已删除", + "loanPaymentAddedToast": "还款已记录", + "loanPaymentTitle": "借款还款:{{borrower}}", + "typeLoan": "借款", + "tabsLabel": "预算分区", + "budgetTab": "预算", + "loansTab": "借款", + "filteredTransactions": "已筛选交易", + "clearLoanFilter": "清除筛选", + "loanFilterActive": "借款:{{title}}", + "filterLoanTransactions": "显示此借款的交易", + "loansEmptyDescription": "点击 + 按钮并选择借款来创建。", + "newCategoryTitle": "新类别", + "newCategoryPlaceholder": "类别名称", + "newSubcategoryTitle": "新子类别", + "newSubcategoryPlaceholder": "子类别名称", + "loanStatusFilterLabel": "借款状态筛选", + "loanStatusActive": "进行中", + "loanStatusPaid": "已还清", + "loanStatusAll": "全部", + "loanTransactions": "借款交易", + "loanInstallmentNumber": "第 {{number}} / {{total}} 期", + "loanReportTitle": "借款报告", + "loanNoTransactions": "尚未记录还款。" }, "settings": { "title": "设置", diff --git a/public/pages/budget.js b/public/pages/budget.js index c454be1..c076aa3 100644 --- a/public/pages/budget.js +++ b/public/pages/budget.js @@ -6,7 +6,7 @@ */ import { api } from '/api.js'; -import { openModal as openSharedModal, closeModal } from '/components/modal.js'; +import { openModal as openSharedModal, closeModal, confirmModal } from '/components/modal.js'; import { stagger, vibrate } from '/utils/ux.js'; import { t, formatDate, getLocale } from '/i18n.js'; import { esc } from '/utils/html.js'; @@ -124,6 +124,10 @@ let state = { entries: [], summary: null, prevSummary: null, // Vormonat für Monatsvergleich + loans: { loans: [], summary: { active_count: 0, remaining_amount: 0, remaining_installments: 0 } }, + activeTab: 'budget', + loanFilterId: null, + loanStatusFilter: 'active', currency: 'EUR', meta: { expenseCategories: [], incomeCategories: [], expenseSubcategories: {} }, }; @@ -148,6 +152,11 @@ function addMonths(ym, n) { return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; } +function setHtml(element, html) { + element.replaceChildren(); + element.insertAdjacentHTML('afterbegin', html); +} + // -------------------------------------------------------- // API // -------------------------------------------------------- @@ -155,21 +164,24 @@ function addMonths(ym, n) { async function loadMonth(month) { const prevMonth = addMonths(month, -1); try { - const [entriesRes, summaryRes, prevSummaryRes] = await Promise.all([ + const [entriesRes, summaryRes, prevSummaryRes, loansRes] = await Promise.all([ api.get(`/budget?month=${month}`), api.get(`/budget/summary?month=${month}`), api.get(`/budget/summary?month=${prevMonth}`), + api.get('/budget/loans'), ]); state.month = month; state.entries = entriesRes.data; state.summary = summaryRes.data; state.prevSummary = prevSummaryRes.data; + state.loans = loansRes.data; } catch (err) { console.error('[Budget] loadMonth Fehler:', err); state.month = month; state.entries = []; state.summary = { income: 0, expenses: 0, balance: 0, byCategory: [] }; state.prevSummary = null; + state.loans = { loans: [], summary: { active_count: 0, remaining_amount: 0, remaining_installments: 0 } }; window.oikos?.showToast(t('budget.loadError'), 'danger'); } } @@ -206,7 +218,7 @@ export async function render(container, { user }) { state.currency = prefsRes.data?.currency ?? 'EUR'; } catch (_) { /* Fallback auf EUR */ } - container.innerHTML = ` + setHtml(container, `