Files
TREK/shared/src/i18n/id/reservations.ts
T
Maurice c15c89ca61 feat(costs): create an expense from a booking, fix editing total-only items
Replace the inline price + budget-category fields in the Transport and
Reservation booking modals with a "Create expense" flow: the modal saves the
booking, then opens the full Costs editor prefilled (name + category mapped from
the booking type) and linked to the reservation. A booking with a linked expense
shows it inline with edit / remove.

Also fix the Costs editor so an expense with a recorded total but no payers
(transport-derived or pre-rework items) opens with its amount, lets you set the
currency, and saves - it previously showed 0 everywhere and could not be saved.
Legacy / localized categories now map to the fixed keys, and changing a booking's
type keeps its linked expense category in sync (unless it was manually set).

- shared: reservation_id on budget create, typeToCostCategory helper, i18n keys
- server: createBudgetItem stores reservation_id; keep total_price for payerless
  items; a booking update no longer wipes its linked expense and syncs the
  category on type change
- client: shared BookingCostsSection, exported ExpenseModal with prefill and an
  editable total, page-level save-then-open wiring
2026-06-17 22:11:56 +02:00

181 lines
8.7 KiB
TypeScript

import type { TranslationStrings } from '../types';
const reservations: TranslationStrings = {
'reservations.title': 'Pemesanan',
'reservations.empty': 'Belum ada reservasi',
'reservations.emptyHint':
'Tambahkan reservasi untuk penerbangan, hotel, dan lainnya',
'reservations.add': 'Tambah Reservasi',
'reservations.addManual': 'Pemesanan Manual',
'reservations.placeHint':
'Tips: Reservasi paling baik dibuat langsung dari sebuah tempat agar terhubung dengan rencana harianmu.',
'reservations.confirmed': 'Dikonfirmasi',
'reservations.pending': 'Tertunda',
'reservations.summary': '{confirmed} dikonfirmasi, {pending} tertunda',
'reservations.fromPlan': 'Dari Rencana',
'reservations.showFiles': 'Tampilkan File',
'reservations.editTitle': 'Edit Reservasi',
'reservations.status': 'Status',
'reservations.datetime': 'Tanggal & Waktu',
'reservations.startTime': 'Waktu mulai',
'reservations.endTime': 'Waktu selesai',
'reservations.date': 'Tanggal',
'reservations.time': 'Waktu',
'reservations.timeAlt': 'Waktu (alternatif, mis. 19:30)',
'reservations.notes': 'Catatan',
'reservations.notesPlaceholder': 'Catatan tambahan...',
'reservations.meta.airline': 'Maskapai',
'reservations.meta.flightNumber': 'No. Penerbangan',
'reservations.meta.from': 'Dari',
'reservations.meta.to': 'Ke',
'reservations.layover.route': 'Rute',
'reservations.layover.stop': 'Persinggahan',
'reservations.layover.addStop': 'Tambah persinggahan',
'reservations.layover.connection': 'Sambungan',
'reservations.layover.layover': 'Transit',
'reservations.needsReview': 'Tinjau',
'reservations.needsReviewHint':
'Bandara tidak dapat dicocokkan otomatis — konfirmasi lokasi.',
'reservations.searchLocation': 'Cari stasiun, pelabuhan, alamat...',
'reservations.meta.trainNumber': 'No. Kereta',
'reservations.meta.platform': 'Peron',
'reservations.meta.seat': 'Kursi',
'reservations.meta.checkIn': 'Check-in',
'reservations.meta.checkInUntil': 'Check-in sampai',
'reservations.meta.checkOut': 'Check-out',
'reservations.meta.linkAccommodation': 'Akomodasi',
'reservations.meta.pickAccommodation': 'Hubungkan ke akomodasi',
'reservations.meta.noAccommodation': 'Tidak ada',
'reservations.meta.hotelPlace': 'Akomodasi',
'reservations.meta.pickHotel': 'Pilih akomodasi',
'reservations.meta.fromDay': 'Dari',
'reservations.meta.toDay': 'Sampai',
'reservations.meta.selectDay': 'Pilih hari',
'reservations.type.flight': 'Penerbangan',
'reservations.type.hotel': 'Akomodasi',
'reservations.type.restaurant': 'Restoran',
'reservations.type.train': 'Kereta',
'reservations.type.car': 'Mobil',
'reservations.type.cruise': 'Kapal Pesiar',
'reservations.type.event': 'Acara',
'reservations.type.tour': 'Tur',
'reservations.type.other': 'Lainnya',
'reservations.type.bus': 'Bus',
'reservations.type.ferry': 'Feri',
'reservations.type.bicycle': 'Sepeda',
'reservations.type.taxi': 'Taksi',
'reservations.type.transport_other': 'Lainnya',
'reservations.confirm.delete': 'Yakin ingin menghapus reservasi "{name}"?',
'reservations.confirm.deleteTitle': 'Hapus pemesanan?',
'reservations.confirm.deleteBody': '"{name}" akan dihapus permanen.',
'reservations.toast.updated': 'Reservasi diperbarui',
'reservations.toast.removed': 'Reservasi dihapus',
'reservations.toast.fileUploaded': 'File diunggah',
'reservations.toast.uploadError': 'Gagal mengunggah',
'reservations.newTitle': 'Reservasi Baru',
'reservations.bookingType': 'Jenis Pemesanan',
'reservations.titleLabel': 'Judul',
'reservations.titlePlaceholder': 'mis. Lufthansa LH123, Hotel Adlon, ...',
'reservations.locationAddress': 'Lokasi / Alamat',
'reservations.locationPlaceholder': 'Alamat, Bandara, Hotel...',
'reservations.confirmationCode': 'Kode Pemesanan',
'reservations.confirmationPlaceholder': 'mis. ABC12345',
'reservations.day': 'Hari',
'reservations.noDay': 'Tanpa Hari',
'reservations.place': 'Tempat',
'reservations.noPlace': 'Tanpa Tempat',
'reservations.pendingSave': 'akan disimpan…',
'reservations.uploading': 'Mengunggah...',
'reservations.attachFile': 'Lampirkan file',
'reservations.linkExisting': 'Hubungkan file yang ada',
'reservations.toast.saveError': 'Gagal menyimpan',
'reservations.toast.updateError': 'Gagal memperbarui',
'reservations.toast.deleteError': 'Gagal menghapus',
'reservations.confirm.remove': 'Hapus reservasi untuk "{name}"?',
'reservations.linkAssignment': 'Hubungkan ke jadwal harian',
'reservations.pickAssignment': 'Pilih jadwal dari rencanamu...',
'reservations.noAssignment': 'Tanpa tautan (mandiri)',
'reservations.price': 'Harga',
'reservations.budgetCategory': 'Kategori anggaran',
'reservations.budgetCategoryPlaceholder': 'mis. Transportasi, Akomodasi',
'reservations.budgetCategoryAuto': 'Otomatis (dari jenis pemesanan)',
'reservations.budgetHint':
'Entri anggaran akan dibuat otomatis saat menyimpan.',
'reservations.departureDate': 'Keberangkatan',
'reservations.arrivalDate': 'Kedatangan',
'reservations.departureTime': 'Waktu berangkat',
'reservations.arrivalTime': 'Waktu tiba',
'reservations.pickupDate': 'Penjemputan',
'reservations.returnDate': 'Pengembalian',
'reservations.pickupTime': 'Waktu jemput',
'reservations.returnTime': 'Waktu kembali',
'reservations.endDate': 'Tanggal selesai',
'reservations.meta.departureTimezone': 'TZ Berangkat',
'reservations.meta.arrivalTimezone': 'TZ Tiba',
'reservations.span.departure': 'Keberangkatan',
'reservations.span.arrival': 'Kedatangan',
'reservations.span.inTransit': 'Dalam perjalanan',
'reservations.span.pickup': 'Penjemputan',
'reservations.span.return': 'Pengembalian',
'reservations.span.active': 'Aktif',
'reservations.span.start': 'Mulai',
'reservations.span.end': 'Selesai',
'reservations.span.ongoing': 'Berlangsung',
'reservations.validation.endBeforeStart':
'Tanggal/waktu selesai harus setelah tanggal/waktu mulai',
'reservations.addBooking': 'Tambah pemesanan',
'reservations.import.title': 'Impor konfirmasi pemesanan',
'reservations.import.cta': 'Impor dari file',
'reservations.import.dropHere':
'Seret file konfirmasi pemesanan ke sini atau klik untuk memilih',
'reservations.import.dropActive': 'Lepaskan file untuk mengimpor',
'reservations.import.acceptedFormats':
'Diterima: EML, PDF, PKPass, HTML, TXT (maks. 10 MB per file, hingga 5 file)',
'reservations.import.parsing': 'Memproses file…',
'reservations.import.previewHeading': '{count} pemesanan ditemukan',
'reservations.import.previewEmpty':
'Tidak ada pemesanan yang dapat diekstrak dari file yang diunggah.',
'reservations.import.removeItem': 'Hapus',
'reservations.import.confirm': 'Impor {count} pemesanan',
'reservations.import.back': 'Kembali',
'reservations.import.success': '{count} pemesanan berhasil diimpor',
'reservations.import.partialFailure':
'{created} berhasil diimpor, {failed} gagal',
'reservations.import.error':
'Pemrosesan gagal. Pastikan file adalah konfirmasi pemesanan yang valid.',
'reservations.import.unavailable':
'Impor pemesanan tidak tersedia di server ini.',
'reservations.import.unsupportedFormat':
'Format file tidak didukung. Gunakan EML, PDF, PKPass, HTML, atau TXT.',
'reservations.import.fileTooLarge': 'File "{name}" melebihi batas 10 MB.',
'reservations.airtrail.title': 'Impor dari AirTrail',
'reservations.airtrail.cta': 'AirTrail',
'reservations.airtrail.synced': 'AirTrail',
'reservations.airtrail.syncedHint':
'Tersinkron dari AirTrail — perubahan tetap sinkron di kedua arah.',
'reservations.airtrail.notSynced': 'Tidak tersinkron',
'reservations.airtrail.notSyncedHint':
'Penerbangan ini telah dihapus di AirTrail dan tidak lagi tersinkron.',
'reservations.airtrail.loadError':
'Tidak dapat memuat penerbangan AirTrail-mu.',
'reservations.airtrail.imported': '{count} penerbangan diimpor',
'reservations.airtrail.skippedDuplicate':
'{count} sudah ada di perjalanan ini, dilewati',
'reservations.airtrail.nothingImported': 'Tidak ada yang dapat diimpor.',
'reservations.airtrail.importError': 'Impor gagal. Silakan coba lagi.',
'reservations.airtrail.undo': 'Impor dari AirTrail',
'reservations.airtrail.alreadyImported': 'Diimpor',
'reservations.airtrail.duringTrip': 'Selama perjalanan ini',
'reservations.airtrail.otherFlights': 'Penerbangan lain',
'reservations.airtrail.empty':
'Tidak ada penerbangan ditemukan di akun AirTrail-mu.',
'reservations.airtrail.importCta': 'Impor {count}',
'reservations.costsLabel': 'Costs',
'reservations.createExpense': 'Create expense',
'reservations.createExpenseHint':
'Saves the booking, then opens the Costs editor.',
'reservations.linkedExpense': 'Linked expense',
'reservations.removeExpense': 'Remove expense',
};
export default reservations;