/** * Arayüz metinleri (tr-TR). Kullanıcıya görünen tüm metinler burada toplanır. * Şimdilik tek dil; ileride çok dil gerekirse bu nesnenin şekli sözleşme olur. */ export const tr = { app: { name: "BÜTÇEM", tagline: "Aile bütçesi, birikim, ev stoğu ve akıllı alışveriş", version: "Sürüm", }, common: { save: "Kaydet", cancel: "Vazgeç", close: "Kapat", delete: "Sil", edit: "Düzenle", create: "Oluştur", search: "Ara", actions: "İşlemler", loading: "Yükleniyor…", comingSoon: "Yakında", required: "Bu alan zorunlu", yes: "Evet", no: "Hayır", previous: "Önceki", next: "Sonraki", noResults: "Sonuç bulunamadı.", page: (current: number, total: number) => `Sayfa ${current} / ${total}`, rowsPerPage: "Sayfa başına", totalRows: (n: number) => `Toplam ${n} kayıt`, showPassword: "Şifreyi göster", hidePassword: "Şifreyi gizle", genericError: "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin.", unauthorized: "Bu işlem için yetkiniz yok.", notFound: "Kayıt bulunamadı.", }, swatches: { blue: "Mavi", sky: "Gök mavisi", teal: "Turkuaz", green: "Yeşil", lime: "Fıstık yeşili", amber: "Kehribar", orange: "Turuncu", red: "Kırmızı", rose: "Gül", pink: "Pembe", purple: "Mor", indigo: "Çivit", slate: "Gri", }, theme: { label: "Tema", light: "Açık", dark: "Koyu", system: "Sistem", }, nav: { main: "Menü", dashboard: "Ana sayfa", transactions: "İşlemler", accounts: "Hesaplar", categories: "Kategoriler", budget: "Bütçe", planned: "Planlı işlemler", contacts: "Cari hesaplar", savings: "Birikim", stock: "Ev stoğu", stores: "Mağazalar", shopping: "Alışveriş", reports: "Raporlar", settings: "Ayarlar", more: "Daha fazla", admin: "Yönetim", adminUsers: "Kullanıcılar", adminHouseholds: "Haneler", toggleSidebar: "Menüyü aç/kapat", }, household: { label: "Aktif hane", select: "Hane seçin", roles: { owner: "Sahip", member: "Üye", viewer: "İzleyici" }, roleHints: { owner: "Hane ayarları, üyeler ve hesaplar", member: "İşlem girer, liste ve stok günceller", viewer: "Yalnızca görüntüler", }, switched: (name: string) => `Aktif hane: ${name}`, }, households: { lastOwner: "Hanenin son sahibi düşürülemez veya çıkarılamaz.", noHousehold: { title: "Henüz bir haneye üye değilsiniz", description: "Bütçe ve diğer verileri görmek için bir haneye üye olmanız gerekir. Yöneticiden sizi bir haneye eklemesini isteyin.", adminHint: "Yönetici olarak Yönetim › Haneler sayfasından hane oluşturabilir ve üye ekleyebilirsiniz.", adminLink: "Hanelere git", }, viewerReadOnly: "İzleyici rolündesiniz; bu hanede değişiklik yapamazsınız.", }, settings: { title: "Ayarlar", description: "Aktif hanenin ayarları ve üyeleri.", household: "Hane", householdDescription: "Bütçe ve planlama tercihleri tüm hane için geçerlidir.", ownerOnly: "Bu ayarları yalnızca hane sahipleri değiştirebilir.", fields: { name: "Hane adı", budgetMonthStartDay: "Bütçe ayı başlangıç günü", budgetMonthStartDayHint: "1 = takvim ayı. Örneğin 15 seçilirse bütçe ayı her ayın 15. günü başlar.", installmentBudgetMode: "Taksitlerin bütçeye etkisi", installmentModes: { per_installment: "Her taksit kendi ayına", purchase_month: "Tamamı harcama ayına", }, dailyPlanMode: "Günlük plan dağıtımı", dailyPlanModes: { even: "Değişken bütçe günlere eşit", previous_month_pattern: "Önceki ayın harcama örüntüsüne göre", }, includePrivateAccountsInTotals: "“Yalnızca ben” hesapları hane toplamlarına dahil edilsin", extraStoreSavingThreshold: "Ek mağaza tasarruf eşiği (TL)", extraStoreSavingThresholdHint: "Alışveriş planlayıcı, ek bir mağazayı yalnızca tasarruf bu tutarı aşarsa önerir.", }, saved: "Hane ayarları kaydedildi.", members: "Üyeler", membersDescription: "Hane içi roller. Yeni üyeyi yönetici ekler.", memberActions: (name: string) => `${name} — işlemler`, changeRole: "Rolü değiştir", removeMember: "Haneden çıkar", removeTitle: "Üye haneden çıkarılsın mı?", removeDescription: (name: string, household: string) => `${name}, “${household}” hanesine artık erişemeyecek. Kullanıcı hesabı silinmez.`, removeConfirm: "Haneden çıkar", roleChanged: (name: string) => `${name} için rol güncellendi.`, memberRemoved: (name: string) => `${name} haneden çıkarıldı.`, banned: "Askıda", }, accounts: { title: "Hesaplar", description: "Nakit, banka, birikim, kredi kartı ve yemek kartı hesapları.", newAccount: "Yeni hesap", createTitle: "Yeni hesap", editTitle: "Hesabı düzenle", formDescription: "Güncel bakiye işlemlerden hesaplanır; açılış bakiyesi başlangıç noktasıdır.", types: { cash: "Nakit", bank: "Vadesiz banka", savings: "Birikim / vadeli", credit_card: "Kredi kartı", meal_card: "Yemek kartı", }, typeGroups: { cash: "Nakit", bank: "Banka hesapları", savings: "Birikim hesapları", credit_card: "Kredi kartları", meal_card: "Yemek kartları", }, providers: { pluxee: "Pluxee (Sodexo)", multinet: "Multinet", edenred: "Edenred (Ticket)", setcard: "Setcard", metropol: "Metropol", other: "Diğer", }, fields: { name: "Hesap adı", type: "Tür", typeLockedHint: "Hesap türü oluşturulduktan sonra değiştirilemez.", institution: "Banka / kurum", institutionPlaceholder: "ör. Ziraat Bankası", provider: "Kart sağlayıcısı", openingBalance: "Açılış bakiyesi (TL)", openingDebt: "Açılış borcu (TL)", openingBalanceHint: "Banka hesabı KMH kullanıyorsa eksi girilebilir (ör. -2.500,00).", openingDebtHint: "Karttaki mevcut toplam borç; pozitif girin.", openingDate: "Açılış tarihi", owner: "Hesap sahibi", ownerNone: "— Ortak hesap —", isPrivate: "Yalnızca ben (bakiyeyi yalnızca hesap sahibi görür)", appearance: "Görünüm", advanced: "Gelişmiş ayarlar", overdraft: "Esnek hesap (KMH)", overdraftEnabled: "Bu hesapta KMH var", overdraftLimit: "KMH limiti (TL)", overdraftRate: "Aylık faiz oranı (%)", overdraftStatementDay: "Hesap kesim günü", card: "Kart bilgileri", cardLimit: "Kart limiti (TL)", cardStatementDay: "Hesap kesim günü", cardStatementDayHint: "Ayda o gün yoksa (ör. 31) ayın son günü kullanılır.", cardDueKind: "Son ödeme günü", dueKinds: { daysAfter: "Kesimden N gün sonra", fixedDay: "Ayın sabit günü" }, cardDueValueDays: "Gün sayısı", cardDueValueDay: "Ayın günü", cardPaymentAccount: "Ödeme hesabı", cardPaymentAccountNone: "— Seçilmedi —", cardMinimumRate: "Asgari ödeme oranı (%)", cardMinimumRateHint: "Boş bırakılırsa limit 50.000 TL'nin altındaysa %20, üstündeyse %40 kullanılır.", }, summary: { assets: "Varlıklar", cardDebt: "Kart borçları", net: "Net", includesHidden: "Toplamlara gizli hesaplar dahil.", excludesHidden: "Gizli hesaplar toplamlara dahil değil (hane ayarı).", }, balance: "Bakiye", debt: "Borç", hidden: "Gizli", hiddenHint: "Bu hesap “yalnızca ben” olarak işaretli; bakiyeyi yalnızca hesap sahibi görür.", privateBadge: "Yalnızca ben", overdraftBadge: (limit: string) => `KMH ${limit}`, limitLabel: (limit: string) => `Limit ${limit}`, statementLabel: (day: number) => `Kesim: ${day}`, empty: "Henüz hesap yok.", emptyOwnerHint: "Başlamak için ilk hesabınızı ekleyin (ör. nakit cüzdan, maaş hesabı).", archivedSection: (n: number) => `Arşivlenmiş hesaplar (${n})`, archive: "Arşivle", unarchive: "Arşivden çıkar", archiveTitle: "Hesap arşivlensin mi?", archiveDescription: (name: string) => `“${name}” yeni işlemlerde seçilemez; geçmiş işlemler ve raporlar korunur. İstediğiniz zaman arşivden çıkarabilirsiniz.`, created: (name: string) => `${name} oluşturuldu.`, updated: (name: string) => `${name} güncellendi.`, archivedToast: (name: string) => `${name} arşivlendi.`, unarchivedToast: (name: string) => `${name} arşivden çıkarıldı.`, ownerNotMember: "Hesap sahibi bu hanenin üyesi olmalı.", invalidPaymentAccount: "Ödeme hesabı bu hanedeki aktif bir banka, nakit veya birikim hesabı olmalı.", typeLocked: "Hesap türü değiştirilemez.", ownerOnly: "Hesapları yalnızca hane sahipleri yönetebilir.", }, transactions: { title: "İşlemler", description: "Gelir, gider ve transferler.", new: "Yeni işlem", types: { expense: "Gider", income: "Gelir", transfer: "Transfer" }, statuses: { posted: "Gerçekleşti", planned: "Planlı", void: "İptal" }, createTitle: { expense: "Yeni gider", income: "Yeni gelir", transfer: "Yeni transfer" }, editTitle: "İşlemi düzenle", copyTitle: "İşlemi kopyala", fields: { amount: "Tutar", date: "Tarih", account: "Hesap", fromAccount: "Kaynak hesap", toAccount: "Hedef hesap", category: "Kategori", selectCategory: "Kategori seçin", selectAccount: "Hesap seçin", payee: "Satıcı / karşı taraf", payeePlaceholder: "ör. Migros", description: "Açıklama", tags: "Etiketler", tagsHint: "Virgülle ayırın (ör. tatil, indirim)", advanced: "Gelişmiş: ek, etiket, bölme", split: "Bölünmüş işlem", splitHint: "Tutarı birden çok kategoriye bölün; kalemlerin toplamı tutara eşit olmalı.", addSplit: "Kalem ekle", removeSplit: "Kalemi kaldır", splitNote: "Not", remaining: "Kalan", remainingOk: "Kalemler toplamı tutara eşit", fillRemaining: "Kalanı son kaleme ekle", suggested: "Bu satıcı için son kullanılan kategori ve hesap önerildi.", installments: "Taksit", singlePayment: "Peşin", installmentCount: (n: number) => `${n} taksit`, installmentHint: (n: number, each: string) => `${n} × yaklaşık ${each}; vadesi gelen taksit kendi döneminde otomatik gerçekleşir.`, }, validation: { amountPositive: "Tutar sıfırdan büyük olmalı", selectAccount: "Hesap seçin", selectToAccount: "Hedef hesabı seçin", sameAccount: "Kaynak ve hedef hesap aynı olamaz", selectCategory: "Kategori seçin", splitMin: "Bölünmüş işlemde en az 2 kalem olmalı", splitSum: "Kalemlerin toplamı tutara eşit olmalı", accountInvalid: "Hesap bu hanede yok, arşivli veya size kapalı.", categoryInvalid: "Kategori bu hanede yok, arşivli veya işlem türüyle uyuşmuyor.", installmentsMax: "En fazla 36 taksit", installmentsExpenseOnly: "Taksit yalnızca bölünmemiş kredi kartı giderinde kullanılabilir.", installmentsCardOnly: "Taksit yalnızca kredi kartı hesabında kullanılabilir.", }, list: { empty: "Bu filtrelerle işlem bulunamadı.", emptyAll: "Henüz işlem yok.", split: (n: number) => `Bölünmüş · ${n} kalem`, transfer: (from: string, to: string) => `${from} → ${to}`, dayTotal: "Günlük net", total: (n: number) => `${n} işlem`, sums: { income: "Gelir", expense: "Gider", net: "Net" }, hiddenAccount: "Gizli hesap", hiddenContact: "Gizli cari", }, filters: { title: "Filtreler", open: "Filtrele", apply: "Uygula", clear: "Temizle", from: "Başlangıç", to: "Bitiş", type: "Tür", account: "Hesap", category: "Kategori", person: "Ekleyen", status: "Durum", min: "En az (TL)", max: "En çok (TL)", tag: "Etiket", search: "Ara", searchPlaceholder: "Açıklama, satıcı veya not…", all: "Tümü", active: (n: number) => `${n} filtre`, }, detail: { title: "İşlem ayrıntısı", lines: "Kalemler", createdBy: "Ekleyen", updatedBy: "Son düzenleyen", createdAt: "Oluşturulma", }, actions: { edit: "Düzenle", copy: "Kopyala", delete: "Sil", restore: "Geri al" }, toast: { created: "İşlem kaydedildi.", updated: "İşlem güncellendi.", deleted: "İşlem silindi.", restored: "İşlem geri alındı.", installmentsCancelled: (n: number) => `${n} kalan taksit iptal edildi.`, }, deleteTitle: "İşlem silinsin mi?", deleteDescription: "İşlem listeden ve bakiyelerden kaldırılır. Bildirimdeki “Geri al” ile geri getirebilirsiniz.", export: "CSV indir", csv: { header: [ "İşlem No", "Tarih", "Tür", "Durum", "Hesap", "Hedef hesap", "Kategori", "Satıcı", "Açıklama", "Kalem notu", "Etiketler", "Tutar", "Ekleyen", ], filename: (date: string) => `butcem-islemler-${date}.csv`, }, adjustment: "Mutabakat düzeltmesi", adjustmentReadOnly: "Mutabakat düzeltmesi düzenlenemez; gerekirse silip mutabakatı yeniden yapın.", reconciled: "Mutabakatı yapıldı", cancelInstallments: "Kalan taksitleri iptal et", contactEditHint: "Cari hareketi cari sayfasından düzenlenir.", inKindPaymentLocked: "Aynî borç ödemesi silinemez; ödeme cari sayfasındaki kayda bağlıdır.", assetLocked: "Varlık alım/satış işlemi Birikim sayfasındaki hareketten yönetilir.", readOnly: "İzleyici rolündesiniz; işlem ekleyemezsiniz.", noAccounts: "İşlem girmek için önce bir hesap gerekli.", noAccountsLink: "Hesaplara git", }, recurring: { title: "Planlı işlemler", description: "Düzenli ve planlı gelir/giderler. Planlı kayıtlar bakiyeyi etkilemez; onaylanınca gerçekleşir.", newRule: "Yeni düzenli işlem", createTitle: "Yeni düzenli işlem", editTitle: "Düzenli işlemi düzenle", tabs: { upcoming: "Yaklaşan", overdue: "Vadesi geçmiş", rules: "Kurallar" }, fields: { estimate: "Tutar tahmini (ör. fatura); onaylarken düzeltilir", startDate: "İlk tarih", frequency: "Sıklık", interval: "Kaç birimde bir", monthlyMode: "Ayın hangi günü", end: "Bitiş", count: "Tekrar sayısı", endDate: "Bitiş tarihi", preview: "İlk tarihler", }, frequencies: { daily: "Günlük", weekly: "Haftalık", monthly: "Aylık", yearly: "Yıllık" }, units: { daily: "gün", weekly: "hafta", monthly: "ay", yearly: "yıl" }, monthlyModes: { day: "İlk tarihin günü", last: "Ayın son günü" }, endKinds: { never: "Bitiş yok", count: "Tekrar sayısı", date: "Bitiş tarihi" }, actions: { confirm: "Onayla", skip: "Atla", postpone: "Ertele", edit: "Düzenle", delete: "Sil", more: "Diğer işlemler", }, confirmTitle: "İşlemi onayla", confirmDescription: "Gerçekleşen tutarı ve tarihi kontrol edin; onaylanınca bakiyeye yansır.", postponeTitle: "Ertele", postponeDate: "Yeni tarih", scopeTitle: "Hangi kayıtlar değişsin?", scopes: { one: "Yalnızca bu", following: "Bu ve sonrakiler", all: "Tümü" }, scopeHints: { one: "Yalnızca bu planlı kayıt değişir; seri aynı kalır.", following: "Seri bu tarihten itibaren yeni değerlerle devam eder.", all: "Onaylanmamış tüm planlı kayıtlar yeni değerlerle yeniden oluşturulur. Gerçekleşmiş kayıtlar değişmez.", }, deleteTitle: "Düzenli işlem silinsin mi?", deleteDescription: "Gerçekleşmiş kayıtlar korunur; yalnızca onaylanmamış planlı kayıtlar silinir.", deleteScopes: { following: "Bu ve sonrakileri sil", all: "Tüm seriyi sil" }, estimate: "Tahmini", next: (date: string) => `Sıradaki: ${date}`, remaining: (n: number) => `${n} tekrar kaldı`, endless: "Süresiz", series: (pos: string) => `${pos}`, empty: { upcoming: "Önümüzdeki 60 günde planlı işlem yok.", overdue: "Vadesi geçmiş planlı işlem yok.", rules: "Henüz düzenli işlem yok. Kira, faturalar ve abonelikler için ekleyin.", }, overdueBanner: (n: number) => `${n} planlı işlemin tarihi geçti; onaylayın, erteleyin veya atlayın.`, overdueLink: "Planlı işlemlere git", upcomingTitle: "Yaklaşan planlı işlemler", toast: { created: "Düzenli işlem kaydedildi.", updated: "Düzenli işlem güncellendi.", deleted: "Düzenli işlem silindi.", confirmed: "İşlem onaylandı.", skipped: "Bu tekrar atlandı.", postponed: "İşlem ertelendi.", }, validation: { interval: "1 ile 12 arasında olmalı", count: "1 ile 600 arasında bir sayı girin", endBeforeStart: "Bitiş tarihi ilk tarihten önce olamaz", }, errors: { splitAmount: "Bölünmüş planlı işlemin tutarı değiştirilemez.", postponeDate: "Yeni tarih mevcut tarihten sonra olmalı.", }, }, attachments: { title: "Ekler", add: "Ek ekle", addHint: { image: "Fiş veya fatura fotoğrafı", imagePdf: "Görsel veya PDF (ör. bordro)" }, count: (n: number) => `${n} ek`, uploading: "Yükleniyor…", remove: "Eki kaldır", open: "Aç", download: "İndir", fullscreen: "Tam ekran", exitFullscreen: "Tam ekrandan çık", previous: "Önceki", next: "Sonraki", position: (i: number, n: number) => `${i} / ${n}`, viewerTitle: "Ek dosyalar", pdf: "PDF belgesi", moreCount: (n: number) => `+${n}`, waitForUploads: "Yüklemeler bitmeden kaydedilemez.", errors: { empty: "Dosya seçilmedi veya dosya boş.", tooLarge: (mb: number) => `Dosya çok büyük (en fazla ${mb} MB).`, tooMany: (n: number) => `Bir kayda en fazla ${n} dosya eklenebilir.`, tooManyPending: "Kaydedilmemiş çok fazla ek var; önce formu kaydedin.", unsupported: "Desteklenmeyen dosya türü. JPEG, PNG, WebP, HEIC veya PDF yükleyin.", unreadable: "Dosya okunamadı veya bozuk.", kindNotAllowed: "Gider işlemlerine yalnızca görsel eklenebilir (PDF gelir ve transferlerde).", invalid: "Ek dosya bulunamadı veya bu kayda eklenemez.", upload: "Dosya yüklenemedi.", }, }, contacts: { title: "Cari hesaplar", description: "Kişilerle borç-alacak takibi. Cari hareketleri transferdir; gelir/gider raporlarına girmez.", contact: "Cari", openContact: "Cariyi aç", new: "Yeni cari", createTitle: "Yeni cari", editTitle: "Cariyi düzenle", relations: { family: "Aile / akraba", friend: "Arkadaş", neighbor: "Komşu", work: "İş", other: "Diğer", }, kinds: { lend: "Borç verdim", repay: "Borç ödedim", borrow: "Borç aldım", collect: "Tahsilat" }, kindHints: { lend: "Hesabınızdan kişiye para verdiniz; size borçlanır.", repay: "Kişiye olan borcunuzu hesabınızdan ödediniz.", borrow: "Kişiden hesabınıza para aldınız; ona borçlanırsınız.", collect: "Kişinin size olan borcunu hesabınıza tahsil ettiniz.", }, fields: { name: "Ad soyad", relation: "Yakınlık", phone: "Telefon", note: "Not", openingBalance: "Açılış bakiyesi (TL)", openingHint: "Uygulamadan önceki durum: size borçluysa pozitif, siz borçluysanız başına - koyarak girin.", isPrivate: "Yalnızca ben (bu cariyi ve hareketlerini yalnızca ben görürüm)", dueDate: "Vade tarihi", dueHint: "Kalan bakiyenin ödenmesi beklenen tarih (isteğe bağlı).", reminderDays: "Kaç gün önce uyarılsın", account: "Hesap", fromAccount: "Ödemenin çıktığı hesap", toAccount: "Paranın girdiği hesap", }, balance: { owesMe: "Bana borçlu", iOwe: "Ben borçluyum", settled: "Hesap kapalı" }, summary: { owesMe: "Bana borçlu", iOwe: "Ben borçluyum", net: "Net" }, newEntry: "Hareket ekle", entryTitle: "Cari hareketi", editEntryTitle: "Cari hareketini düzenle", due: { overdue: (d: string) => `Vade geçti · ${d}`, upcoming: (d: string) => `Vade yaklaşıyor · ${d}`, on: (d: string) => `Vade · ${d}`, }, dueBanner: (n: number) => `${n} carinin vadesi geçti veya yaklaşıyor.`, dueLink: "Carilere git", statement: "Cari ekstresi", opening: "Açılış bakiyesi", runningBalance: "Bakiye", lastActivity: (d: string) => `Son hareket ${d}`, empty: "Henüz cari yok. Borç verdiğiniz veya aldığınız kişileri ekleyin.", emptyEntries: "Henüz hareket yok.", archive: "Arşivle", unarchive: "Arşivden çıkar", archivedSection: (n: number) => `Arşivlenmiş cariler (${n})`, privateBadge: "Yalnızca ben", readOnly: "İzleyici rolündesiniz; cari hareketi ekleyemezsiniz.", toast: { created: "Cari oluşturuldu.", updated: "Cari güncellendi.", entrySaved: "Cari hareketi kaydedildi.", archived: "Cari arşivlendi.", unarchived: "Cari arşivden çıkarıldı.", }, errors: { duplicate: "Bu adla bir cari zaten var.", archived: "Arşivlenmiş cariye hareket eklenemez.", }, }, inKind: { title: "Aynî borç ve alacaklar", description: "Altın, ziynet veya döviz cinsinden borç/alacak. Kapanış yalnızca “Ödeme gerçekleşti” ile.", new: "Aynî kayıt ekle", createTitle: "Yeni aynî borç/alacak", editTitle: "Aynî kaydı düzenle", directions: { debt: "Ben borçluyum", receivable: "Bana borçlu" }, fields: { direction: "Yön", asset: "Varlık", quantity: "Miktar", date: "Borç tarihi", unitPrice: "O tarihteki birim fiyat (TL)", unitPriceHint: "Boş bırakılırsa fiyat tablosundaki o tarihe ait son fiyat kullanılır.", note: "Not", savingsAccount: "Birikim hesabı", savingsNone: "— Birikim planı yok —", monthlyPlan: "Aylık ayrılacak tutar (TL)", planHint: "Borcu kapatmak için her ay bu hesaba para ayırın; borç yalnızca ödeme yapılınca kapanır.", }, stats: { remaining: "Kalan", dateValue: (d: string) => `${d} değeri`, currentValue: "Güncel değer", accumulated: "Biriken", remainingNeed: "Kalan ihtiyaç", estimatedClose: "Tahmini kapanış", noPrice: "Güncel fiyat yok", closed: (d: string) => `Kapandı · ${d}`, priceAt: (price: string, date: string) => `Fiyat ${price} (${date})`, currentPrice: (debt: boolean, price: string, date: string) => `Güncel ${debt ? "satış" : "alış"} fiyatı ${price} · ${date}`, }, contribute: "Birikim ekle", contributionTitle: "Birikim ekle", fromAccount: "Kaynak hesap", contributionDescription: (label: string, name: string) => `Birikim: ${label} borcu (${name})`, pay: "Ödeme gerçekleşti", payTitle: "Ödeme gerçekleşti", methods: { asset: "Aynı varlıkla", cash: "TL karşılığıyla" }, methodHints: { asset: "Varlığın kendisiyle ödendi (ör. kuyumcudan alınan altın verildi).", cash: "Varlığın TL karşılığı ödendi; hesaptan çıkış işlemi oluşturulur.", }, receiveHints: { asset: "Varlığın kendisi teslim alındı.", cash: "Varlığın TL karşılığı hesaba tahsil edildi.", }, payFields: { quantity: "Ödenen miktar", quantityHint: "Boş bırakılırsa tutar güncel fiyata bölünerek hesaplanır.", amount: "Tutar (TL)", assetAmount: "Varlığı almak için harcanan (TL, isteğe bağlı)", account: "Hesap", }, paymentDescription: (debt: boolean, label: string, name: string) => debt ? `Aynî borç ödemesi: ${label} (${name})` : `Aynî alacak tahsilatı: ${label} (${name})`, payments: "Ödemeler", paymentLine: (method: string, qty: string, amount: string | null) => amount ? `${method} · ${qty} · ${amount}` : `${method} · ${qty}`, delete: "Kaydı sil", deleteTitle: "Aynî kayıt silinsin mi?", deleteDescription: "Kayıt listeden kaldırılır. Oluşturulmuş para hareketleri (birikim, ödeme) işlemlerde kalır.", prices: "Fiyat tablosu", toast: { saved: "Aynî kayıt kaydedildi.", contributed: "Birikim eklendi.", paid: "Ödeme kaydedildi.", closed: "Ödeme kaydedildi; kayıt kapandı.", deleted: "Aynî kayıt silindi.", }, errors: { noPrice: "Bu tarih için fiyat yok; birim fiyatı girin veya fiyat tablosunu güncelleyin.", noSavings: "Önce kayda bir birikim hesabı seçin.", closed: "Kayıt kapanmış.", quantityBelowPaid: "Miktar ödenmiş miktardan az olamaz.", receivablePlan: "Birikim planı yalnızca borçlar içindir.", noCurrentPrice: "Güncel fiyat yok; ödenen miktarı girin.", sameAccount: "Kaynak hesap birikim hesabıyla aynı olamaz.", }, validation: { quantity: "Geçerli bir miktar girin (en fazla 3 ondalık)", price: "Alış veya satış fiyatı girin", amount: "Tutar girin", account: "Hesap seçin", assetOnlyWithAsset: "Varlık bağlantısı yalnızca aynı varlıkla ödemede kullanılır.", noAmountWithAsset: "Varlıktan ödemede TL tutar girilmez.", }, link: { debt: "Birikimdeki varlıktan düş", receivable: "Birikimdeki varlığa ekle", debtHint: "Ödenen miktar seçilen varlıktan ortalama maliyetle çıkar.", receivableHint: "Tahsil edilen miktar seçilen varlığa eklenir; maliyet borç tarihindeki birim fiyattır.", asset: "Varlık", none: "Bu türde varlık yok; önce Birikim sayfasından ekleyin.", movementNote: (name: string) => `Aynî kayıt: ${name}`, assetMismatch: "Seçilen varlık bu kaydın varlık türünde değil.", }, }, assets: { title: "Birikim", description: "Altın, döviz ve ziynet birikimleri: alım lotları, satış ve çıkışlar, ortalama maliyet ve kâr/zarar. Değerleme alış fiyatıyla.", new: "Varlık ekle", asset: "Varlık", open: "Varlığa git", createTitle: "Yeni varlık", editTitle: "Varlığı düzenle", empty: "Henüz varlık yok. Bir varlık ekleyip ilk alımı girin.", closedGroup: "Elde kalmayanlar", privateBadge: "Yalnızca ben", fields: { asset: "Varlık türü", name: "Ad", namePlaceholder: "Ör. Gram altın birikimi", note: "Not", isPrivate: "Yalnızca ben görebilirim", isPrivateHint: "İşaretlenirse bu varlık ve hareketleri hanedeki diğer üyelere görünmez.", }, stats: { quantity: "Eldeki miktar", avgCost: "Ortalama maliyet", cost: "Maliyet", currentValue: "Güncel değer", unrealized: "Gerçekleşmemiş K/Z", realized: "Gerçekleşmiş K/Z", invested: "Yatırılan", proceeds: "Satış geliri", noPrice: "Fiyat yok", price: (price: string, date: string) => `Güncel alış fiyatı ${price} · ${date}`, perUnit: (unit: string) => `/ ${unit}`, }, totals: { value: "Toplam güncel değer", cost: "Toplam maliyet", unrealized: "Gerçekleşmemiş K/Z", realized: "Gerçekleşmiş K/Z", missingPrice: (n: number) => `${n} varlığın fiyatı yok; toplam değere katılmadı.`, }, kinds: { buy: "Alım", gift_in: "Hediye / miras geldi", sell: "Satış", gift_out: "Hediye / çıkış", }, kindHints: { buy: "Para seçilen hesaptan çıkar (transfer; gider sayılmaz).", gift_in: "Hesap hareketi oluşmaz; maliyet o günkü değerdir.", sell: "Satış tutarı seçilen hesaba girer; ortalama maliyete göre kâr/zarar yazılır.", gift_out: "Hesap hareketi oluşmaz; ortalama maliyetle elden çıkar.", }, movement: { add: "Hareket ekle", title: (kind: string, name: string) => `${kind} · ${name}`, date: "Tarih", quantity: "Miktar", unitPrice: "Birim fiyat (TL)", amount: "Toplam tutar (TL)", priceHint: "Tutar veya birim fiyattan birini girin; ikisi de boşsa fiyat tablosu kullanılır (alımda satış, satışta alış fiyatı).", giftValueHint: "Boş bırakılırsa fiyat tablosundaki o günkü alış fiyatı kullanılır.", account: "Hesap", accountNone: "— Hesap yok —", accountHint: "Hesap seçilmezse hesap hareketi oluşmaz.", storage: "Saklama yeri", storagePlaceholder: "Ör. ev kasası, banka kiralık kasa", note: "Not", held: (q: string) => `Eldeki: ${q}`, }, history: "Hareketler", noMovements: "Henüz hareket yok.", report: { title: "Dönemsel rapor", ranges: { "3": "3 ay", "6": "6 ay", "12": "12 ay", tum: "Tümü" }, rangeLabel: "Dönem", period: (from: string, to: string) => `${from} – ${to}`, startValue: "Dönem başı değer", invested: "Yatırılan", endValue: "Dönem sonu değer", profit: "Dönem kâr/zararı", proceeds: "Satış geliri", giftIn: "Gelen hediye", giftOut: "Çıkan hediye", formula: "Kâr/zarar = dönem sonu değer + satış + çıkan hediye − dönem başı değer − yatırılan − gelen hediye.", value: "Güncel değer", cost: "Maliyet", chartLabel: "Aylık değer ve maliyet", table: "Tablo olarak göster", date: "Tarih", noPrice: "Fiyat yok", excluded: (n: number) => `${n} varlık fiyatı olmadığı için rapora katılmadı.`, empty: "Bu dönemde gösterilecek varlık yok.", }, netWorth: { title: "Net varlık", description: "Hesaplar + birikim + alacaklar − borçlar (TL ve aynî).", accounts: "Hesap bakiyeleri", cardDebt: "Kart ve KMH borçları", assets: "Birikim (altın, döviz)", contactReceivable: "Cari alacaklar", contactPayable: "Cari borçlar", inKindReceivable: "Aynî alacaklar", inKindPayable: "Aynî borçlar", total: "Net varlık", missingPrice: (n: number) => `${n} kalemin fiyatı yok; toplama katılmadı.`, includesHidden: "Hane ayarı gereği diğer üyelerin gizli hesap bakiyeleri dahil.", }, table: { date: "Tarih", kind: "Hareket", quantity: "Miktar", unitPrice: "Birim fiyat", amount: "Tutar", result: "K/Z", balance: "Kalan", }, deleteMovement: "Hareketi sil", deleteMovementTitle: "Hareket silinsin mi?", deleteMovementDescription: "Hareket ve bağlı hesap işlemi silinir; ortalama maliyet ve kâr/zarar yeniden hesaplanır.", delete: "Varlığı sil", deleteTitle: "Varlık silinsin mi?", deleteDescription: "Yalnızca hareketi olmayan varlık silinebilir.", prices: "Fiyat tablosu", back: "Birikim", txDescription: { buy: (label: string, name: string) => `Varlık alımı: ${label} (${name})`, sell: (label: string, name: string) => `Varlık satışı: ${label} (${name})`, }, toast: { saved: "Varlık kaydedildi.", movement: "Hareket kaydedildi.", movementDeleted: "Hareket silindi.", deleted: "Varlık silindi.", }, errors: { noPrice: "Bu tarih için fiyat yok; tutar veya birim fiyat girin.", insufficient: "Bu tarihte eldeki miktar yetersiz.", deleteBreaks: "Bu hareket silinirse sonraki bir satış/çıkış eldeki miktarı aşar.", hasMovements: "Hareketi olan varlık silinemez; önce hareketleri silin.", assetKeyLocked: "Hareketi olan varlığın türü değiştirilemez.", futureDate: "Gelecek tarihli hareket girilemez.", privateOwner: "Yalnızca sahibi gizliliği değiştirebilir.", }, validation: { noAccountForGift: "Hediye hareketinde hesap seçilmez.", }, }, budget: { title: "Bütçe", description: "Aylık kategori limitleri, gerçekleşen harcama ve ay sonu tahmini. Üst kategori limiti alt kategorileri kapsar.", prevMonth: "Önceki ay", nextMonth: "Sonraki ay", thisMonth: "Bu ay", period: (from: string, to: string) => `${from} – ${to}`, totals: { limit: "Bütçe", actual: "Harcanan", remaining: "Kalan", over: "Aşım", forecast: "Ay sonu tahmini", planned: (amount: string) => `Planlı: ${amount}`, unbudgeted: "Bütçesiz harcama", monthProgress: (day: number, total: number, pct: string) => `Ayın ${day}/${total}. günü (%${pct}).`, }, status: { ok: "Yolunda", warning: "%80 geçildi", over: "Limit aşıldı", full: "Limit doldu", none: "Limitsiz", covered: "Üst kategori limitinde", forecastOver: "Tahmin limiti aşıyor", }, line: { ofLimit: (actual: string, limit: string) => `${actual} / ${limit}`, remaining: (amount: string) => `${amount} kaldı`, over: (amount: string) => `${amount} aşıldı`, forecast: (amount: string) => `Tahmin ${amount}`, planned: (amount: string) => `Planlı ${amount}`, }, uncategorized: "Kategorisiz", empty: "Bu ay için bütçe yok.", emptyHint: "Limitleri elle girebilir, önceki ayın bütçesini kopyalayabilir veya önceki ayın harcamalarından oluşturabilirsiniz.", noSpending: "Bu ay henüz gider yok.", edit: "Limitleri düzenle", editTitle: (month: string) => `Bütçe limitleri · ${month}`, editHint: "Boş bırakılan kategori limitsizdir. Alt kategori limiti üst kategorinin içinde bir alt sınırdır.", editTotal: (amount: string) => `Toplam bütçe: ${amount}`, copyPrevious: "Önceki aydan kopyala", fromActuals: "Önceki ayın harcamalarından oluştur", fromActualsHint: "Ana kategorilerin önceki ay harcaması 100 TL'ye yukarı yuvarlanarak limit olur.", replaceTitle: "Mevcut limitler değiştirilsin mi?", replaceDescription: "Bu ayın tüm limitleri seçilen kaynakla değiştirilir.", replace: "Değiştir", includesHidden: "Hane ayarı gereği diğer üyelerin gizli hesaplarından yapılan harcamalar dahil.", warnings: (n: number) => `${n} kategoride bütçenin %80'i geçildi veya limit aşıldı.`, goToBudget: "Bütçeye git", income: { title: "Gelir planı", description: "Gerçekleşen gelirler, planlı (düzenli) gelirler ve elle eklenen beklenen gelirler.", actual: "Gerçekleşen", pending: "Bekleyen planlı", manual: "Elle eklenen", expected: "Beklenen toplam", plannedLeft: "Plana göre elde kalacak", projectedLeft: "Bu tempoda elde kalacak", plannedLeftHint: "Beklenen gelir − bütçe", projectedLeftHint: "Beklenen gelir − ay sonu tahmini gider", received: "Alındı", planned: "Planlı", empty: "Bu ay için planlı gelir yok.", edit: "Beklenen gelir ekle", editTitle: (month: string) => `Elle eklenen gelirler · ${month}`, editHint: "Planlı işlemi olmayan beklenen gelirler (ör. prim). Gelir gerçekleşip işlem olarak girildiğinde kalemi buradan kaldırın; aksi halde iki kez sayılır.", itemName: "Açıklama", itemAmount: "Tutar", addItem: "Kalem ekle", removeItem: "Kalemi kaldır", saved: "Gelir planı kaydedildi.", }, daily: { title: "Günlük plan", headline: (monthPct: number, spentPct: number) => `Bugün ayın %${monthPct}'si geçti, bütçenin %${spentPct}'i harcandı.`, today: "Bugün için", todayHint: "Bugünün planı + önceki günlerden kalan (veya aşan) tutar", plannedToDate: "Bugüne kadar planlanan", actualToDate: "Bugüne kadar harcanan", projectedLeft: "Bu tempoda ay sonunda elde kalacak", chartLabel: "Kümülatif planlanan ve gerçekleşen gider", cumPlanned: "Planlanan (kümülatif)", cumActual: "Gerçekleşen (kümülatif)", income: "Beklenen gelir", modes: { even: "Değişken bütçe günlere eşit dağıtıldı.", previous_month_pattern: "Değişken bütçe önceki ayın günlük örüntüsüne göre dağıtıldı.", }, fixedNote: (amount: string) => `Tarihe bağlı giderler kendi günlerinde: ${amount}.`, table: "Günleri tablo olarak göster", day: "Gün", planned: "Plan", actual: "Gerçekleşen", noBudget: "Günlük plan için bu ayın bütçesini oluşturun.", next: (month: string) => `Sonraki ay (${month})`, nextIncome: "Beklenen gelir", nextBudget: "Bütçe", nextDiff: "Fark", nextNoBudget: "Bütçe yok", }, toast: { saved: "Bütçe kaydedildi.", copied: "Önceki ayın limitleri kopyalandı.", created: "Limitler önceki ayın harcamalarından oluşturuldu.", }, errors: { noPrevious: "Önceki ay için bütçe yok.", noPreviousSpending: "Önceki ayda gider yok.", category: "Geçersiz veya arşivlenmiş kategori.", }, validation: { month: "Geçersiz ay", category: "Kategori seçin", }, }, stock: { title: "Ev stoğu", description: "Evdeki ürünlerin miktarı, kritik eşik ve son kullanma tarihleri. Stok ürün tipi düzeyinde tutulur.", newProduct: "Yeni ürün tipi", categoriesLink: "Stok kategorileri", countLink: "Sayım", analysisLink: "Tüketim analizi", countNote: "Sayım", countDue: { title: "Sayımı gelenler", description: "Sayım sıklığı dolan kategoriler. Sıklık ürün tipinde veya stok kategorisinde ayarlanır.", products: (n: number) => `${n} ürün`, overdue: (days: number) => (days > 0 ? `${days} gün gecikti` : "Bugün"), start: "Sayıma başla", }, count: { title: "Sayım", description: "Evdeki gerçek miktarları girin. Kayıtlarla arasındaki fark sayım düzeltmesi olur; eksiğin bir kısmını fire olarak işaretleyebilirsiniz. Boş bıraktığınız ürünler sayılmaz.", back: "Ev stoğuna dön", allCategories: "Tüm stok", category: "Kategori", dueCount: (n: number) => `${n} sayımı gelen`, onlyDue: "Yalnızca sayımı gelenler", expected: "Beklenen", actual: "Sayılan", diff: "Fark", same: "Aynı", markWaste: "Eksiğin bir kısmı fire", wasteQuantity: "Fire miktarı", wasteMax: (q: string) => `En çok ${q}`, dueBadge: (days: number) => (days > 0 ? `Sayım ${days} gün gecikti` : "Sayım bugün"), lastCount: (date: string) => `Son sayım ${date}`, neverCounted: "Hiç sayılmadı", fillExpected: "Beklenenle doldur", fillExpectedHint: "Sayılmayan satırlara beklenen miktarı yazar; değişenleri düzeltin.", clear: "Temizle", note: "Not", counted: (n: number) => `${n} ürün sayılacak`, submit: "Sayımı kaydet", empty: "Bu kategoride sayılacak ürün yok.", done: (counted: number, adjusted: number) => adjusted ? `${counted} ürün sayıldı; ${adjusted} üründe fark düzeltildi.` : `${counted} ürün sayıldı; kayıtlarla aynı.`, }, analysis: { title: "Tüketim analizi", description: "Ürün tipi başına aylık tüketim ve fire. Tüketim: girilen tüketimler ve sayımda çıkan eksikler. Maliyet, ürün fiyatları (Faz 12) gelince eklenecek.", back: "Ev stoğuna dön", product: "Ürün tipi", avgUsed: "Aylık ort. tüketim", avgWasted: "Aylık ort. fire", wastePct: "Fire oranı", thisMonth: "Bu ay", trend: (n: number) => `Son ${n} ay`, noData: "—", empty: "Analiz için ürün tipi yok.", chartLabel: (name: string) => `${name}: aylık tüketim`, monthValue: (month: string, used: string, wasted: string) => `${month}: tüketim ${used}, fire ${wasted}`, highWaste: "Fire oranı yüksek", table: "Tablo", }, readOnly: "İzleyici rolündesiniz; stoğu değiştiremezsiniz.", summary: { products: "Ürün tipi", low: "Azalan", expiring: "SKT yaklaşan", expired: "SKT geçmiş", }, suggestions: { title: "Alınması önerilenler", description: "Kritik eşiğin altına düşen ürünler ve hedefe tamamlamak için gereken miktar.", empty: "Eşiğin altına düşen ürün yok.", suggested: (q: string) => `Öneri: ${q}`, wasteReduced: (purchases: number, pct: number) => `Son ${purchases} alımda %${pct} fire, miktar azaltıldı.`, roundedByUsage: (week: string) => `Haftalık tüketime (${week}) göre yuvarlandı.`, covers: (days: number) => `Mevcutla birlikte yaklaşık ${days} gün yeter.`, }, expiring: { title: "Son kullanma tarihi", description: "Evde kalan miktarı olan ve SKT'si 7 gün içinde dolan veya geçmiş partiler.", expired: "Geçti", soon: "Yaklaşıyor", on: (date: string) => `SKT ${date}`, }, list: { empty: "Henüz ürün tipi yok. “Yeni ürün tipi” ile evdeki ürünleri ekleyin.", emptyCategory: "Bu kategoride ürün yok.", search: "Ürün ara", onlyLow: "Yalnızca azalanlar", noMatch: "Aramaya uyan ürün yok.", lowBadge: "Azaldı", outBadge: "Bitti", of: (current: string, target: string) => `${current} / ${target}`, quickConsume: (name: string) => `${name}: 1 azalt`, quickDone: (name: string, rest: string) => `${name} azaltıldı, kalan ${rest}.`, }, fields: { name: "Ad", namePlaceholder: "ör. Toz Deterjan, Kırmızı Mercimek", category: "Stok kategorisi", unit: "Temel ölçü birimi", customUnit: "Özel birim", customUnitOption: "Özel birim…", customUnitPlaceholder: "ör. yıkama, tablet", target: "Hedef (tam) stok", targetHint: "Evde bulunmasını istediğiniz tam miktar.", thresholdPct: "Kritik eşik (%)", thresholdHint: "Mevcut miktar hedefin bu yüzdesinin altına düşerse ürün önerilir.", location: "Saklama yeri", locationPlaceholder: "Kiler, banyo dolabı…", step: "“1 azalt” miktarı", stepHint: "Hızlı azaltma düğmesinin düşeceği miktar.", countEveryDays: "Sayım sıklığı (gün)", countEveryDaysHint: "Boş bırakılırsa kategoriden devralınır.", note: "Not", initialQuantity: "Evdeki mevcut miktar", initialHint: "Tahmini veya ambalaj üzerinden. Boş bırakılırsa 0 kabul edilir.", date: "Tarih", quantity: "Miktar", wasteReason: "Fire nedeni", expiryDate: "Son kullanma tarihi", expiryHint: "İsteğe bağlı. Yaklaşınca uyarı verilir.", actualQuantity: "Sayılan (gerçek) miktar", expected: (q: string) => `Kayıtlara göre beklenen: ${q}`, }, createTitle: "Yeni ürün tipi", editTitle: "Ürün tipini düzenle", kinds: { purchase: "Alım", consume: "Tüketim", waste: "Fire / zarar", count_adjust: "Sayım düzeltmesi", }, actions: { purchase: "Alım ekle", consume: "Tüketim gir", waste: "Fire gir", count: "Sayım yap", }, movementTitles: { purchase: "Alım ekle", consume: "Tüketim gir", waste: "Fire / zarar gir", }, countTitle: "Sayım yap", countDescription: "Evdeki gerçek miktarı girin; kayıtlarla arasındaki fark sayım düzeltmesi olarak işlenir.", wasteReasons: { spoiled: "Bozuldu", expired: "Son kullanma tarihi geçti", damaged: "Hasar / döküldü", other: "Diğer", }, initial: "Başlangıç miktarı", detail: { back: "Ev stoğuna dön", current: "Mevcut", target: "Hedef", threshold: "Eşik", suggested: "Önerilen alım", usage: "Tüketim hızı", perWeek: (q: string) => `Haftada ~${q}`, noUsage: "Henüz yeterli geçmiş yok", countSchedule: "Periyodik sayım", countEvery: (n: number) => `${n} günde bir`, nextCount: (date: string) => `Sonraki sayım ${date}`, noCountSchedule: "Sayım sıklığı ayarlanmadı", location: "Saklama yeri", lots: "Evdeki partiler", lotsHint: "Çıkışlar en eski alımdan düşülür (FIFO).", noLots: "Evde bu üründen yok.", noExpiry: "SKT yok", movements: "Hareketler", noMovements: "Henüz hareket yok.", after: (q: string) => `Sonra: ${q}`, archive: "Arşivle", unarchive: "Arşivden çıkar", archived: "Arşivli", archiveTitle: "Ürün tipi arşivlensin mi?", archiveDescription: (name: string) => `“${name}” stok listesinde ve önerilerde görünmez. Hareketleri silinmez; istediğinizde arşivden çıkarabilirsiniz.`, deleteMovement: "Hareketi sil", deleteMovementTitle: "Hareket silinsin mi?", deleteMovementDescription: "Mevcut miktar bu hareket olmadan yeniden hesaplanır.", }, categories: { title: "Stok kategorileri", description: "Stok kategorileri gider kategorilerinden ayrıdır. Her kategori bir gider kategorisine eşlenebilir; alışveriş tamamlanınca ürünler o gidere yazılır.", back: "Ev stoğuna dön", new: "Yeni kategori", addChild: "Alt kategori ekle", edit: "Düzenle", archive: "Arşivle", unarchive: "Arşivden çıkar", showArchived: "Arşivi göster", archived: "Arşivli", defaultBadge: "Varsayılan", empty: "Stok kategorisi yok.", createTitle: "Yeni stok kategorisi", editTitle: "Stok kategorisini düzenle", name: "Ad", parent: "Üst kategori", noParent: "— Ana kategori —", expenseCategory: "Gider kategorisi", expenseInherit: "— Üstten devral —", expenseHint: "Alışveriş tamamlanınca bu kategorideki ürünlerin yazılacağı gider kategorisi.", inherited: (name: string) => `${name} (üstten)`, noExpense: "Eşlenmedi", countEveryDays: "Sayım sıklığı (gün)", countEveryDaysHint: "Boş bırakılırsa üst kategoriden devralınır.", everyDays: (n: number) => `${n} günde bir sayım`, productCount: (n: number) => `${n} ürün`, archiveTitle: "Stok kategorisi arşivlensin mi?", archiveDescription: (name: string) => `“${name}” ve alt kategorileri yeni ürünlerde seçilemez.`, hasProducts: "Bu kategoride veya altında aktif ürün tipi var; önce onları başka kategoriye taşıyın veya arşivleyin.", duplicate: "Bu düzeyde aynı adlı bir kategori zaten var.", expenseInvalid: "Geçerli bir gider kategorisi seçin.", }, toast: { saved: "Kaydedildi.", movementSaved: "Hareket kaydedildi.", deleted: "Silindi.", archived: "Arşivlendi.", unarchived: "Arşivden çıkarıldı.", counted: (diff: string) => `Sayım kaydedildi; fark ${diff}.`, noChange: "Sayım kayıtlarla aynı; düzeltme gerekmedi.", }, validation: { selectCategory: "Bir stok kategorisi seçin", quantity: "Geçerli bir miktar girin (ör. 1,5)", countDays: "1 ile 365 arasında gün sayısı girin", unit: "Birim 1–20 karakter olmalı", thresholdPct: "0 ile 100 arasında tam sayı girin", wasteReason: "Fire nedenini seçin", expiryBeforeDate: "Son kullanma tarihi alım tarihinden önce olamaz", notEnough: (q: string) => `Stokta yalnızca ${q} var.`, nothingCounted: "En az bir ürünün sayılan miktarını girin.", wasteOverShortage: (q: string) => `Fire, sayımda çıkan eksikten (${q}) fazla olamaz.`, emptyStock: "Stok zaten boş.", duplicate: "Bu adla bir ürün tipi zaten var.", categoryArchived: "Seçilen stok kategorisi arşivli veya bulunamadı.", archived: "Ürün tipi arşivli.", }, dashboard: { title: "Stok uyarıları", description: (low: number, expiring: number, countDue = 0) => [ low ? `${low} ürün eşiğin altında` : null, expiring ? `${expiring} partinin SKT'si yaklaşıyor` : null, countDue ? `${countDue} kategoride sayım zamanı` : null, ] .filter(Boolean) .join(" · "), more: (n: number) => `+${n} ürün daha`, open: "Ev stoğuna git", }, }, stores: { title: "Mağazalar", description: "Alışveriş yaptığınız marketler, online platformlar ve pazarlar. Uzaklık ve taşıma güçlüğünden zahmet skoru hesaplanır; alışveriş önerisi bunu dikkate alır.", new: "Yeni mağaza", createTitle: "Yeni mağaza", editTitle: "Mağazayı düzenle", empty: "Henüz mağaza yok. “Yeni mağaza” ile ekleyin.", readOnly: "İzleyici rolündesiniz; mağazaları değiştiremezsiniz.", sort: "Sırala", sorts: { name: "Ada göre", nearest: "En yakın", farthest: "En uzak", effort: "En zahmetli", }, showArchived: "Arşivi göster", archived: "Arşivli", kinds: { market: "Fiziksel market", online: "Online platform", bazaar: "Pazar", }, kindShort: { market: "Market", online: "Online", bazaar: "Pazar", }, fields: { name: "Ad", namePlaceholder: "ör. Migros, A101, Semt pazarı", kind: "Tür", branch: "Şube", branchPlaceholder: "ör. Kadıköy", distance: "Eve uzaklık (km)", distanceHint: "ör. 1,5. Online mağazada gerekmez.", carry: "Taşıma güçlüğü", carryHint: "1 = kolay (kapının önü), 5 = çok zor (uzak, yokuş, araç gerekir).", deliveryFee: "Teslimat ücreti", freeDeliveryMin: "Ücretsiz teslimat alt limiti", mealCard: "Yemek kartı geçerli", mealCardProviders: "Geçerli yemek kartları", note: "Not", }, carryLevels: { 1: "Kolay", 2: "Rahat", 3: "Orta", 4: "Zor", 5: "Çok zor", } as Record, effort: "Zahmet", effortLevels: { low: "Düşük", medium: "Orta", high: "Yüksek" }, effortValue: (score: number) => `Zahmet ${score}/100`, effortHint: "Zahmet skoru 0–100: uzaklık (20 km'ye kadar) ve taşıma güçlüğü eşit ağırlıkla. Online mağazada uzaklık sayılmaz.", distanceUnknown: "Uzaklık girilmedi", delivery: (fee: string) => `Teslimat ${fee}`, freeDeliveryFrom: (min: string) => `${min} üzeri ücretsiz`, freeDelivery: "Ücretsiz teslimat", mealCardBadge: "Yemek kartı", actions: { edit: "Düzenle", archive: "Arşivle", unarchive: "Arşivden çıkar", more: "Mağaza işlemleri", }, archiveTitle: "Mağaza arşivlensin mi?", archiveDescription: (name: string) => `“${name}” yeni fiyat ve alışverişlerde seçilemez. Geçmiş kayıtları silinmez.`, toast: { saved: "Mağaza kaydedildi.", archived: "Mağaza arşivlendi.", unarchived: "Mağaza arşivden çıkarıldı.", }, validation: { distance: "Geçerli bir uzaklık girin (ör. 2,5)", carry: "1 ile 5 arasında seçin", providers: "En az bir yemek kartı seçin", duplicate: "Bu ad ve şubeyle bir mağaza zaten var.", archived: "Mağaza arşivli.", }, }, products: { title: "Ürünler", description: "Marka ve paket düzeyinde ürünler (ör. “Ariel Matik 5 kg”). Her ürün bir ürün tipine bağlıdır; stok ürün tipinde tutulur, fiyatlar üründe.", catalogLink: "Ürün kataloğu", back: "Ev stoğuna dön", new: "Yeni ürün", createTitle: "Yeni ürün", editTitle: "Ürünü düzenle", sectionTitle: "Ürünler (marka / paket)", sectionDescription: "Bu ürün tipinin markaları ve paketleri. Fiyatlar ve birim fiyat karşılaştırması bu ürünler üzerinden yapılır.", empty: "Henüz ürün yok.", emptyType: "Bu ürün tipine henüz marka/paket eklenmedi.", search: "Marka, tanım veya barkod ara", noMatch: "Aramaya uyan ürün yok.", showArchived: "Arşivi göster", archived: "Arşivli", barcode: (code: string) => `Barkod ${code}`, images: (n: number) => `${n} görsel`, conversionMissing: "Dönüşüm gerekli", conversionMissingHint: "Ürün tipinin birimi değişti; bu paketin karşılığını girmeden fiyatı karşılaştırılamaz.", fields: { productType: "Ürün tipi", brand: "Marka", brandPlaceholder: "ör. Ariel, Fairy, Yayla", name: "Tanım", namePlaceholder: "ör. Matik Dağ Esintisi", barcode: "Barkod", barcodeHint: "İsteğe bağlı, 8–14 rakam.", packageQuantity: "Paket miktarı", packageUnit: "Paket birimi", typeQuantity: (unit: string) => `Bir paket kaç ${unit}?`, typeQuantityHint: (pkg: string, unit: string) => `${pkg} ürün tipinin birimine (${unit}) kendiliğinden çevrilemiyor; ör. 5 kg = 50 yıkama.`, autoConversion: (pkg: string) => `Bir paket = ${pkg}`, images: "Ürün görselleri", addImage: "Görsel ekle", imagesHint: "Ambalajın önü, arkası veya raf etiketi", note: "Not", }, actions: { edit: "Düzenle", archive: "Arşivle", unarchive: "Arşivden çıkar", more: "Ürün işlemleri", }, archiveTitle: "Ürün arşivlensin mi?", archiveDescription: (name: string) => `“${name}” yeni fiyat ve alışveriş listelerinde seçilemez. Görselleri ve geçmişi silinmez.`, toast: { saved: "Ürün kaydedildi.", archived: "Ürün arşivlendi.", unarchived: "Ürün arşivden çıkarıldı.", }, validation: { productType: "Aktif bir ürün tipi seçin", barcode: "Barkod 8–14 rakam olmalı", barcodeTaken: "Bu barkod başka bir üründe kayıtlı.", packageQuantity: "Geçerli bir paket miktarı girin (ör. 5 veya 0,5)", packageUnit: "Paket birimi 1–20 karakter olmalı", typeQuantity: "Geçerli bir miktar girin", conversionRequired: (pkgUnit: string, typeUnit: string) => `${pkgUnit} → ${typeUnit} dönüşümünü girin (bir paket kaç ${typeUnit}?).`, archived: "Ürün arşivli.", }, }, prices: { title: "Fiyat tablosu", description: "Altın ve döviz fiyatları (elle). Varlıklar ve aynî alacaklar alış, aynî borçlar satış fiyatıyla değerlenir.", add: "Fiyat gir", asset: "Varlık", date: "Tarih", buy: "Alış (TL)", sell: "Satış (TL)", sellHint: "Boş bırakılırsa alış fiyatı kullanılır (tek fiyat).", noPrice: "Fiyat yok", history: "Son fiyatlar", perUnit: (unit: string) => `/ ${unit}`, saved: "Fiyat kaydedildi.", }, card: { title: "Kart özeti", debt: "Toplam borç", available: "Kullanılabilir limit", limitOf: (limit: string) => `Limit ${limit}`, pendingInstallments: (amount: string) => `Gelecek taksitler limitten düşer: ${amount}`, statementPeriod: "Hesap kesim dönemi", currentPeriod: "Güncel dönem", periodRange: (start: string, end: string) => `${start} – ${end}`, statementDebt: "Dönem borcu", minimum: (rate: string) => `Asgari ödeme (%${rate})`, paid: "Ödenen", remaining: "Kalan", dueDate: "Son ödeme", daysLeft: (n: number) => n > 0 ? `${n} gün kaldı` : n === 0 ? "Bugün son gün" : `${-n} gün geçti`, paidInFull: "Dönem borcu ödendi.", spent: "Harcama", pay: "Borcu öde", payDescription: "Kart borcu ödemesi", upcomingInstallments: "Yaklaşan taksitler", installmentPeriod: (end: string, due: string, n: number) => `${end} kesim · son ödeme ${due} · ${n} taksit`, noInstallments: "Bekleyen taksit yok.", planned: "Planlı harcamalar", history: "Geçmiş ekstreler", historyHeaders: { period: "Dönem", debt: "Borç", minimum: "Asgari", paid: "Ödenen", due: "Son ödeme", }, }, overdraft: { title: "Esnek hesap (KMH)", limit: "KMH limiti", used: "Kullanılan", available: "Kullanılabilir KMH", rate: (rate: string) => `Aylık faiz %${rate}`, lastPeriod: "Geçen dönem", currentSoFar: "Bu dönem (şimdiye kadar)", estimatedInterest: "Tahmini faiz", averageUsed: (amount: string) => `Ortalama kullanım ${amount}`, bookInterest: "Faiz kaydı ekle", booked: "Bu dönemin faiz kaydı girilmiş.", interestDescription: (range: string) => `KMH faizi (${range})`, taxNote: "Tahmin vergiler (KKDF/BSMV) hariçtir; banka ekstresindeki tutarı girin.", }, statement: { title: "Hesap ekstresi", back: "Hesaplar", allTransactions: "Tüm işlemler", prevMonth: "Önceki ay", nextMonth: "Sonraki ay", opening: "Ay başı bakiye", inflow: "Giriş", outflow: "Çıkış", closing: "Ay sonu bakiye", current: "Güncel bakiye", balanceAfter: "Bakiye", empty: "Bu ayda işlem yok.", truncated: "Çok fazla işlem var; yalnızca ilk 2.000 işlem gösteriliyor.", lastReconciliation: (date: string, balance: string) => `Son mutabakat: ${date} · ekstre bakiyesi ${balance}`, noReconciliation: "Henüz mutabakat yapılmadı.", reconciledHint: "Mutabakatı yapılmış işlem", adjustmentDescription: (statementBalance: string) => `Ekstre bakiyesi ${statementBalance} ile fark`, reconcile: { open: "Mutabakat yap", title: "Mutabakat", description: "Banka veya kart ekstrenizdeki tarihi ve bakiyeyi girin; uygulamadaki bakiye ile karşılaştırılır.", date: "Ekstre tarihi", balance: "Ekstredeki bakiye (TL)", debt: "Ekstredeki borç (TL)", balanceHint: "Eksi bakiye için başına - koyun (ör. KMH kullanımı).", debtHint: "Karttaki toplam borcu pozitif girin.", check: "Karşılaştır", statementBalance: "Ekstre", appBalance: "Uygulama", difference: "Fark", matches: "Bakiyeler tutuyor.", mismatch: "Bakiyeler tutmuyor. Eksik veya hatalı işlem olabilir.", adjustmentOffer: (amount: string, kind: string) => `Farkı kapatmak için ${amount} tutarında bir “${kind}” düzeltme işlemi oluşturulsun.`, acceptAdjustment: "Düzeltme işlemi oluştur", unreconciled: (n: number) => `${n} işlem işaretlenecek.`, confirm: "Mutabakatı tamamla", confirmWithAdjustment: "Düzelt ve tamamla", done: (n: number) => `Mutabakat tamamlandı; ${n} işlem işaretlendi.`, doneWithAdjustment: (n: number) => `Düzeltme işlemi oluşturuldu ve ${n} işlem işaretlendi.`, }, errors: { date: "Geçerli ve bugünden ileri olmayan bir tarih girin.", archived: "Arşivlenmiş hesapta mutabakat yapılamaz.", needsAdjustment: "Bakiyeler tutmuyor; düzeltme işlemini onaylayın veya işlemleri kontrol edin.", }, }, categories: { title: "Kategoriler", description: "Gelir ve gider kategorileri. Alt kategoriler raporlarda üst kategoriye toplanır.", expense: "Gider", income: "Gelir", newCategory: "Yeni kategori", addChild: "Alt kategori ekle", edit: "Düzenle", moveUp: "Yukarı taşı", moveDown: "Aşağı taşı", archive: "Arşivle", unarchive: "Arşivden çıkar", showArchived: "Arşivi göster", archived: "Arşivli", defaultBadge: "Varsayılan", empty: "Bu türde kategori yok.", createTitle: "Yeni kategori", editTitle: "Kategoriyi düzenle", formDescription: "Alt kategori için bir üst kategori seçin; boş bırakılırsa ana kategori olur.", name: "Ad", parent: "Üst kategori", noParent: "— Ana kategori —", icon: "İkon", color: "Renk", created: (name: string) => `${name} oluşturuldu.`, updated: (name: string) => `${name} güncellendi.`, archivedToast: (name: string) => `${name} arşivlendi.`, unarchivedToast: (name: string) => `${name} arşivden çıkarıldı.`, archiveTitle: "Kategori arşivlensin mi?", archiveDescription: (name: string) => `“${name}” ve alt kategorileri yeni işlemlerde seçilemez. Geçmiş işlemler ve raporlar etkilenmez.`, duplicate: "Bu düzeyde aynı adlı bir kategori zaten var.", violations: { self: "Kategori kendi altına taşınamaz.", descendant: "Kategori kendi alt kategorisinin altına taşınamaz.", kind: "Gelir ve gider kategorileri birbirinin altına konamaz.", depth: "En fazla 5 seviye derinliğe izin verilir.", parentNotFound: "Üst kategori bulunamadı.", parentArchived: "Üst kategori arşivli; önce onu arşivden çıkarın.", }, readOnly: "İzleyici rolündesiniz; kategorileri değiştiremezsiniz.", }, adminHouseholds: { title: "Haneler", description: "Hane oluşturma, kullanıcıları haneye atama ve hane içi roller.", newHousehold: "Yeni hane", createTitle: "Yeni hane", createDescription: "Hane oluşturulur ve seçilen kullanıcı ilk sahibi olur.", name: "Hane adı", owner: "İlk sahip", selectUser: "Kullanıcı seçin", created: (name: string) => `${name} hanesi oluşturuldu.`, members: (n: number) => `${n} üye`, owners: "Sahipler", noOwner: "Sahibi yok", addMember: "Üye ekle", addMemberTitle: (household: string) => `${household} — üye ekle`, addMemberDescription: "Kullanıcı zaten üyeyse rolü güncellenir.", user: "Kullanıcı", role: "Hane içi rol", memberAdded: (name: string) => `${name} haneye eklendi.`, empty: "Henüz hane yok.", privacyNote: "Yöneticiler haneleri ve üyelikleri yönetir; üyesi olmadıkları hanenin finansal verisini göremez.", }, userMenu: { open: "Kullanıcı menüsü", profile: "Profil", logout: "Çıkış yap", loggedOut: "Çıkış yapıldı.", }, roles: { admin: "Yönetici", user: "Kullanıcı" }, quickAdd: { button: "Hızlı ekle", title: "Hızlı ekle", description: "Ne eklemek istiyorsunuz?", expense: "Gider", income: "Gelir", transfer: "Transfer", expenseHint: "Harcama, fatura, alışveriş", incomeHint: "Maaş, ek gelir, iade", transferHint: "Hesaplar ve cariler arası", noAccounts: "İşlem girmek için önce bir hesap gerekli.", }, auth: { loginTitle: "Giriş yap", loginDescription: "Hesabınıza kullanıcı adı veya e-posta ile giriş yapın.", identifier: "Kullanıcı adı veya e-posta", identifierPlaceholder: "ornek veya ornek@eposta.com", password: "Şifre", submit: "Giriş yap", submitting: "Giriş yapılıyor…", invalidCredentials: "Kullanıcı adı/e-posta veya şifre hatalı.", banned: "Hesabınız askıya alınmış. Lütfen yöneticiyle iletişime geçin.", tooManyAttempts: "Çok fazla deneme yapıldı. Lütfen bir dakika sonra tekrar deneyin.", noSignUp: "Hesaplar yalnızca yönetici tarafından açılır.", identifierRequired: "Kullanıcı adı veya e-posta girin", passwordRequired: "Şifre girin", }, dashboard: { title: "Ana sayfa", welcome: (name: string) => `Hoş geldin, ${name}`, welcomeDescription: "Bu ayın özeti, günlük plan ve uyarılar.", cards: { monthIncome: "Bu ay gelir", monthExpense: "Bu ay gider", monthRemaining: "Kalan", totalBalance: "Toplam hesap bakiyesi", cardDebt: "Kart borçları", netWorth: "Net varlık", }, noData: "Henüz veri yok", }, adminUsers: { title: "Kullanıcılar", description: "Kullanıcı oluşturma, rol, şifre ve erişim yönetimi.", newUser: "Yeni kullanıcı", searchPlaceholder: "Ad, kullanıcı adı veya e-posta ara…", columns: { name: "Ad soyad", username: "Kullanıcı adı", email: "E-posta", role: "Rol", status: "Durum", createdAt: "Oluşturulma", }, status: { active: "Aktif", banned: "Askıda" }, actions: { edit: "Düzenle", changeRole: "Rolü değiştir", makeAdmin: "Yönetici yap", makeUser: "Kullanıcı yap", resetPassword: "Şifre sıfırla", ban: "Askıya al", unban: "Askıyı kaldır", delete: "Sil", }, form: { createTitle: "Yeni kullanıcı", createDescription: "Kullanıcı kendi hesabını açamaz; hesapları buradan oluşturun.", editTitle: "Kullanıcıyı düzenle", editDescription: "Ad, kullanıcı adı, e-posta ve rol bilgilerini güncelleyin.", name: "Ad soyad", username: "Kullanıcı adı", usernameHint: "Küçük harf, rakam, nokta, alt çizgi; 3–30 karakter.", email: "E-posta", emailHint: "İsteğe bağlı. Boş bırakılırsa giriş kullanıcı adıyla yapılır.", role: "Sistem rolü", password: "Geçici şifre", passwordHint: "En az 8 karakter. Kullanıcıya güvenli bir kanaldan iletin.", }, password: { title: "Şifre sıfırla", description: (name: string) => `${name} için yeni bir şifre belirleyin.`, newPassword: "Yeni şifre", confirm: "Şifreyi belirle", }, ban: { title: "Kullanıcıyı askıya al", description: (name: string) => `${name} giriş yapamayacak ve açık oturumları kapatılacak.`, reason: "Neden (isteğe bağlı)", confirm: "Askıya al", }, remove: { title: "Kullanıcı silinsin mi?", description: (name: string) => `${name} kalıcı olarak silinecek. Bu işlem geri alınamaz.`, confirm: "Kalıcı olarak sil", }, toast: { created: (name: string) => `${name} oluşturuldu.`, updated: (name: string) => `${name} güncellendi.`, roleChanged: (name: string) => `${name} için rol değiştirildi.`, passwordSet: (name: string) => `${name} için şifre güncellendi.`, banned: (name: string) => `${name} askıya alındı.`, unbanned: (name: string) => `${name} için askı kaldırıldı.`, removed: (name: string) => `${name} silindi.`, }, guards: { self: "Kendi hesabınız için bu işlem yapılamaz.", lastAdmin: "Sistemdeki son yönetici silinemez veya rolü düşürülemez.", }, errors: { usernameTaken: "Bu kullanıcı adı kullanılıyor.", emailTaken: "Bu e-posta adresi kullanılıyor.", checkFields: "Lütfen işaretli alanları düzeltin.", }, you: "Siz", noEmail: "—", }, validation: { nameMin: "Ad en az 2 karakter olmalı", nameMax: "Ad en fazla 80 karakter olabilir", phone: "Geçerli bir telefon numarası girin", usernameFormat: "Yalnızca küçük harf, rakam, nokta ve alt çizgi; 3–30 karakter", email: "Geçerli bir e-posta adresi girin", passwordMin: "Şifre en az 8 karakter olmalı", passwordMax: "Şifre en fazla 128 karakter olabilir", banReasonMax: "Neden en fazla 200 karakter olabilir", householdNameMin: "Hane adı en az 2 karakter olmalı", householdNameMax: "Hane adı en fazla 80 karakter olabilir", selectUser: "Bir kullanıcı seçin", wholeNumber: "Tam sayı girin", money: "Geçerli bir tutar girin (ör. 1.250,50)", moneyNonNegative: "Tutar negatif olamaz", percent: "0 ile 100 arasında bir oran girin (ör. 4,25)", date: "Geçerli bir tarih seçin", selectProvider: "Kart sağlayıcısını seçin", privateNeedsOwner: "“Yalnızca ben” hesabı için hesap sahibini seçin", dueDays: "Kesimden sonra en fazla 30 gün olabilir", }, errors: { notFoundTitle: "Sayfa bulunamadı", notFoundDescription: "Aradığınız sayfa taşınmış veya hiç var olmamış olabilir.", backHome: "Ana sayfaya dön", errorTitle: "Bir şeyler ters gitti", errorDescription: "Sayfa yüklenirken bir hata oluştu. Tekrar deneyebilirsiniz.", retry: "Tekrar dene", reference: "Hata kodu", }, } as const; export type Messages = typeof tr;