fix(mobile): a booking opens its detail sheet first, as a transport and the desktop do; Wallet and Map buttons read short

Bookings in the Bookings tab, the day sheet, a place's sheet and the road trip
opened their editor straight away, while a transport showed its details with
a pencil to edit. Every booking now opens the same detail sheet; its edit and
delete follow the booking's own permission (reservation_edit for a stay, a
table or a ticket, day_edit for a transport). Notes keep opening for editing,
as on the desktop.

The wallet button reads "Wallet" (its accessible name still says which one),
and "On map" reads "Map" in every language.
This commit is contained in:
Maurice
2026-11-09 12:56:50 +01:00
parent ed0142be7d
commit f03bb97d50
68 changed files with 121 additions and 111 deletions
@@ -61,12 +61,14 @@ describe('MWalletButton', () => {
await waitFor(() => expect(onError).toHaveBeenLastCalledWith(expect.stringMatching(/could not be made/i)));
});
it('on Android adds the booking to Google Wallet, under its own name', async () => {
it('on Android adds the booking to Google Wallet, under its own name for screen readers', async () => {
wallet.kind = 'google';
wallet.addGoogle.mockResolvedValue('added');
const onError = vi.fn();
render(<MWalletButton tripId={42} reservationId={7} onError={onError} />);
expect(screen.getByRole('button')).toHaveTextContent(/Google Wallet/);
// The label is short, the accessible name says which wallet.
expect(screen.getByRole('button')).toHaveTextContent(/^Wallet$/);
expect(screen.getByRole('button', { name: /Google Wallet/ })).toBeInTheDocument();
fireEvent.click(screen.getByRole('button'));
await waitFor(() => expect(wallet.addGoogle).toHaveBeenCalledWith(42, 7, expect.any(String)));
expect(wallet.add).not.toHaveBeenCalled();
@@ -57,10 +57,11 @@ export default function MWalletButton({ tripId, reservationId, onError, classNam
onClick={() => void add()}
disabled={busy}
aria-busy={busy}
aria-label={t(wallet === 'google' ? 'reservations.wallet.addGoogle' : 'reservations.wallet.add')}
className="flex items-center gap-[6px] rounded-full bg-black px-3 py-[7px] text-[length:calc(12px*var(--fs-scale-body,1))] font-semibold text-white transition-transform active:scale-[.97] disabled:opacity-70" // theme-lint-disable: the wallets' badges are black in either theme
>
{busy ? <Loader2 size={13} className="animate-spin" /> : <Wallet size={13} strokeWidth={2} />}
{t(wallet === 'google' ? 'reservations.wallet.addGoogle' : 'reservations.wallet.add')}
{t('reservations.wallet.short')}
</button>
);
return className ? <div className={className}>{button}</div> : button;
@@ -180,14 +180,8 @@ function RoadtripStagePage({ planner, shell, dayId: pageDayId, alts, chrome }: O
// A chip that may not be opened is not a button in the first place (`bookingOpens`),
// so nothing is turned away silently here.
const canEditBookings = planner.can('reservation_edit', planner.trip)
const openBooking = (res: Reservation) => {
if (planner.TRANSPORT_TYPES.has(res.type)) {
shell.openSheet('transport', { reservationId: res.id })
return
}
planner.setEditingReservation(res)
planner.setShowReservationModal(true)
}
// Every booking opens its detail sheet, as on the desktop; its pencil edits it there.
const openBooking = (res: Reservation) => shell.openSheet('transport', { reservationId: res.id })
// A booked night at the edge of the stage is no stop, and has no stop sheet: it opens the
// booking behind the night, else the stay for somebody who may edit days, else the
// hotel's place, the way a stay chip in the day timeline does (#2210).
@@ -111,19 +111,11 @@ export default function MDaySheet({ planner, shell }: MTripSheetsProps) {
}
}
// A booking opens its detail sheet, as on the desktop; its pencil edits it there.
const openReservation = (r: Reservation) => {
const isTransport = planner.TRANSPORT_TYPES.has(r.type)
if (isTransport && canEditDays) {
planner.setEditingTransport(r)
planner.setTransportModalDayId(r.day_id ?? null)
planner.setShowTransportModal(true)
} else if (!isTransport && canEditReservations) {
planner.setEditingReservation(r)
planner.setShowReservationModal(true)
} else {
return
}
shell.closeSheet()
if (isTransport ? !canEditDays : !canEditReservations) return
shell.openSheet('transport', { reservationId: r.id })
}
const planTransit = () => {
@@ -112,18 +112,11 @@ export default function MPlaceSheet({ planner, shell }: MTripSheetsProps) {
)
const openRes = (res: Reservation) => {
if (!canOpenRes(res)) return
if (planner.TRANSPORT_TYPES.has(res.type)) {
planner.setEditingTransport(res)
planner.setTransportModalDayId(res.day_id ?? null)
planner.setTransportModalAutomated(false)
planner.setShowTransportModal(true)
} else {
planner.setEditingReservation(res)
planner.setShowReservationModal(true)
}
// This sheet hangs off the place selection, not the sheet stack, so its own
// close() is what dismisses it — otherwise the editor opens on top of it.
// close() is what dismisses it; the booking's detail sheet then opens alone,
// with its pencil for editing, as on the desktop.
close()
shell.openSheet('transport', { reservationId: res.id })
}
const participants = assignmentInDay?.participants || []
@@ -413,7 +406,6 @@ export default function MPlaceSheet({ planner, shell }: MTripSheetsProps) {
type="button"
onClick={() => openRes(res)}
disabled={!canOpenRes(res)}
aria-label={canOpenRes(res) ? t('inspector.editRes') : undefined}
className={`flex w-full items-center gap-2 rounded-[14px] px-3 py-[10px] text-start ${INNER_CLS}`}
>
<span
@@ -103,6 +103,7 @@ export default function MTransportSheet({ planner, shell }: MTripSheetsProps) {
})
const canEditDays = planner.can('day_edit', planner.trip)
const canEditBookings = planner.can('reservation_edit', planner.trip)
const timeFormat = useSettingsStore(s => s.settings.time_format) || '24h'
const blurCodes = useSettingsStore(s => s.settings.blur_booking_codes)
const [codeRevealed, setCodeRevealed] = useState(false)
@@ -118,6 +119,9 @@ export default function MTransportSheet({ planner, shell }: MTripSheetsProps) {
}
const meta = parseMetadata(res)
// A transport is part of the day plan, a stay, a table or a ticket a booking:
// each is edited under its own permission, as in the tab it belongs to.
const canEdit = isTransportReservationType(res.type) ? canEditDays : canEditBookings
const ResIcon = RES_ICONS[res.type as keyof typeof RES_ICONS] || RES_ICONS.other
const from = (res.endpoints || []).find(e => e.role === 'from')
@@ -362,7 +366,7 @@ export default function MTransportSheet({ planner, shell }: MTripSheetsProps) {
<span dir="auto" className="truncate">{f.original_name}</span>
</button>
))}
{canEditDays && (
{canEdit && (
<button
type="button"
onClick={editTransport}
@@ -372,7 +376,7 @@ export default function MTransportSheet({ planner, shell }: MTripSheetsProps) {
{t('common.edit')}
</button>
)}
{canEditDays && (
{canEdit && (
<button
type="button"
onClick={deleteTransport}
@@ -69,6 +69,7 @@ export default function MBookingsTab({ planner, shell }: MTabScreenProps) {
planner={planner}
canEdit={canEdit}
compact={shell.bookingsCompact}
onView={() => shell.openSheet('transport', { reservationId: res.id })}
/>
))}
</CardGrid>
@@ -79,10 +80,12 @@ export default function MBookingsTab({ planner, shell }: MTabScreenProps) {
)
}
function BookingCard({ res, planner, canEdit, compact }: {
function BookingCard({ res, planner, canEdit, compact, onView }: {
res: Reservation
planner: MTabScreenProps['planner']
canEdit: boolean
/** A tap on the card: the booking's detail sheet, as a transport opens, and as on the desktop. */
onView: () => void
compact: boolean
}) {
const { t, days } = planner
@@ -139,7 +142,7 @@ function BookingCard({ res, planner, canEdit, compact }: {
{/* Header */}
<div className="flex items-center gap-[7px] border-b border-[color:var(--m-rowbr)] px-3 py-[10px]" style={{ background: tint }}>
<StatusDot color={dotColor} />
<CardTitleButton res={res} TypeIcon={TypeIcon} typeColor={typeColor} onOpen={openEdit} t={t} />
<CardTitleButton res={res} TypeIcon={TypeIcon} typeColor={typeColor} onOpen={onView} t={t} />
{canEdit && <CardActions onEdit={openEdit} onDelete={card.askDelete} t={t} />}
</div>
@@ -154,11 +157,11 @@ function BookingCard({ res, planner, canEdit, compact }: {
timeValue={timeValue}
code={res.confirmation_number}
card={card}
onOpen={openEdit}
onOpen={onView}
t={t}
/>
<button type="button" onClick={openEdit} className="block w-full text-start">
<button type="button" onClick={onView} className="block w-full text-start">
{metaCells.length > 0 && (
<div className="mt-2 flex gap-2">
{metaCells.slice(0, 3).map((c, i) => (
@@ -201,13 +201,12 @@ describe('MBookingsTab', () => {
expect(within(card).getAllByText('—')).toHaveLength(2)
})
it('FE-MOB-BKTAB-012: opens the reservation editor from the row', () => {
it('FE-MOB-BKTAB-012: a tap on the card shows the booking first, as a transport and the desktop do', () => {
const p = planner()
renderTab(p)
const { shell } = renderTab(p)
fireEvent.click(screen.getByText('Sushi Saito'))
expect(p.can).toHaveBeenCalledWith('reservation_edit', p.trip)
expect(p.setEditingReservation).toHaveBeenCalledWith(expect.objectContaining({ id: 202 }))
expect(p.setShowReservationModal).toHaveBeenCalledWith(true)
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 202 })
expect(p.setShowReservationModal).not.toHaveBeenCalled()
})
it('FE-MOB-BKTAB-013: opens the same editor from the pencil', () => {
@@ -217,10 +216,11 @@ describe('MBookingsTab', () => {
expect(p.setEditingReservation).toHaveBeenCalledWith(expect.objectContaining({ id: 201 }))
})
it('FE-MOB-BKTAB-014: a read-only member gets no editor and no actions', () => {
it('FE-MOB-BKTAB-014: a read-only member may look at a booking but gets no editor and no actions', () => {
const p = planner({ can: vi.fn(() => false) as unknown as TripPlanner['can'] })
renderTab(p)
const { shell } = renderTab(p)
fireEvent.click(screen.getByText('Sushi Saito'))
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 202 })
expect(p.setShowReservationModal).not.toHaveBeenCalled()
expect(screen.queryByRole('button', { name: 'common.edit' })).not.toBeInTheDocument()
expect(screen.queryByRole('button', { name: 'common.delete' })).not.toBeInTheDocument()
@@ -315,14 +315,14 @@ describe('MDaySheet', () => {
expect(screen.queryByText('Opera (other day)')).not.toBeInTheDocument()
expect(screen.queryByText('Hotel Sacher booking')).not.toBeInTheDocument()
// Each booking opens its detail sheet first, with the pencil there, as on the desktop.
fireEvent.click(screen.getByText('Train to Salzburg'))
expect(planner.setEditingTransport).toHaveBeenCalledWith(expect.objectContaining({ id: 22 }))
expect(planner.setShowTransportModal).toHaveBeenCalledWith(true)
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 22 })
fireEvent.click(screen.getByText('Dinner at Figlmueller'))
expect(planner.setEditingReservation).toHaveBeenCalledWith(expect.objectContaining({ id: 21 }))
expect(planner.setShowReservationModal).toHaveBeenCalledWith(true)
expect(shell.closeSheet).toHaveBeenCalledTimes(2)
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 21 })
expect(planner.setShowTransportModal).not.toHaveBeenCalled()
expect(planner.setShowReservationModal).not.toHaveBeenCalled()
})
it('FE-MOB-DAYSH-021: a booking row does nothing without the matching permission', async () => {
@@ -332,7 +332,7 @@ describe('MDaySheet', () => {
fireEvent.click(screen.getByText('Train to Salzburg'))
expect(planner.setShowReservationModal).not.toHaveBeenCalled()
expect(planner.setShowTransportModal).not.toHaveBeenCalled()
expect(shell.closeSheet).not.toHaveBeenCalled()
expect(shell.openSheet).not.toHaveBeenCalled()
})
it('FE-MOB-DAYSH-022: renders notes sorted, splits a leading time off the detail line, and routes taps', async () => {
@@ -494,29 +494,26 @@ describe('MPlaceSheet', () => {
expect(screen.getByText('Ferry to Corfu')).toBeInTheDocument()
})
it('FE-MOB-PLSH-028: a transport booking opens the transport editor, not the reservation modal', () => {
it('FE-MOB-PLSH-028: a transport booking opens its detail sheet, not an editor', () => {
const planner = bookingPlanner({ id: 7, assignment_id: 11, title: 'Ferry to Corfu', status: 'pending', type: 'ferry', day_id: 2 })
renderSheet(planner)
const { shell } = renderSheet(planner)
fireEvent.click(screen.getByRole('button', { name: 'Edit Reservation' }))
fireEvent.click(screen.getByText('Ferry to Corfu').closest('button') as HTMLButtonElement)
expect(planner.setEditingTransport).toHaveBeenCalledWith(expect.objectContaining({ id: 7 }))
expect(planner.setTransportModalDayId).toHaveBeenCalledWith(2)
expect(planner.setShowTransportModal).toHaveBeenCalledWith(true)
expect(planner.setShowReservationModal).not.toHaveBeenCalled()
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 7 })
expect(planner.setShowTransportModal).not.toHaveBeenCalled()
// and the place sheet gets out of the way
expect(planner.setSelectedPlaceId).toHaveBeenCalledWith(null)
})
it('FE-MOB-PLSH-029: a non-transport booking opens the reservation modal', () => {
it('FE-MOB-PLSH-029: a non-transport booking opens the same detail sheet first, as on the desktop', () => {
const planner = bookingPlanner({ id: 8, assignment_id: 11, title: 'Museum tour', status: 'confirmed', type: 'activity' })
renderSheet(planner)
const { shell } = renderSheet(planner)
fireEvent.click(screen.getByRole('button', { name: 'Edit Reservation' }))
fireEvent.click(screen.getByText('Museum tour').closest('button') as HTMLButtonElement)
expect(planner.setEditingReservation).toHaveBeenCalledWith(expect.objectContaining({ id: 8 }))
expect(planner.setShowReservationModal).toHaveBeenCalledWith(true)
expect(planner.setShowTransportModal).not.toHaveBeenCalled()
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: 8 })
expect(planner.setShowReservationModal).not.toHaveBeenCalled()
})
it('FE-MOB-PLSH-030: a viewer without edit rights sees the booking but gets no live button', () => {
@@ -529,7 +526,6 @@ describe('MPlaceSheet', () => {
// Still readable — just not a control that would do nothing when pressed.
expect(screen.getByText('Ferry to Corfu')).toBeInTheDocument()
expect(screen.queryByRole('button', { name: 'Edit Reservation' })).not.toBeInTheDocument()
const row = screen.getByText('Ferry to Corfu').closest('button') as HTMLButtonElement
expect(row.disabled).toBe(true)
})
@@ -899,11 +899,10 @@ describe('MRoadtripTab', () => {
// The chips are the stop's, not stops: the count stays at two.
expect(screen.getByText('roadtrip.day.stopCount:2')).toBeInTheDocument()
// A chip opens its booking in the editor, the way the place sheet opens a linked one.
// A chip opens its booking's detail sheet, the way the place sheet opens a linked one.
fireEvent.click(screen.getByText('Tisch Bullerei'))
expect(p.setEditingReservation).toHaveBeenCalledWith(reservations[0])
expect(p.setShowReservationModal).toHaveBeenCalledWith(true)
expect(shell.openSheet).not.toHaveBeenCalled()
expect(shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: reservations[0].id })
expect(p.setShowReservationModal).not.toHaveBeenCalled()
})
it('FE-MOB-RTTAB-057: a transport chip goes to the transport sheet, and a table is not even a button for a member who may not edit bookings', () => {
@@ -992,9 +991,8 @@ describe('MRoadtripTab', () => {
const editor = planner({ roadtripRoutes: routes({ days: [hotelStage()] }), reservations: [hotelBooking] })
const first = renderTab(editor)
fireEvent.click(screen.getByText('roadtrip.bookend.back'))
expect(editor.setEditingReservation).toHaveBeenCalledWith(hotelBooking)
expect(editor.setShowReservationModal).toHaveBeenCalledWith(true)
expect(first.shell.openSheet).not.toHaveBeenCalled()
expect(first.shell.openSheet).toHaveBeenCalledWith('transport', { reservationId: hotelBooking.id })
expect(editor.setShowReservationModal).not.toHaveBeenCalled()
first.unmount()
const dayEditor = planner({
@@ -181,7 +181,7 @@ describe('MTransportSheet', () => {
const planner = makePlanner()
const shell = makeShell({ trTab: 'transports', view: 'plan' })
render(<MTransportSheet planner={planner} shell={shell} />)
const btn = screen.getByRole('button', { name: 'On map' })
const btn = screen.getByRole('button', { name: 'Map' })
expect(btn).toHaveAttribute('aria-pressed', 'false')
fireEvent.click(btn)
expect(planner.toggleConnection).toHaveBeenCalledWith(7)
@@ -194,7 +194,7 @@ describe('MTransportSheet', () => {
const planner = makePlanner({ visibleConnections: [7] })
const shell = makeShell({ trTab: 'plan', view: 'map' })
render(<MTransportSheet planner={planner} shell={shell} />)
const btn = screen.getByRole('button', { name: 'On map' })
const btn = screen.getByRole('button', { name: 'Map' })
expect(btn).toHaveAttribute('aria-pressed', 'true')
fireEvent.click(btn)
expect(planner.toggleConnection).toHaveBeenCalledWith(7)
@@ -253,7 +253,7 @@ describe('MTransportSheet', () => {
render(<MTransportSheet planner={planner} shell={makeShell()} />)
expect(screen.queryByRole('button', { name: 'Edit' })).not.toBeInTheDocument()
expect(screen.queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument()
expect(screen.getByRole('button', { name: 'On map' })).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'Map' })).toBeInTheDocument()
})
it('FE-MOB-TRSH-021: keeps the last booking on screen while the sheet animates out', () => {
@@ -323,7 +323,7 @@ describe('MTransportSheet', () => {
const shell = makeShell({ trTab: 'transports', view: 'plan' })
render(<MTransportSheet planner={planner} shell={shell} />)
fireEvent.click(screen.getByRole('button', { name: 'On map' }))
fireEvent.click(screen.getByRole('button', { name: 'Map' }))
expect(planner.toggleConnection).toHaveBeenCalledWith(7)
expect(planner.handleSelectDay).toHaveBeenCalledWith(3, false)
@@ -338,7 +338,7 @@ describe('MTransportSheet', () => {
const shell = makeShell({ trTab: 'transports', view: 'map' })
render(<MTransportSheet planner={planner} shell={shell} />)
fireEvent.click(screen.getByRole('button', { name: 'On map' }))
fireEvent.click(screen.getByRole('button', { name: 'Map' }))
expect(shell.toggleView).not.toHaveBeenCalled()
expect(planner.handleSelectDay).toHaveBeenCalledWith(3, false)
@@ -351,7 +351,7 @@ describe('MTransportSheet', () => {
const planner = makePlanner({ days: DAYS, selectedDayId: 4, reservations: [overnight] })
render(<MTransportSheet planner={planner} shell={makeShell({ trTab: 'plan', view: 'plan' })} />)
fireEvent.click(screen.getByRole('button', { name: 'On map' }))
fireEvent.click(screen.getByRole('button', { name: 'Map' }))
expect(planner.toggleConnection).toHaveBeenCalledWith(7)
expect(planner.handleSelectDay).not.toHaveBeenCalled()
@@ -362,13 +362,13 @@ describe('MTransportSheet', () => {
const unbound = { ...FLIGHT, day_id: null, end_day_id: null } as unknown as Reservation
const allDays = makePlanner({ days: DAYS, selectedDayId: null })
const { unmount } = render(<MTransportSheet planner={allDays} shell={makeShell({ trTab: 'transports', view: 'map' })} />)
fireEvent.click(screen.getByRole('button', { name: 'On map' }))
fireEvent.click(screen.getByRole('button', { name: 'Map' }))
expect(allDays.handleSelectDay).not.toHaveBeenCalled()
unmount()
const noDay = makePlanner({ days: DAYS, selectedDayId: 5, reservations: [unbound] })
render(<MTransportSheet planner={noDay} shell={makeShell({ trTab: 'transports', view: 'plan' })} />)
fireEvent.click(screen.getByRole('button', { name: 'On map' }))
fireEvent.click(screen.getByRole('button', { name: 'Map' }))
expect(noDay.toggleConnection).toHaveBeenCalledWith(7)
expect(noDay.handleSelectDay).not.toHaveBeenCalled()
})
@@ -381,7 +381,7 @@ describe('MTransportSheet', () => {
const shell = makeShell({ trTab: 'transports', view: 'plan' })
render(<MTransportSheet planner={planner} shell={shell} />)
const btn = screen.getByRole('button', { name: 'On map' })
const btn = screen.getByRole('button', { name: 'Map' })
expect(btn).toHaveAttribute('aria-pressed', 'false')
fireEvent.click(btn)
@@ -398,7 +398,7 @@ describe('MTransportSheet', () => {
const shell = makeShell({ trTab: 'plan', view: 'map' })
render(<MTransportSheet planner={planner} shell={shell} />)
const btn = screen.getByRole('button', { name: 'On map' })
const btn = screen.getByRole('button', { name: 'Map' })
expect(btn).toHaveAttribute('aria-pressed', 'true')
fireEvent.click(btn)
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'فئة جديدة',
'mobileTrip.newReservation': 'حجز جديد',
'mobileTrip.notes': 'الملاحظات',
'mobileTrip.onMap': 'على الخريطة',
'mobileTrip.onMap': 'الخريطة',
'mobileTrip.profileDriving': 'بالسيارة',
'mobileTrip.profileWalking': 'سيرًا على الأقدام',
'mobileTrip.profileCycling': 'بالدراجة',
+1
View File
@@ -301,6 +301,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'تصدير الصفوف المعروضة ({shown} من {total}) (CSV)',
'reservations.wallet.add': 'إضافة إلى Apple Wallet',
'reservations.wallet.addGoogle': 'إضافة إلى Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'تعذّر إنشاء بطاقة Wallet. حاول مرة أخرى.',
'reservations.wallet.undated': 'حدّد تاريخًا للحجز أولًا: يعرض Wallet البطاقة قرب موعده.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Yeni kateqoriya',
'mobileTrip.newReservation': 'Yeni rezervasiya',
'mobileTrip.notes': 'Qeydlər',
'mobileTrip.onMap': 'Xəritədə',
'mobileTrip.onMap': 'Xəritə',
'mobileTrip.profileDriving': 'Avtomobillə',
'mobileTrip.profileWalking': 'Piyada',
'mobileTrip.profileCycling': 'Velosipedlə',
+1
View File
@@ -309,6 +309,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Göstərilən {shown}/{total} sətri ixrac et (CSV)',
'reservations.wallet.add': 'Apple Wallet-ə əlavə et',
'reservations.wallet.addGoogle': 'Google Wallet-ə əlavə et',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Wallet kartını yaratmaq alınmadı. Yenidən cəhd edin.',
'reservations.wallet.undated': 'Əvvəlcə rezervasiyaya tarix verin: Wallet kartı həmin vaxta yaxın göstərir.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nova categoria',
'mobileTrip.newReservation': 'Nova reserva',
'mobileTrip.notes': 'Notas',
'mobileTrip.onMap': 'No mapa',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'De carro',
'mobileTrip.profileWalking': 'A pé',
'mobileTrip.profileCycling': 'De bicicleta',
+1
View File
@@ -275,6 +275,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Ezporzhiañ ar {shown} diwar {total} renk skwer (CSV)',
'reservations.wallet.add': 'Adicionar à Apple Wallet',
'reservations.wallet.addGoogle': 'Adicionar à Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Não foi possível criar o passe da Wallet. Tente novamente.',
'reservations.wallet.undated': 'Primeiro dê uma data à reserva: a Wallet mostra o passe perto desse horário.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Categoria nova',
'mobileTrip.newReservation': 'Reserva nova',
'mobileTrip.notes': 'Notes', // same-as-en
'mobileTrip.onMap': 'Al mapa',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'En cotxe',
'mobileTrip.profileWalking': 'A peu',
'mobileTrip.profileCycling': 'En bicicleta',
+1
View File
@@ -278,6 +278,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exporta les {shown} de {total} files mostrades (CSV)',
'reservations.wallet.add': 'Afegeix a Apple Wallet',
'reservations.wallet.addGoogle': 'Afegeix a Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'No s’ha pogut crear el passi de Wallet. Torna-ho a provar.',
'reservations.wallet.undated':
'Primer posa una data a la reserva: Wallet mostra el passi al voltant d’aquell moment.',
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nová kategorie',
'mobileTrip.newReservation': 'Nová rezervace',
'mobileTrip.notes': 'Poznámky',
'mobileTrip.onMap': 'Na mapě',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'Autem',
'mobileTrip.profileWalking': 'Pěšky',
'mobileTrip.profileCycling': 'Na kole',
+1
View File
@@ -282,6 +282,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exportovat zobrazené řádky, {shown} z {total} (CSV)',
'reservations.wallet.add': 'Přidat do Apple Wallet',
'reservations.wallet.addGoogle': 'Přidat do Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Kartu do Wallet se nepodařilo vytvořit. Zkuste to znovu.',
'reservations.wallet.undated': 'Nejdřív rezervaci zadejte datum: Wallet kartu zobrazí kolem toho času.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Neue Kategorie',
'mobileTrip.newReservation': 'Neue Buchung',
'mobileTrip.notes': 'Notizen',
'mobileTrip.onMap': 'Auf Karte',
'mobileTrip.onMap': 'Karte',
'mobileTrip.profileDriving': 'Auto',
'mobileTrip.profileWalking': 'Fußweg',
'mobileTrip.profileCycling': 'Fahrrad',
+1
View File
@@ -280,6 +280,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Die {shown} von {total} angezeigten Zeilen exportieren (CSV)',
'reservations.wallet.add': 'Zu Apple Wallet hinzufügen',
'reservations.wallet.addGoogle': 'Zu Google Wallet hinzufügen',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Der Wallet-Pass konnte nicht erstellt werden. Bitte versuch es erneut.',
'reservations.wallet.undated': 'Gib der Buchung zuerst ein Datum: Wallet zeigt den Pass rund um diesen Zeitpunkt an.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'New category',
'mobileTrip.newReservation': 'New Reservation',
'mobileTrip.notes': 'Notes',
'mobileTrip.onMap': 'On map',
'mobileTrip.onMap': 'Map',
'mobileTrip.profileDriving': 'Driving',
'mobileTrip.profileWalking': 'Walking',
'mobileTrip.profileCycling': 'Cycling',
+1
View File
@@ -277,6 +277,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Export the {shown} of {total} shown rows (CSV)',
'reservations.wallet.add': 'Add to Apple Wallet',
'reservations.wallet.addGoogle': 'Add to Google Wallet',
'reservations.wallet.short': 'Wallet',
'reservations.wallet.failed': 'The Wallet pass could not be made. Please try again.',
'reservations.wallet.undated': 'Give the booking a date first: Wallet brings the pass up around its time.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nueva categoría',
'mobileTrip.newReservation': 'Nueva reserva',
'mobileTrip.notes': 'Notas',
'mobileTrip.onMap': 'En el mapa',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'En coche',
'mobileTrip.profileWalking': 'A pie',
'mobileTrip.profileCycling': 'En bici',
+1
View File
@@ -278,6 +278,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exportar las {shown} de {total} filas mostradas (CSV)',
'reservations.wallet.add': 'Añadir a Apple Wallet',
'reservations.wallet.addGoogle': 'Añadir a Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'No se pudo crear el pase de Wallet. Inténtalo de nuevo.',
'reservations.wallet.undated': 'Primero ponle una fecha a la reserva: Wallet muestra el pase en torno a ese momento.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Uus kategooria',
'mobileTrip.newReservation': 'Uus broneering',
'mobileTrip.notes': 'Märkmed',
'mobileTrip.onMap': 'Kaardil',
'mobileTrip.onMap': 'Kaart',
'mobileTrip.profileDriving': 'Autoga',
'mobileTrip.profileWalking': 'Jalgsi',
'mobileTrip.profileCycling': 'Jalgrattaga',
+1
View File
@@ -277,6 +277,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Ekspordi näidatud read, {shown} / {total} (CSV)',
'reservations.wallet.add': 'Lisa Apple Walletisse',
'reservations.wallet.addGoogle': 'Lisa Google Walletisse',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Walleti passi ei õnnestunud luua. Proovi uuesti.',
'reservations.wallet.undated': 'Anna broneeringule kõigepealt kuupäev: Wallet näitab passi selle aja paiku.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nouvelle catégorie',
'mobileTrip.newReservation': 'Nouvelle réservation',
'mobileTrip.notes': 'Notes', // same-as-en
'mobileTrip.onMap': 'Sur la carte',
'mobileTrip.onMap': 'Carte',
'mobileTrip.profileDriving': 'Voiture',
'mobileTrip.profileWalking': 'Marche',
'mobileTrip.profileCycling': 'Vélo',
+1
View File
@@ -281,6 +281,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exporter les {shown} lignes affichées sur {total} (CSV)',
'reservations.wallet.add': 'Ajouter à Apple Wallet',
'reservations.wallet.addGoogle': 'Ajouter à Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Impossible de créer la carte Wallet. Réessayez.',
'reservations.wallet.undated':
'Donnez d’abord une date à la réservation : Wallet affiche la carte autour de ce moment.',
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Νέα κατηγορία',
'mobileTrip.newReservation': 'Νέα Κράτηση',
'mobileTrip.notes': 'Σημειώσεις',
'mobileTrip.onMap': 'Στον χάρτη',
'mobileTrip.onMap': 'Χάρτης',
'mobileTrip.profileDriving': 'Με αυτοκίνητο',
'mobileTrip.profileWalking': 'Με τα πόδια',
'mobileTrip.profileCycling': 'Με ποδήλατο',
+1
View File
@@ -280,6 +280,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Εξαγωγή των {shown} από {total} εμφανιζόμενων γραμμών (CSV)',
'reservations.wallet.add': 'Προσθήκη στο Apple Wallet',
'reservations.wallet.addGoogle': 'Προσθήκη στο Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Δεν ήταν δυνατή η δημιουργία της κάρτας Wallet. Δοκιμάστε ξανά.',
'reservations.wallet.undated':
'Δώστε πρώτα ημερομηνία στην κράτηση: το Wallet εμφανίζει την κάρτα γύρω από εκείνη την ώρα.',
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'קטגוריה חדשה',
'mobileTrip.newReservation': 'הזמנה חדשה',
'mobileTrip.notes': 'הערות',
'mobileTrip.onMap': 'על המפה',
'mobileTrip.onMap': 'מפה',
'mobileTrip.profileDriving': 'נהיגה',
'mobileTrip.profileWalking': 'הליכה',
'mobileTrip.profileCycling': 'רכיבה',
+1
View File
@@ -279,6 +279,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'ייצוא {shown} מתוך {total} השורות המוצגות (CSV)',
'reservations.wallet.add': 'הוספה ל-Apple Wallet',
'reservations.wallet.addGoogle': 'הוספה ל-Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'לא ניתן היה ליצור את כרטיס ה-Wallet. אנא נסו שוב.',
'reservations.wallet.undated': 'קודם תנו להזמנה תאריך: Wallet מציג את הכרטיס סביב המועד שלה.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Új kategória',
'mobileTrip.newReservation': 'Új foglalás',
'mobileTrip.notes': 'Jegyzetek',
'mobileTrip.onMap': 'Térképen',
'mobileTrip.onMap': 'Térkép',
'mobileTrip.profileDriving': 'Autózás',
'mobileTrip.profileWalking': 'Gyaloglás',
'mobileTrip.profileCycling': 'Kerékpározás',
+1
View File
@@ -279,6 +279,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'A megjelenített {shown} sor exportálása a(z) {total} közül (CSV)',
'reservations.wallet.add': 'Hozzáadás az Apple Wallethez',
'reservations.wallet.addGoogle': 'Hozzáadás a Google Wallethez',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Nem sikerült létrehozni a Wallet-kártyát. Próbáld újra.',
'reservations.wallet.undated': 'Előbb adj dátumot a foglalásnak: a Wallet az időpont körül jeleníti meg a kártyát.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Kategori baru',
'mobileTrip.newReservation': 'Reservasi Baru',
'mobileTrip.notes': 'Catatan',
'mobileTrip.onMap': 'Di peta',
'mobileTrip.onMap': 'Peta',
'mobileTrip.profileDriving': 'Berkendara',
'mobileTrip.profileWalking': 'Jalan kaki',
'mobileTrip.profileCycling': 'Bersepeda',
+1
View File
@@ -268,6 +268,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Ekspor {shown} dari {total} baris yang ditampilkan (CSV)',
'reservations.wallet.add': 'Tambahkan ke Apple Wallet',
'reservations.wallet.addGoogle': 'Tambahkan ke Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Pass Wallet tidak dapat dibuat. Silakan coba lagi.',
'reservations.wallet.undated': 'Beri tanggal pada pemesanan dulu: Wallet menampilkan pass di sekitar waktunya.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nuova categoria',
'mobileTrip.newReservation': 'Nuova prenotazione',
'mobileTrip.notes': 'Note',
'mobileTrip.onMap': 'Sulla mappa',
'mobileTrip.onMap': 'Mappa',
'mobileTrip.profileDriving': 'In auto',
'mobileTrip.profileWalking': 'A piedi',
'mobileTrip.profileCycling': 'In bici',
+1
View File
@@ -276,6 +276,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Esporta le {shown} righe mostrate su {total} (CSV)',
'reservations.wallet.add': 'Aggiungi ad Apple Wallet',
'reservations.wallet.addGoogle': 'Aggiungi a Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Impossibile creare il pass di Wallet. Riprova.',
'reservations.wallet.undated': 'Prima dai una data alla prenotazione: Wallet mostra il pass intorno a quel momento.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': '新しいカテゴリ',
'mobileTrip.newReservation': '新しい予約',
'mobileTrip.notes': 'メモ',
'mobileTrip.onMap': '地図上',
'mobileTrip.onMap': '地図',
'mobileTrip.profileDriving': '車',
'mobileTrip.profileWalking': '徒歩',
'mobileTrip.profileCycling': '自転車',
+1
View File
@@ -268,6 +268,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': '表示中の {shown}/{total} 行をエクスポート (CSV)',
'reservations.wallet.add': 'Apple Walletに追加',
'reservations.wallet.addGoogle': 'Google Walletに追加',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Walletパスを作成できませんでした。もう一度お試しください。',
'reservations.wallet.undated': '先に予約に日付を入れてください。Walletはその時刻の前後にパスを表示します。',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': '새 카테고리',
'mobileTrip.newReservation': '새 예약',
'mobileTrip.notes': '메모',
'mobileTrip.onMap': '지도에서',
'mobileTrip.onMap': '지도',
'mobileTrip.profileDriving': '자동차',
'mobileTrip.profileWalking': '도보',
'mobileTrip.profileCycling': '자전거',
+1
View File
@@ -268,6 +268,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': '표시된 {total}행 중 {shown}행 내보내기 (CSV)',
'reservations.wallet.add': 'Apple Wallet에 추가',
'reservations.wallet.addGoogle': 'Google Wallet에 추가',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Wallet 패스를 만들지 못했습니다. 다시 시도하세요.',
'reservations.wallet.undated': '먼저 예약에 날짜를 지정하세요. Wallet은 그 시간 즈음에 패스를 보여 줍니다.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nieuwe categorie',
'mobileTrip.newReservation': 'Nieuwe reservering',
'mobileTrip.notes': 'Notities',
'mobileTrip.onMap': 'Op kaart',
'mobileTrip.onMap': 'Kaart',
'mobileTrip.profileDriving': 'Auto',
'mobileTrip.profileWalking': 'Lopen',
'mobileTrip.profileCycling': 'Fietsen',
+1
View File
@@ -277,6 +277,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'De {shown} van {total} getoonde rijen exporteren (CSV)',
'reservations.wallet.add': 'Voeg toe aan Apple Wallet',
'reservations.wallet.addGoogle': 'Voeg toe aan Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'De Wallet-pas kon niet worden gemaakt. Probeer het opnieuw.',
'reservations.wallet.undated': 'Geef de boeking eerst een datum: Wallet toont de pas rond dat moment.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nowa kategoria',
'mobileTrip.newReservation': 'Nowa rezerwacja',
'mobileTrip.notes': 'Notatki',
'mobileTrip.onMap': 'Na mapie',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'Samochodem',
'mobileTrip.profileWalking': 'Pieszo',
'mobileTrip.profileCycling': 'Rowerem',
+1
View File
@@ -291,6 +291,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Eksportuj wyświetlone wiersze: {shown} z {total} (CSV)',
'reservations.wallet.add': 'Dodaj do Apple Wallet',
'reservations.wallet.addGoogle': 'Dodaj do Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Nie udało się utworzyć karty Wallet. Spróbuj ponownie.',
'reservations.wallet.undated': 'Najpierw nadaj rezerwacji datę: Wallet pokazuje kartę w okolicach tego terminu.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Новая категория',
'mobileTrip.newReservation': 'Новое бронирование',
'mobileTrip.notes': 'Заметки',
'mobileTrip.onMap': 'На карте',
'mobileTrip.onMap': 'Карта',
'mobileTrip.profileDriving': 'На машине',
'mobileTrip.profileWalking': 'Пешком',
'mobileTrip.profileCycling': 'На велосипеде',
+1
View File
@@ -289,6 +289,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Экспортировать показанные строки: {shown} из {total} (CSV)',
'reservations.wallet.add': 'Добавить в Apple Wallet',
'reservations.wallet.addGoogle': 'Добавить в Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Не удалось создать карту Wallet. Повторите попытку.',
'reservations.wallet.undated': 'Сначала укажите дату брони: Wallet показывает карту ближе к этому времени.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Nová kategória',
'mobileTrip.newReservation': 'Nová rezervácia',
'mobileTrip.notes': 'Poznámky',
'mobileTrip.onMap': 'Na mape',
'mobileTrip.onMap': 'Mapa',
'mobileTrip.profileDriving': 'Autom',
'mobileTrip.profileWalking': 'Pešo',
'mobileTrip.profileCycling': 'Na bicykli',
+1
View File
@@ -285,6 +285,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exportovať zobrazené riadky, {shown} z {total} (CSV)',
'reservations.wallet.add': 'Pridať do Apple Wallet',
'reservations.wallet.addGoogle': 'Pridať do Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Kartu do Wallet sa nepodarilo vytvoriť. Skúste to znova.',
'reservations.wallet.undated': 'Najprv rezervácii zadajte dátum: Wallet kartu zobrazí okolo toho času.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Ny kategori',
'mobileTrip.newReservation': 'Ny bokning',
'mobileTrip.notes': 'Anteckningar',
'mobileTrip.onMap': 'På kartan',
'mobileTrip.onMap': 'Karta',
'mobileTrip.profileDriving': 'Bil',
'mobileTrip.profileWalking': 'Gång',
'mobileTrip.profileCycling': 'Cykel',
+1
View File
@@ -276,6 +276,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Exportera de {shown} av {total} visade raderna (CSV)',
'reservations.wallet.add': 'Lägg till i Apple Wallet',
'reservations.wallet.addGoogle': 'Lägg till i Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Wallet-kortet kunde inte skapas. Försök igen.',
'reservations.wallet.undated': 'Ge bokningen ett datum först: Wallet visar kortet runt den tiden.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'หมวดหมู่ใหม่',
'mobileTrip.newReservation': 'การจองใหม่',
'mobileTrip.notes': 'หมายเหตุ',
'mobileTrip.onMap': 'บนแผนที่',
'mobileTrip.onMap': 'แผนที่',
'mobileTrip.profileDriving': 'ขับรถ',
'mobileTrip.profileWalking': 'เดิน',
'mobileTrip.profileCycling': 'ปั่นจักรยาน',
+1
View File
@@ -270,6 +270,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'ส่งออก {shown} จาก {total} แถวที่แสดง (CSV)',
'reservations.wallet.add': 'เพิ่มลงใน Apple Wallet',
'reservations.wallet.addGoogle': 'เพิ่มลงใน Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'สร้างบัตร Wallet ไม่สำเร็จ โปรดลองอีกครั้ง',
'reservations.wallet.undated': 'กำหนดวันที่ให้การจองก่อน Wallet จะแสดงบัตรในช่วงเวลานั้น',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Yeni kategori',
'mobileTrip.newReservation': 'Yeni Rezervasyon',
'mobileTrip.notes': 'Notlar',
'mobileTrip.onMap': 'Haritada',
'mobileTrip.onMap': 'Harita',
'mobileTrip.profileDriving': 'Araba',
'mobileTrip.profileWalking': 'Yürüyüş',
'mobileTrip.profileCycling': 'Bisiklet',
+1
View File
@@ -277,6 +277,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Gösterilen {total} satırdan {shown} tanesini dışa aktar (CSV)',
'reservations.wallet.add': 'Apple Cüzdan’a Ekle',
'reservations.wallet.addGoogle': 'Google Cüzdan’a Ekle',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Cüzdan kartı oluşturulamadı. Lütfen tekrar deneyin.',
'reservations.wallet.undated': 'Önce rezervasyona bir tarih verin: Cüzdan kartı o zamana yakın gösterir.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Нова категорія',
'mobileTrip.newReservation': 'Нове бронювання',
'mobileTrip.notes': 'Нотатки',
'mobileTrip.onMap': 'На карті',
'mobileTrip.onMap': 'Мапа',
'mobileTrip.profileDriving': 'На авто',
'mobileTrip.profileWalking': 'Пішки',
'mobileTrip.profileCycling': 'Велосипедом',
+1
View File
@@ -289,6 +289,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Експортувати показані рядки: {shown} із {total} (CSV)',
'reservations.wallet.add': 'Додати до Apple Wallet',
'reservations.wallet.addGoogle': 'Додати до Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Не вдалося створити картку Wallet. Повторіть спробу.',
'reservations.wallet.undated': 'Спершу вкажіть дату бронювання: Wallet показує картку ближче до цього часу.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': 'Danh mục mới',
'mobileTrip.newReservation': 'Đặt chỗ mới',
'mobileTrip.notes': 'Ghi chú',
'mobileTrip.onMap': 'Trên bản đồ',
'mobileTrip.onMap': 'Bản đồ',
'mobileTrip.profileDriving': 'Lái xe',
'mobileTrip.profileWalking': 'Đi bộ',
'mobileTrip.profileCycling': 'Đạp xe',
+1
View File
@@ -271,6 +271,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': 'Xuất {shown} trong {total} dòng đang hiển thị (CSV)',
'reservations.wallet.add': 'Thêm vào Apple Wallet',
'reservations.wallet.addGoogle': 'Thêm vào Google Wallet',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': 'Không thể tạo thẻ Wallet. Vui lòng thử lại.',
'reservations.wallet.undated': 'Hãy đặt ngày cho đặt chỗ trước: Wallet sẽ hiện thẻ vào khoảng thời gian đó.',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': '新增分類',
'mobileTrip.newReservation': '新建預訂',
'mobileTrip.notes': '備註',
'mobileTrip.onMap': '在地圖上',
'mobileTrip.onMap': '地圖',
'mobileTrip.profileDriving': '開車',
'mobileTrip.profileWalking': '步行',
'mobileTrip.profileCycling': '騎自行車',
+1
View File
@@ -263,6 +263,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': '匯出顯示的 {shown}/{total} 列 (CSV)',
'reservations.wallet.add': '加入 Apple 錢包',
'reservations.wallet.addGoogle': '加入 Google 錢包',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': '無法產生錢包票卡。請重試。',
'reservations.wallet.undated': '請先為訂位設定日期:錢包會在那個時間前後顯示票卡。',
};
+1 -1
View File
@@ -31,7 +31,7 @@ const mobileTrip: TranslationStrings = {
'mobileTrip.newCategory': '新建分类',
'mobileTrip.newReservation': '新建预订',
'mobileTrip.notes': '备注',
'mobileTrip.onMap': '在地图上',
'mobileTrip.onMap': '地图',
'mobileTrip.profileDriving': '驾车',
'mobileTrip.profileWalking': '步行',
'mobileTrip.profileCycling': '骑行',
+1
View File
@@ -263,6 +263,7 @@ const reservations: TranslationStrings = {
'reservations.exportCsvFiltered': '导出显示的 {shown}/{total} 行 (CSV)',
'reservations.wallet.add': '添加到 Apple 钱包',
'reservations.wallet.addGoogle': '添加到 Google 钱包',
'reservations.wallet.short': 'Wallet', // same-as-en
'reservations.wallet.failed': '无法生成钱包卡券。请重试。',
'reservations.wallet.undated': '请先为预订设置日期:钱包会在那个时间前后显示卡券。',
};