Files
butcem/src/i18n/tr.ts
T
suphicakir bd5a20ce64 feat(shopping): alışverişi tamamla transaction'ı ve karşılaştırma motoru
- tek transaction: stok alımı, fiş kaynaklı fiyat, mağaza başına bölünmüş gider, fiş ekleri, kalanların taşınması
- muadil, markasız ürün tipi ve plansız ekstra satırları; stok → gider kategorisi eşlemesi ve yedek kategori
- compareShopping saf fonksiyonu: aynı/muadil/alınmadı/ekstra, farkın nedenlere tam ayrışması
- tamamlanan listede rapor görüntüsü; testler

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 23:57:50 +03:00

1988 lines
81 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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, fire ve tahmini maliyet. Tüketim: girilen tüketimler ve sayımda çıkan eksikler. Maliyet: aylık ortalama tüketim × son bilinen birim fiyat.",
avgCost: "Aylık ort. maliyet",
costHint: (price: string, date: string) => `Son birim fiyat ${price} (${date})`,
noPrice: "Fiyat yok",
totalCost: (total: string) => `Fiyatı bilinen ürünlerde aylık tahmini maliyet: ${total}`,
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.",
toShopping: "Alışveriş listelerinde onayla veya reddet",
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.",
bulky: "Ağır / hacimli",
bulkyHint:
"Su, deterjan gibi taşıması zor ürünler. Akıllı öneri bunları yakın ya da online mağazaya yönlendirir.",
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<number, string>,
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.",
},
},
shopping: {
title: "Alışveriş listeleri",
description:
"Aile üyeleri aynı listeleri kullanır. Stokta azalan ürünler öneri olarak gelir; akıllı öneri en uygun mağaza ve markayı seçer.",
readOnly: "Görüntüleme yetkiniz var; listeleri değiştiremezsiniz.",
newList: "Yeni liste",
createTitle: "Yeni alışveriş listesi",
editTitle: "Listeyi düzenle",
active: "Aktif listeler",
completed: "Tamamlanan alışverişler",
emptyActive: "Aktif liste yok. Yeni bir liste açın.",
itemCount: (n: number) => `${n} kalem`,
checkedCount: (done: number, total: number) => `${done}/${total} alındı`,
updated: (when: string) => `Güncellendi: ${when}`,
completedAt: (when: string) => `Tamamlandı: ${when}`,
emptyList: "Liste boş.",
suggestionsBanner: (n: number) =>
`Stokta eşiğin altına düşen ${n} ürün var. Bir listeyi açıp öneriyi onaylayın ya da reddedin.`,
fields: {
name: "Liste adı",
namePlaceholder: "ör. Haftalık market, Ay başı toptan",
note: "Not",
kind: "Kalem türü",
productType: "Ürün tipi",
product: "Ürün (marka/paket)",
text: "Kalem",
textPlaceholder: "ör. Doğum günü mumu",
quantity: "Miktar",
packages: "Paket adedi",
quantityHint: "Boş bırakılırsa en az bir paket.",
unit: "Birim",
unitPlaceholder: "ör. adet",
itemNote: "Not",
itemNotePlaceholder: "ör. laktozsuz olsun",
},
kinds: { type: "Ürün tipi", product: "Belirli marka", text: "Serbest metin" },
kindHints: {
type: "Markayı akıllı öneri seçer.",
product: "Yalnızca bu ürün önerilir.",
text: "Stokla ve fiyatlarla bağlanmaz.",
},
packageUnit: "paket",
stockLine: (current: string, target: string) => `Evde ${current} / hedef ${target}`,
fromSuggestion: "Stok önerisi",
archivedRef: "Arşivlendi",
actions: {
more: "Diğer işlemler",
addItem: "Kalem ekle",
edit: "Düzenle",
editList: "Listeyi düzenle",
deleteList: "Listeyi sil",
remove: "Listeden çıkar",
moveTo: "Başka listeye taşı",
goShopping: "Alışverişe çık",
back: "Alışveriş listeleri",
backToList: "Listeye dön",
},
editItemTitle: "Kalemi düzenle",
addItemTitle: "Kalem ekle",
moveTitle: "Başka listeye taşı",
moveDescription: (name: string) => `"${name}" seçilen aktif listeye taşınır.`,
moveTarget: "Hedef liste",
noOtherLists: "Taşınabilecek başka aktif liste yok.",
deleteTitle: "Liste silinsin mi?",
deleteDescription: (name: string) => `"${name}" listesi ve kalemleri silinir.`,
suggestions: {
title: "Stok önerileri",
description: "Eşiğin altına düşen ürünler. Onaylananlar önerilen miktarla listeye eklenir.",
addAll: "Tümünü ekle",
add: "Ekle",
dismiss: "Reddet",
dismissHint: "Stok yenilenene (yeni alım girilene) kadar önerilmez.",
line: (current: string, target: string, pct: number | null) =>
`Evde ${current} / hedef ${target}${pct === null ? "" : ` (%${pct})`}`,
suggested: (q: string) => `Önerilen: ${q}`,
},
plan: {
title: "Akıllı mağaza önerisi",
description:
"Son bilinen fiyatlarla. Uzaklık ve taşıma güçlüğü, online teslimat ücreti ve yemek kartı bakiyesi hesaba katılır.",
recommended: "Önerilen dağılım",
single: "Tek mağaza",
singleBest: (store: string, total: string) => `Tek mağaza en iyi seçenek: ${store}, ${total}`,
split: (parts: string, total: string) => `Önerilen dağılım: ${parts}: ${total}`,
part: (store: string, n: number) => `${store} (${n} ürün)`,
saving: (amount: string) => `${amount} tasarruf`,
singleMissing: (n: number) => `Tek mağazada ${n} kalem bulunmuyor.`,
threshold: (amount: string) =>
`Ek mağaza ancak ${amount} üstü tasarruf sağlarsa önerilir (hane ayarı).`,
mealCard: (amount: string) => `Yemek kartıyla ödenebilir: ${amount}`,
mealCardBalance: (amount: string) => `Yemek kartı bakiyeniz: ${amount}`,
delivery: (amount: string) => `Teslimat ${amount}`,
freeDelivery: "Teslimat ücretsiz",
subtotal: "Ara toplam",
total: "Tahmini toplam",
line: (packages: string, price: string) => `${packages} × ${price}`,
unpriced: "Fiyatı bilinmeyenler",
unpricedHint: "Bu kalemler için mağaza fiyatı girilmemiş.",
cheapestAt: (store: string, unitPrice: string) =>
`En ucuz birim fiyat: ${store}, ${unitPrice}`,
empty: "Öneri için listede fiyatı bilinen ürün yok.",
textItems: "Serbest metin kalemleri öneriye katılmaz.",
missing: "Bu planda alınamayan",
},
mode: {
title: "Alışveriş modu",
progress: (done: number, total: number) => `${done}/${total} sepette`,
other: "Diğer",
otherHint: "Fiyatı bilinmeyen ve serbest metin kalemleri",
inCart: "Sepette",
allDone: "Hepsi sepette.",
planChoice: "Plan",
check: (label: string) => `${label}: sepete alındı olarak işaretle`,
refreshed: "Liste güncellendi",
},
toast: {
saved: "Liste kaydedildi.",
deleted: "Liste silindi.",
itemAdded: "Kalem eklendi.",
itemSaved: "Kalem güncellendi.",
itemRemoved: "Kalem listeden çıkarıldı.",
moved: "Kalem taşındı.",
suggestionsAdded: (n: number) => `${n} öneri listeye eklendi.`,
dismissed: "Öneri reddedildi.",
},
validation: {
quantity: "Geçerli bir miktar girin (ör. 2 veya 1,5)",
productType: "Aktif bir ürün tipi seçin",
product: "Aktif bir ürün seçin",
text: "Kalem adını yazın",
duplicate: "Bu ürün listede zaten var; miktarını düzenleyin.",
duplicateIn: (name: string) => `Bu ürün "${name}" listesinde zaten var.`,
notActive: "Bu liste tamamlandı; değiştirilemez.",
sameList: "Kalem zaten bu listede.",
suggestionGone: "Öneri artık geçerli değil (listede ya da stok yenilenmiş).",
amount: "Geçerli bir tutar girin (ör. 89,90)",
noLines: "Alınan en az bir ürün seçin",
duplicateLine: "Bir liste kalemi yalnızca bir kez girilebilir",
duplicateStore: "Mağaza iki kez girilmiş",
account: "Her mağaza için ödeme hesabı seçin",
targetList: "Alınmayanlar için hedef liste seçin",
futureDate: "Gelecek tarihli alışveriş girilemez",
itemGone: "Listede olmayan bir kalem seçilmiş; sayfayı yenileyin",
substituteType: "Muadil aynı ürün tipinden olmalı",
textNoProduct: "Serbest metin kalemine ürün seçilemez",
conversion: (name: string) => `"${name}" ürününün tip birimine dönüşümü yok`,
fallbackCategory: "Eşlenmemiş kalemler için gider kategorisi seçin",
tooManySplits: "Bir mağazada çok fazla gider kategorisi var",
},
complete: {
action: "Alışverişi tamamla",
title: "Alışverişi tamamla",
description:
"Aldıklarınızı seçin: aynı ürün ya da muadili, paket adedi, ödenen tutar ve mağaza. Kaydedince stok, fiyatlar, mağaza başına gider ve fişler tek seferde işlenir.",
date: "Alışveriş tarihi",
bought: "Alındı",
itemsTitle: "Listedekiler",
extrasTitle: "Listede olmayanlar",
addExtra: "Listede olmayan ürün ekle",
removeExtra: "Ekstrayı çıkar",
product: "Alınan ürün",
store: "Mağaza",
packages: "Paket",
quantity: "Miktar",
generic: (unit: string) => `Marka belirtmeden (${unit})`,
amount: "Tutar (₺)",
amountHint: "Fişteki satır tutarı.",
planned: (text: string) => `Plan: ${text}`,
substitute: "Muadil",
noPlan: "Planda fiyat yoktu",
textItem: "Serbest metin: stok ve fiyata işlenmez.",
storesTitle: "Ödeme ve fiş",
storesDescription:
"Her mağaza ayrı gider işlemi olur; kalemler stok kategorisinin gider kategorisine bölünür.",
account: "Ödeme hesabı",
receipts: "Fiş görselleri",
addReceipt: "Fiş ekle",
receiptHint: "Fiş fotoğrafı; işlemin ekine kaydedilir.",
subtotal: (n: number) => `${n} kalem`,
fallbackCategory: "Eşlenmemiş kalemlerin gider kategorisi",
fallbackHint:
"Stok kategorisi bir gider kategorisine eşlenmemiş ürünler ve serbest metin kalemleri buraya yazılır.",
leftoverTitle: "Alınmayanlar",
leftoverDescription: (n: number) => `${n} kalem alınmadı.`,
leftoverActions: {
move: "Başka aktif listeye taşı",
new: "Yeni liste aç",
drop: "Bırak (listeyle kapanır)",
},
newListName: "Yeni liste adı",
newListDefault: (name: string) => `${name} – kalanlar`,
total: "Toplam",
plannedTotal: "Planlanan",
submit: "Alışverişi tamamla",
saved: "Alışveriş tamamlandı; stok, fiyatlar ve giderler işlendi.",
txDescription: (list: string) => `Alışveriş: ${list}`,
splitNote: (n: number) => `${n} kalem`,
noStores: "Mağaza yok. Önce bir mağaza ekleyin.",
},
report: {
title: "Karşılaştırma raporu",
description: (date: string) =>
`Alışveriş tarihi ${date}. Plan, tamamlama anındaki akıllı öneridir.`,
planned: "Planlanan",
actual: "Gerçekleşen",
diff: "Fark",
reasonsTitle: "Farkın nedenleri",
reasons: {
price: "Fiyat farkı (aynı ürün)",
quantity: "Miktar farkı",
substitute: "Muadil ürün",
skipped: "Alınmayanlar",
extra: "Plansız ekstralar",
unplanned: "Planda fiyatı olmayanlar",
},
matches: { same: "Aynı", substitute: "Muadil", skipped: "Alınmadı", extra: "Plansız ekstra" },
item: "Kalem",
plan: "Plan",
bought: "Alınan",
expenses: "Mağaza giderleri",
expenseLine: (account: string, receipts: number) =>
receipts ? `${account} · ${receipts} fiş` : account,
movedTo: (name: string) => `Alınmayanlar "${name}" listesine taşındı.`,
noPlanCell: "—",
},
dashboard: {
title: "Alışveriş",
empty: "Aktif liste yok.",
open: "Listeleri aç",
suggestions: (n: number) => `${n} stok önerisi bekliyor`,
},
},
productPrices: {
add: "Fiyat gir",
addTitle: "Fiyat gir",
comparisonTitle: "Birim fiyat karşılaştırması",
comparisonDescription: (unit: string) =>
`Marka ve mağazaların son bilinen fiyatları, 1 ${unit} başına sıralı. Süresi biten kampanyada önceki normal fiyat kullanılır.`,
noPrices: "Henüz fiyat girilmedi.",
noProducts: "Fiyat girmek için önce bir ürün (marka/paket) ekleyin.",
cheapest: "En uygun",
diff: (pct: number) => `%${pct} pahalı`,
perUnit: "Birim fiyat",
packagePrice: "Paket fiyatı",
store: "Mağaza",
product: "Ürün",
date: "Tarih",
promo: "Kampanya",
promoUntil: (date: string) => `${date} tarihine kadar`,
promoEnded: "Kampanya bitti",
fellBack: "Kampanya bitti, normal fiyat",
stale: (days: number) => `${days} gün önce`,
staleHint: "90 günden eski fiyat; güncel olmayabilir.",
noConversion: "Dönüşüm yok",
sources: { manual: "Elle", receipt: "Fiş", provider: "Sağlayıcı" } as Record<string, string>,
detail: {
back: "Ürün kataloğu",
typeLink: (name: string) => `Ürün tipi: ${name}`,
currentTitle: "Mağazalardaki fiyatlar",
currentDescription: "Her mağazadaki geçerli (son) fiyat; birim fiyata göre sıralı.",
chartTitle: "Fiyat geçmişi",
chartDescription: "Mağaza başına paket fiyatı; fiyat yeni kayda kadar geçerli sayılır.",
chartLabel: (name: string) => `${name}: mağaza başına fiyat geçmişi`,
historyTitle: "Fiyat kayıtları",
deletePrice: "Fiyat kaydını sil",
deleteTitle: "Fiyat kaydı silinsin mi?",
deleteDescription: "Kayıt fiyat geçmişinden ve karşılaştırmadan çıkarılır.",
images: "Görseller",
barcode: "Barkod",
package: "Paket",
},
fields: {
product: "Ürün",
store: "Mağaza",
date: "Tarih",
price: "Paket fiyatı (₺)",
isPromo: "Kampanya / indirim",
promoUntil: "Kampanya bitişi",
promoUntilHint: "İsteğe bağlı. Bitince karşılaştırmada önceki normal fiyat kullanılır.",
note: "Not",
unitPreview: (value: string) => `Birim fiyat: ${value}`,
},
toast: { saved: "Fiyat kaydedildi.", deleted: "Fiyat kaydı silindi." },
validation: {
product: "Aktif bir ürün seçin",
store: "Aktif bir mağaza seçin",
price: "Geçerli bir fiyat girin (ör. 89,90)",
promoUntil: "Kampanya bitişi fiyat tarihinden önce olamaz",
futureDate: "Gelecek tarihli fiyat girilemez",
},
},
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;