feat(assistant): booking and stay cards, and a read of the bookings with their details

This commit is contained in:
Maurice
2026-10-22 15:50:50 +02:00
parent 51e5dbef03
commit b391ddcc43
67 changed files with 6336 additions and 103 deletions
@@ -0,0 +1,125 @@
import {
BOOKING_CHANGED_FIELDS,
bookingCardSchema,
type BookingItem,
type BookingLeg,
type BookingStay,
type BookingTicket,
} from './booking.card';
import { BOOKING_APPLIED_ENTITIES, BOOKING_VERB_KEYS } from './booking.contract';
import { storedTrekCardSchema, trekCardSchema } from './index';
import { describe, expect, it } from 'vitest';
const day = { id: 31, number: 1, date: '2026-06-03' };
const LEG: BookingLeg = {
carrier: 'Lufthansa',
number: 'LH 400',
departs: '08:15',
departsDay: day,
arrives: '11:05',
arrivesDay: day,
minutes: 530,
seat: '12A',
platform: null,
};
const TICKET: BookingTicket = {
shape: 'ticket',
stops: [
{ name: 'Frankfurt', code: 'FRA', lat: 50.03, lng: 8.57 },
{ name: 'New York', code: 'JFK', lat: 40.64, lng: -73.78 },
],
legs: [LEG],
minutes: 530,
mappable: true,
};
const STAY: BookingStay = {
shape: 'stay',
accommodationId: 601,
placeId: 12,
address: 'Invalidenstraße 38',
lat: 52.53,
lng: 13.38,
photoKey: 'ChIJmercure',
checkIn: { day, from: '15:00', until: '20:00' },
checkOut: { day: { id: 33, number: 3, date: '2026-06-05' }, by: '11:00' },
nights: 2,
};
const ticket: BookingItem = {
tripId: 4,
tripTitle: null,
reservationId: 501,
type: 'flight',
title: 'Frankfurt to New York',
status: 'confirmed',
needsReview: false,
hasReference: true,
price: { amount: 420, currency: 'EUR' },
travelers: [{ id: 7, name: 'mia', avatarKey: 'mia.png' }],
moreTravelers: 0,
changed: [],
body: TICKET,
};
const stay: BookingItem = {
...ticket,
reservationId: null,
type: 'hotel',
status: null,
body: STAY,
};
const card = (items: unknown[], extra: Record<string, unknown> = {}) => ({
kind: 'booking',
change: 'none',
items,
more: 0,
...extra,
});
describe('bookingCardSchema', () => {
it('CARDBOOK-001: takes a ticket, a stay and a venue in one card, and the union reads it', () => {
const body = { shape: 'venue', day, starts: '19:00', ends: null, location: 'Borchardt', placeId: 13 };
const venue = { ...ticket, body: { ...body, lat: null, lng: null } };
expect(bookingCardSchema.safeParse(card([ticket, stay, venue])).success).toBe(true);
expect(trekCardSchema.safeParse(card([ticket], { change: 'update' })).success).toBe(true);
});
it('CARDBOOK-002: holds one to eight bookings and counts the rest', () => {
expect(bookingCardSchema.safeParse(card([])).success).toBe(false);
expect(bookingCardSchema.safeParse(card(Array.from({ length: 9 }, () => ticket))).success).toBe(false);
expect(bookingCardSchema.safeParse(card([ticket], { more: -1 })).success).toBe(false);
});
it('CARDBOOK-003: refuses a picture address or a coordinate key as photo key, and a clock past 23:59', () => {
const photo = (photoKey: string) => card([{ ...stay, body: { ...STAY, photoKey } }]);
expect(bookingCardSchema.safeParse(photo('https://maps.example/x.jpg')).success).toBe(false);
expect(bookingCardSchema.safeParse(photo('coords:52.5,13.4')).success).toBe(false);
const late = { ...ticket, body: { ...TICKET, legs: [{ ...LEG, departs: '24:00' }] } };
expect(bookingCardSchema.safeParse(card([late])).success).toBe(false);
});
it('CARDBOOK-004: refuses a ticket without a leg, an unknown shape, a lowercase code and a currency in words', () => {
expect(bookingCardSchema.safeParse(card([{ ...ticket, body: { ...TICKET, legs: [] } }])).success).toBe(false);
expect(bookingCardSchema.safeParse(card([{ ...ticket, body: { shape: 'cruise' } }])).success).toBe(false);
const code = { ...ticket, body: { ...TICKET, stops: [{ name: 'Frankfurt', code: 'fra', lat: null, lng: null }] } };
expect(bookingCardSchema.safeParse(card([code])).success).toBe(false);
const words = { ...ticket, price: { amount: 5, currency: 'euro' } };
expect(bookingCardSchema.safeParse(card([words])).success).toBe(false);
});
it('CARDBOOK-005: a changed field must be one the card knows; a broken card reads as none, never the message', () => {
expect(bookingCardSchema.safeParse(card([{ ...ticket, changed: [...BOOKING_CHANGED_FIELDS] }])).success).toBe(true);
expect(bookingCardSchema.safeParse(card([{ ...ticket, changed: ['seat'] }])).success).toBe(false);
expect(storedTrekCardSchema.parse(card([{ ...ticket, title: '' }]))).toBeNull();
});
it('CARDBOOK-006: the bookings add their verbs and the stay as an applied entity', () => {
expect(BOOKING_VERB_KEYS).toEqual(['addStay', 'updateStay', 'updateReservation']);
expect(BOOKING_APPLIED_ENTITIES).toEqual(['accommodation']);
});
});
+148 -3
View File
@@ -1,8 +1,153 @@
import { idSchema } from '../../common/primitives.schema';
import { RESERVATION_STATUSES } from '../../reservation/reservation-types';
import {
cardClockSchema,
cardCountSchema,
cardDaySchema,
cardLatSchema,
cardLngSchema,
cardMoneySchema,
cardPersonSchema,
cardPhotoKeySchema,
cardText,
} from './card-parts';
import { z } from 'zod';
/**
* Bookings: flights, trains, stays and other reservations. Only its kind so far; the booking cards
* give it its fields.
* Bookings in the assistant chat: a flight, a train, a hire car (a ticket), a
* hotel or any stay (a stay), a table, a show, a tour or a car park (a
* venue). One card per tool call holds the bookings it is about, at most
* eight, with the rest counted; an e-ticket file with a flight, a hotel and a
* flight back stays one itinerary. A booking's reference never travels, only
* that it has one: the chat is stored and can be shared, and the planner
* blurs it too.
*/
export const bookingCardSchema = z.object({ kind: z.literal('booking') });
/** The type column is free text: any short key passes, the client draws an unknown one as `other`. */
const bookingTypeSchema = z.string().regex(/^[a-z_]{1,30}$/);
const lat = cardLatSchema.nullable();
const lng = cardLngSchema.nullable();
/** One end or stop of a route: the airport or station, its code where it has one. */
const bookingStopSchema = z.object({
name: cardText(80),
code: z
.string()
.regex(/^[A-Z0-9]{2,5}$/)
.nullable(),
lat,
lng,
});
/** One segment; a stopover's arrival lives only here (a stop's endpoint carries the onward departure). */
const bookingLegSchema = z.object({
carrier: cardText(60).nullable(),
number: cardText(20).nullable(),
departs: cardClockSchema.nullable(),
departsDay: cardDaySchema.nullable(),
arrives: cardClockSchema.nullable(),
arrivesDay: cardDaySchema.nullable(),
/** Only when both ends know their zone. */
minutes: z.number().int().min(1).max(10_080).nullable(),
seat: cardText(20).nullable(),
platform: cardText(20).nullable(),
});
const ticketBodySchema = z.object({
shape: z.literal('ticket'),
/** From, the stops, to; empty when no route is known (a hire car, a taxi). */
stops: z.array(bookingStopSchema).max(9),
/** One per segment between the stops, else exactly one. */
legs: z.array(bookingLegSchema).min(1).max(8),
/** First departure to last arrival. */
minutes: z.number().int().min(1).max(20_160).nullable(),
/** A saved booking with two stops that have coordinates: the plan can draw it. */
mappable: z.boolean(),
});
const stayBodySchema = z.object({
shape: z.literal('stay'),
/** Null while a create or a new place waits. */
accommodationId: idSchema.nullable(),
placeId: idSchema.nullable(),
address: cardText(200).nullable(),
lat,
lng,
/** A Google place id for TREK's photo proxy; never a picture address. */
photoKey: cardPhotoKeySchema.nullable(),
checkIn: z
.object({ day: cardDaySchema, from: cardClockSchema.nullable(), until: cardClockSchema.nullable() })
.nullable(),
checkOut: z.object({ day: cardDaySchema, by: cardClockSchema.nullable() }).nullable(),
nights: z.number().int().min(0).max(366).nullable(),
});
const venueBodySchema = z.object({
shape: z.literal('venue'),
day: cardDaySchema.nullable(),
starts: cardClockSchema.nullable(),
ends: cardClockSchema.nullable(),
/** The location text, else the linked place's name. */
location: cardText(200).nullable(),
placeId: idSchema.nullable(),
lat,
lng,
});
/** What an update changes, as the card shows it (its derived values, not the raw arguments). */
export const BOOKING_CHANGED_FIELDS = [
'title',
'type',
'status',
'day',
'time',
'route',
'stay',
'checkIn',
'checkOut',
'location',
'price',
'travelers',
'reference',
] as const;
export type BookingChangedField = (typeof BOOKING_CHANGED_FIELDS)[number];
export const bookingItemSchema = z.object({
tripId: idSchema,
/** Only on a row of another trip (the upcoming bookings across every trip). */
tripTitle: cardText(120).nullable(),
reservationId: idSchema.nullable(),
type: bookingTypeSchema,
title: cardText(200),
/** Null for a transit journey, a bare stay, or a status not known. */
status: z.enum(RESERVATION_STATUSES).nullable(),
needsReview: z.boolean(),
/** A confirmation number exists; the number itself never travels. */
hasReference: z.boolean(),
price: cardMoneySchema.nullable(),
travelers: z.array(cardPersonSchema).max(8),
moreTravelers: z.number().int().min(0).max(500),
changed: z.array(z.enum(BOOKING_CHANGED_FIELDS)).max(BOOKING_CHANGED_FIELDS.length),
body: z.discriminatedUnion('shape', [ticketBodySchema, stayBodySchema, venueBodySchema]),
});
export type BookingItem = z.infer<typeof bookingItemSchema>;
export type BookingBody = BookingItem['body'];
export type BookingTicket = Extract<BookingBody, { shape: 'ticket' }>;
export type BookingStay = Extract<BookingBody, { shape: 'stay' }>;
export type BookingVenue = Extract<BookingBody, { shape: 'venue' }>;
export type BookingLeg = BookingTicket['legs'][number];
export type BookingStop = BookingTicket['stops'][number];
/** What a held write does to its bookings; `none` on an answer and on an applied change. */
export const BOOKING_CHANGES = ['none', 'create', 'update', 'remove'] as const;
export const bookingCardSchema = z.object({
kind: z.literal('booking'),
change: z.enum(BOOKING_CHANGES),
items: z.array(bookingItemSchema).min(1).max(8),
/** Bookings the answer held past the eight shown. */
more: cardCountSchema,
});
export type BookingCard = z.infer<typeof bookingCardSchema>;
@@ -10,5 +10,7 @@ export * from './booking.card';
* or entity is added here and nowhere else.
*/
export const BOOKING_CARD_SCHEMAS = [bookingCardSchema] as const;
export const BOOKING_VERB_KEYS = [] as const;
export const BOOKING_APPLIED_ENTITIES = [] as const;
/** addReservation and importBooking sit in the core list already. */
export const BOOKING_VERB_KEYS = ['addStay', 'updateStay', 'updateReservation'] as const;
/** 'reservation' is a core entity already; a stay is its own row. */
export const BOOKING_APPLIED_ENTITIES = ['accommodation'] as const;
+56 -1
View File
@@ -1,4 +1,59 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'الحجوزات',
'assistant.card.booking.open': 'افتح الحجز',
'assistant.card.booking.openStay': 'اعرض في الخطة',
'assistant.card.booking.more': '{count} حجز آخر',
'assistant.card.booking.more.zero': 'لا حجوزات أخرى',
'assistant.card.booking.more.one': 'حجز آخر واحد',
'assistant.card.booking.more.two': 'حجزان آخران',
'assistant.card.booking.more.few': '{count} حجوزات أخرى',
'assistant.card.booking.more.many': '{count} حجزًا آخر',
'assistant.card.booking.nights': '{count} ليلة',
'assistant.card.booking.nights.zero': 'لا ليالٍ',
'assistant.card.booking.nights.one': 'ليلة واحدة',
'assistant.card.booking.nights.two': 'ليلتان',
'assistant.card.booking.nights.few': '{count} ليالٍ',
'assistant.card.booking.nights.many': '{count} ليلة',
'assistant.card.booking.stops': '{count} توقف',
'assistant.card.booking.stops.zero': 'بلا توقف',
'assistant.card.booking.stops.one': 'توقف واحد',
'assistant.card.booking.stops.two': 'توقفان',
'assistant.card.booking.stops.few': '{count} توقفات',
'assistant.card.booking.stops.many': '{count} توقفًا',
'assistant.card.booking.direct': 'رحلة مباشرة',
'assistant.card.booking.layoverAt': '{duration} في {place}',
'assistant.card.booking.arrivesLater': 'يصل بعد {count} يوم',
'assistant.card.booking.arrivesLater.zero': 'يصل في اليوم نفسه',
'assistant.card.booking.arrivesLater.one': 'يصل في اليوم التالي',
'assistant.card.booking.arrivesLater.two': 'يصل بعد يومين',
'assistant.card.booking.arrivesLater.few': 'يصل بعد {count} أيام',
'assistant.card.booking.arrivesLater.many': 'يصل بعد {count} يومًا',
'assistant.card.booking.reference': 'رقم الحجز محفوظ',
'assistant.card.booking.referenceHint': 'يبقى رقم الحجز مع الحجز، لا في المحادثة',
'assistant.card.booking.seat': 'المقعد {seat}',
'assistant.card.booking.platform': 'الرصيف {platform}',
'assistant.card.booking.checkInAt': 'تسجيل الوصول {time}',
'assistant.card.booking.checkOutAt': 'تسجيل المغادرة {time}',
'assistant.card.booking.cancelled': 'ملغى',
'assistant.card.booking.inTrip': 'في رحلة {trip}',
'assistant.card.booking.range': 'من {from} إلى {to}',
'assistant.change.verb.addStay': 'إضافة إقامة',
'assistant.change.verb.updateStay': 'تغيير الإقامة',
'assistant.change.verb.updateReservation': 'تغيير الحجز',
'assistant.tool.set_reservation_travelers': 'تغيير المسافرين',
'assistant.tool.link_hotel_accommodation': 'ربط الفندق بلياليه',
'assistant.tool.update_transport': 'تغيير وسيلة النقل',
'assistant.tool.delete_transport': 'حذف وسيلة النقل',
'assistant.tool.delete_accommodation': 'إلغاء الإقامة',
'assistant.tool.reorder_reservations': 'إعادة ترتيب الحجوزات',
'assistant.tool.import_airtrail_flights': 'استيراد الرحلات من AirTrail',
'assistant.step.bookings': 'قراءة الحجوزات',
'assistant.step.stays': 'قراءة أماكن إقامتك',
'assistant.step.upcoming': 'الاطلاع على الحجوزات القادمة',
'assistant.followUp.bookingsOpen': 'أي الحجوزات ما زالت معلقة؟',
'assistant.followUp.bookingsNights': 'هل لكل ليلة مكان إقامة؟',
'assistant.followUp.bookingsConfirm': 'تأكيد الحجوزات المعلقة',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Rezervasiyalar',
'assistant.card.booking.open': 'Rezervasiyanı aç',
'assistant.card.booking.openStay': 'Planda göstər',
'assistant.card.booking.more': 'Daha {count} rezervasiya',
'assistant.card.booking.more.one': 'Daha {count} rezervasiya',
'assistant.card.booking.nights': '{count} gecə',
'assistant.card.booking.nights.one': '{count} gecə',
'assistant.card.booking.stops': '{count} aralıq dayanacaq',
'assistant.card.booking.stops.one': '{count} aralıq dayanacaq',
'assistant.card.booking.direct': 'Birbaşa',
'assistant.card.booking.layoverAt': '{place} şəhərində {duration}',
'assistant.card.booking.arrivesLater': '{count} gün sonra çatır',
'assistant.card.booking.arrivesLater.one': '{count} gün sonra çatır',
'assistant.card.booking.reference': 'Rezervasiya kodu saxlanıldı',
'assistant.card.booking.referenceHint': 'Rezervasiya kodu söhbətdə deyil, rezervasiyada saxlanılır',
'assistant.card.booking.seat': 'Oturacaq {seat}',
'assistant.card.booking.platform': 'Platforma {platform}',
'assistant.card.booking.checkInAt': 'Giriş {time}',
'assistant.card.booking.checkOutAt': 'Çıxış {time}',
'assistant.card.booking.cancelled': 'Ləğv edilib',
'assistant.card.booking.inTrip': '{trip} səfərində',
'assistant.card.booking.range': '{from} ilə {to} arası',
'assistant.change.verb.addStay': 'Yerləşmə əlavə et',
'assistant.change.verb.updateStay': 'Qalmanı dəyiş',
'assistant.change.verb.updateReservation': 'Rezervasiyanı dəyiş',
'assistant.tool.set_reservation_travelers': 'Kimin səyahət etdiyini dəyiş',
'assistant.tool.link_hotel_accommodation': 'Oteli gecələrinə bağla',
'assistant.tool.update_transport': 'Nəqliyyatı dəyiş',
'assistant.tool.delete_transport': 'Nəqliyyatı sil',
'assistant.tool.delete_accommodation': 'Qalmanı ləğv et',
'assistant.tool.reorder_reservations': 'Rezervasiyaları yenidən sırala',
'assistant.tool.import_airtrail_flights': 'AirTrail-dan uçuşları idxal et',
'assistant.step.bookings': 'Rezervasiyalar oxunur',
'assistant.step.stays': 'Qalacağınız yerlər oxunur',
'assistant.step.upcoming': 'Yaxınlaşan rezervasiyalara baxılır',
'assistant.followUp.bookingsOpen': 'Hansı rezervasiyalar hələ gözləyir?',
'assistant.followUp.bookingsNights': 'Hər gecə üçün qalacaq yer varmı?',
'assistant.followUp.bookingsConfirm': 'Gözləyən rezervasiyaları təsdiqlə',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Reservas',
'assistant.card.booking.open': 'Abrir a reserva',
'assistant.card.booking.openStay': 'Mostrar no plano',
'assistant.card.booking.more': 'Mais {count} reservas',
'assistant.card.booking.more.one': 'Mais {count} reserva',
'assistant.card.booking.nights': '{count} noites',
'assistant.card.booking.nights.one': '{count} noite',
'assistant.card.booking.stops': '{count} escalas',
'assistant.card.booking.stops.one': '{count} escala',
'assistant.card.booking.direct': 'Direto',
'assistant.card.booking.layoverAt': '{duration} em {place}',
'assistant.card.booking.arrivesLater': 'Chega {count} dias depois',
'assistant.card.booking.arrivesLater.one': 'Chega {count} dia depois',
'assistant.card.booking.reference': 'Código salvo',
'assistant.card.booking.referenceHint': 'O código da reserva fica com a reserva, não no chat',
'assistant.card.booking.seat': 'Assento {seat}',
'assistant.card.booking.platform': 'Plataforma {platform}',
'assistant.card.booking.checkInAt': 'Entrada {time}',
'assistant.card.booking.checkOutAt': 'Saída {time}',
'assistant.card.booking.cancelled': 'Cancelada',
'assistant.card.booking.inTrip': 'Em {trip}',
'assistant.card.booking.range': 'de {from} a {to}',
'assistant.change.verb.addStay': 'Adicionar hospedagem',
'assistant.change.verb.updateStay': 'Alterar a estadia',
'assistant.change.verb.updateReservation': 'Alterar a reserva',
'assistant.tool.set_reservation_travelers': 'Alterar quem viaja',
'assistant.tool.link_hotel_accommodation': 'Vincular o hotel às suas noites',
'assistant.tool.update_transport': 'Alterar o transporte',
'assistant.tool.delete_transport': 'Excluir o transporte',
'assistant.tool.delete_accommodation': 'Cancelar a estadia',
'assistant.tool.reorder_reservations': 'Reordenar as reservas',
'assistant.tool.import_airtrail_flights': 'Importar voos do AirTrail',
'assistant.step.bookings': 'Lendo as reservas',
'assistant.step.stays': 'Lendo onde você se hospeda',
'assistant.step.upcoming': 'Vendo as próximas reservas',
'assistant.followUp.bookingsOpen': 'Quais reservas ainda estão pendentes?',
'assistant.followUp.bookingsNights': 'Toda noite tem hospedagem?',
'assistant.followUp.bookingsConfirm': 'Confirmar as reservas pendentes',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Reserves',
'assistant.card.booking.open': 'Obre la reserva',
'assistant.card.booking.openStay': 'Mostra al pla',
'assistant.card.booking.more': '{count} reserves més',
'assistant.card.booking.more.one': '{count} reserva més',
'assistant.card.booking.nights': '{count} nits',
'assistant.card.booking.nights.one': '{count} nit',
'assistant.card.booking.stops': '{count} escales',
'assistant.card.booking.stops.one': '{count} escala',
'assistant.card.booking.direct': 'Directe',
'assistant.card.booking.layoverAt': '{duration} a {place}',
'assistant.card.booking.arrivesLater': 'Arriba {count} dies després',
'assistant.card.booking.arrivesLater.one': 'Arriba {count} dia després',
'assistant.card.booking.reference': 'Referència desada',
'assistant.card.booking.referenceHint': 'La referència es queda amb la reserva, no al xat',
'assistant.card.booking.seat': 'Seient {seat}',
'assistant.card.booking.platform': 'Andana {platform}',
'assistant.card.booking.checkInAt': 'Entrada {time}',
'assistant.card.booking.checkOutAt': 'Sortida {time}',
'assistant.card.booking.cancelled': 'Cancel·lada',
'assistant.card.booking.inTrip': 'A {trip}',
'assistant.card.booking.range': 'del {from} al {to}',
'assistant.change.verb.addStay': 'Afegeix allotjament',
'assistant.change.verb.updateStay': 'Canvia l’estada',
'assistant.change.verb.updateReservation': 'Canvia la reserva',
'assistant.tool.set_reservation_travelers': 'Canvia qui viatja',
'assistant.tool.link_hotel_accommodation': 'Vincula l’hotel a les seves nits',
'assistant.tool.update_transport': 'Canvia el transport',
'assistant.tool.delete_transport': 'Elimina el transport',
'assistant.tool.delete_accommodation': 'Cancel·la l’estada',
'assistant.tool.reorder_reservations': 'Reordena les reserves',
'assistant.tool.import_airtrail_flights': 'Importa vols d’AirTrail',
'assistant.step.bookings': 'Llegint les reserves',
'assistant.step.stays': 'Llegint on t’allotges',
'assistant.step.upcoming': 'Mirant les properes reserves',
'assistant.followUp.bookingsOpen': 'Quines reserves encara estan pendents?',
'assistant.followUp.bookingsNights': 'Cada nit té allotjament?',
'assistant.followUp.bookingsConfirm': 'Confirma les reserves pendents',
};
export default assistantBooking;
+44 -1
View File
@@ -1,4 +1,47 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Rezervace',
'assistant.card.booking.open': 'Otevřít rezervaci',
'assistant.card.booking.openStay': 'Zobrazit v plánu',
'assistant.card.booking.more': 'Dalších {count} rezervací',
'assistant.card.booking.more.one': 'Ještě {count} rezervace',
'assistant.card.booking.more.few': 'Další {count} rezervace',
'assistant.card.booking.nights': '{count} nocí',
'assistant.card.booking.nights.one': '{count} noc',
'assistant.card.booking.nights.few': '{count} noci',
'assistant.card.booking.stops': '{count} přestupů',
'assistant.card.booking.stops.one': '{count} přestup',
'assistant.card.booking.stops.few': '{count} přestupy',
'assistant.card.booking.direct': 'Přímý spoj',
'assistant.card.booking.layoverAt': '{duration} v {place}',
'assistant.card.booking.arrivesLater': 'Přílet o {count} dní později',
'assistant.card.booking.arrivesLater.one': 'Přílet o {count} den později',
'assistant.card.booking.arrivesLater.few': 'Přílet o {count} dny později',
'assistant.card.booking.reference': 'Kód rezervace uložen',
'assistant.card.booking.referenceHint': 'Kód rezervace zůstává u rezervace, ne v chatu',
'assistant.card.booking.seat': 'Sedadlo {seat}',
'assistant.card.booking.platform': 'Nástupiště {platform}',
'assistant.card.booking.checkInAt': 'Příjezd {time}',
'assistant.card.booking.checkOutAt': 'Odjezd {time}',
'assistant.card.booking.cancelled': 'Zrušeno',
'assistant.card.booking.inTrip': 'V cestě {trip}',
'assistant.card.booking.range': '{from} až {to}',
'assistant.change.verb.addStay': 'Přidat ubytování',
'assistant.change.verb.updateStay': 'Změnit pobyt',
'assistant.change.verb.updateReservation': 'Změnit rezervaci',
'assistant.tool.set_reservation_travelers': 'Změnit, kdo cestuje',
'assistant.tool.link_hotel_accommodation': 'Propojit hotel s jeho nocemi',
'assistant.tool.update_transport': 'Změnit dopravu',
'assistant.tool.delete_transport': 'Smazat dopravu',
'assistant.tool.delete_accommodation': 'Zrušit pobyt',
'assistant.tool.reorder_reservations': 'Přeřadit rezervace',
'assistant.tool.import_airtrail_flights': 'Importovat lety z AirTrail',
'assistant.step.bookings': 'Čtu rezervace',
'assistant.step.stays': 'Čtu, kde bydlíš',
'assistant.step.upcoming': 'Dívám se na nadcházející rezervace',
'assistant.followUp.bookingsOpen': 'Které rezervace ještě čekají?',
'assistant.followUp.bookingsNights': 'Má každá noc ubytování?',
'assistant.followUp.bookingsConfirm': 'Potvrdit čekající rezervace',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Buchungen',
'assistant.card.booking.open': 'Buchung öffnen',
'assistant.card.booking.openStay': 'Im Plan zeigen',
'assistant.card.booking.more': '{count} weitere Buchungen',
'assistant.card.booking.more.one': '{count} weitere Buchung',
'assistant.card.booking.nights': '{count} Nächte',
'assistant.card.booking.nights.one': '{count} Nacht',
'assistant.card.booking.stops': '{count} Zwischenstopps',
'assistant.card.booking.stops.one': '{count} Zwischenstopp',
'assistant.card.booking.direct': 'Direktverbindung',
'assistant.card.booking.layoverAt': '{duration} Aufenthalt in {place}',
'assistant.card.booking.arrivesLater': 'Ankunft {count} Tage später',
'assistant.card.booking.arrivesLater.one': 'Ankunft {count} Tag später',
'assistant.card.booking.reference': 'Buchungsnummer gespeichert',
'assistant.card.booking.referenceHint': 'Die Buchungsnummer bleibt bei der Buchung, nicht im Chat',
'assistant.card.booking.seat': 'Sitz {seat}',
'assistant.card.booking.platform': 'Gleis {platform}',
'assistant.card.booking.checkInAt': 'Anreise {time}',
'assistant.card.booking.checkOutAt': 'Abreise {time}',
'assistant.card.booking.cancelled': 'Storniert',
'assistant.card.booking.inTrip': 'Reise: {trip}',
'assistant.card.booking.range': '{from} bis {to}',
'assistant.change.verb.addStay': 'Unterkunft hinzufügen',
'assistant.change.verb.updateStay': 'Aufenthalt ändern',
'assistant.change.verb.updateReservation': 'Buchung ändern',
'assistant.tool.set_reservation_travelers': 'Reisende ändern',
'assistant.tool.link_hotel_accommodation': 'Hotel mit seinen Nächten verknüpfen',
'assistant.tool.update_transport': 'Transport ändern',
'assistant.tool.delete_transport': 'Transport löschen',
'assistant.tool.delete_accommodation': 'Aufenthalt stornieren',
'assistant.tool.reorder_reservations': 'Buchungen neu ordnen',
'assistant.tool.import_airtrail_flights': 'Flüge aus AirTrail importieren',
'assistant.step.bookings': 'Liest die Buchungen',
'assistant.step.stays': 'Liest, wo du übernachtest',
'assistant.step.upcoming': 'Sieht kommende Buchungen durch',
'assistant.followUp.bookingsOpen': 'Welche Buchungen sind noch offen?',
'assistant.followUp.bookingsNights': 'Hat jede Nacht eine Unterkunft?',
'assistant.followUp.bookingsConfirm': 'Offene Buchungen bestätigen',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Bookings',
'assistant.card.booking.open': 'Open the booking',
'assistant.card.booking.openStay': 'Show in the plan',
'assistant.card.booking.more': '{count} more bookings',
'assistant.card.booking.more.one': '{count} more booking',
'assistant.card.booking.nights': '{count} nights',
'assistant.card.booking.nights.one': '{count} night',
'assistant.card.booking.stops': '{count} stops',
'assistant.card.booking.stops.one': '{count} stop',
'assistant.card.booking.direct': 'Direct',
'assistant.card.booking.layoverAt': '{duration} in {place}',
'assistant.card.booking.arrivesLater': 'Arrives {count} days later',
'assistant.card.booking.arrivesLater.one': 'Arrives {count} day later',
'assistant.card.booking.reference': 'Reference saved',
'assistant.card.booking.referenceHint': 'The booking reference is kept with the booking, not in the chat',
'assistant.card.booking.seat': 'Seat {seat}',
'assistant.card.booking.platform': 'Platform {platform}',
'assistant.card.booking.checkInAt': 'Check-in {time}',
'assistant.card.booking.checkOutAt': 'Check-out {time}',
'assistant.card.booking.cancelled': 'Cancelled',
'assistant.card.booking.inTrip': 'In {trip}',
'assistant.card.booking.range': '{from} to {to}',
'assistant.change.verb.addStay': 'Add accommodation',
'assistant.change.verb.updateStay': 'Change the stay',
'assistant.change.verb.updateReservation': 'Change the booking',
'assistant.tool.set_reservation_travelers': 'Change who travels',
'assistant.tool.link_hotel_accommodation': 'Link the hotel to its nights',
'assistant.tool.update_transport': 'Change the transport',
'assistant.tool.delete_transport': 'Delete the transport',
'assistant.tool.delete_accommodation': 'Cancel the stay',
'assistant.tool.reorder_reservations': 'Reorder the bookings',
'assistant.tool.import_airtrail_flights': 'Import flights from AirTrail',
'assistant.step.bookings': 'Reading the bookings',
'assistant.step.stays': 'Reading where you stay',
'assistant.step.upcoming': 'Looking at upcoming bookings',
'assistant.followUp.bookingsOpen': 'Which bookings are still pending?',
'assistant.followUp.bookingsNights': 'Is every night covered by a stay?',
'assistant.followUp.bookingsConfirm': 'Confirm the pending bookings',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Reservas',
'assistant.card.booking.open': 'Abrir la reserva',
'assistant.card.booking.openStay': 'Mostrar en el plan',
'assistant.card.booking.more': '{count} reservas más',
'assistant.card.booking.more.one': '{count} reserva más',
'assistant.card.booking.nights': '{count} noches',
'assistant.card.booking.nights.one': '{count} noche',
'assistant.card.booking.stops': '{count} escalas',
'assistant.card.booking.stops.one': '{count} escala',
'assistant.card.booking.direct': 'Directo',
'assistant.card.booking.layoverAt': '{duration} en {place}',
'assistant.card.booking.arrivesLater': 'Llega {count} días después',
'assistant.card.booking.arrivesLater.one': 'Llega {count} día después',
'assistant.card.booking.reference': 'Referencia guardada',
'assistant.card.booking.referenceHint': 'La referencia se guarda con la reserva, no en el chat',
'assistant.card.booking.seat': 'Asiento {seat}',
'assistant.card.booking.platform': 'Andén {platform}',
'assistant.card.booking.checkInAt': 'Entrada {time}',
'assistant.card.booking.checkOutAt': 'Salida {time}',
'assistant.card.booking.cancelled': 'Cancelada',
'assistant.card.booking.inTrip': 'En {trip}',
'assistant.card.booking.range': 'del {from} al {to}',
'assistant.change.verb.addStay': 'Añadir alojamiento',
'assistant.change.verb.updateStay': 'Cambiar la estancia',
'assistant.change.verb.updateReservation': 'Cambiar la reserva',
'assistant.tool.set_reservation_travelers': 'Cambiar quién viaja',
'assistant.tool.link_hotel_accommodation': 'Vincular el hotel a sus noches',
'assistant.tool.update_transport': 'Cambiar el transporte',
'assistant.tool.delete_transport': 'Eliminar el transporte',
'assistant.tool.delete_accommodation': 'Cancelar la estancia',
'assistant.tool.reorder_reservations': 'Reordenar las reservas',
'assistant.tool.import_airtrail_flights': 'Importar vuelos de AirTrail',
'assistant.step.bookings': 'Leyendo las reservas',
'assistant.step.stays': 'Leyendo dónde te alojas',
'assistant.step.upcoming': 'Mirando las próximas reservas',
'assistant.followUp.bookingsOpen': '¿Qué reservas siguen pendientes?',
'assistant.followUp.bookingsNights': '¿Tiene cada noche un alojamiento?',
'assistant.followUp.bookingsConfirm': 'Confirmar las reservas pendientes',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Broneeringud',
'assistant.card.booking.open': 'Ava broneering',
'assistant.card.booking.openStay': 'Näita plaanis',
'assistant.card.booking.more': 'Veel {count} broneeringut',
'assistant.card.booking.more.one': 'Veel {count} broneering',
'assistant.card.booking.nights': '{count} ööd',
'assistant.card.booking.nights.one': '{count} öö',
'assistant.card.booking.stops': '{count} vahepeatust',
'assistant.card.booking.stops.one': '{count} vahepeatus',
'assistant.card.booking.direct': 'Otse',
'assistant.card.booking.layoverAt': '{duration} kohas {place}',
'assistant.card.booking.arrivesLater': 'Saabub {count} päeva hiljem',
'assistant.card.booking.arrivesLater.one': 'Saabub {count} päev hiljem',
'assistant.card.booking.reference': 'Broneeringukood salvestatud',
'assistant.card.booking.referenceHint': 'Broneeringukood jääb broneeringu juurde, mitte vestlusesse',
'assistant.card.booking.seat': 'Istekoht {seat}',
'assistant.card.booking.platform': 'Perroon {platform}',
'assistant.card.booking.checkInAt': 'Sisseregistreerimine {time}',
'assistant.card.booking.checkOutAt': 'Väljaregistreerimine {time}',
'assistant.card.booking.cancelled': 'Tühistatud',
'assistant.card.booking.inTrip': 'Reisil {trip}',
'assistant.card.booking.range': '{from} kuni {to}',
'assistant.change.verb.addStay': 'Lisa majutus',
'assistant.change.verb.updateStay': 'Muuda peatumist',
'assistant.change.verb.updateReservation': 'Muuda broneeringut',
'assistant.tool.set_reservation_travelers': 'Muuda, kes reisivad',
'assistant.tool.link_hotel_accommodation': 'Seo hotell selle öödega',
'assistant.tool.update_transport': 'Muuda transporti',
'assistant.tool.delete_transport': 'Kustuta transport',
'assistant.tool.delete_accommodation': 'Tühista peatumine',
'assistant.tool.reorder_reservations': 'Järjesta broneeringud ümber',
'assistant.tool.import_airtrail_flights': 'Impordi lennud AirTrailist',
'assistant.step.bookings': 'Loen broneeringuid',
'assistant.step.stays': 'Loen, kus sa ööbid',
'assistant.step.upcoming': 'Vaatan eelseisvaid broneeringuid',
'assistant.followUp.bookingsOpen': 'Millised broneeringud on veel ootel?',
'assistant.followUp.bookingsNights': 'Kas igaks ööks on majutus?',
'assistant.followUp.bookingsConfirm': 'Kinnita ootel broneeringud',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Réservations',
'assistant.card.booking.open': 'Ouvrir la réservation',
'assistant.card.booking.openStay': 'Afficher dans le plan',
'assistant.card.booking.more': '{count} autres réservations',
'assistant.card.booking.more.one': '{count} autre réservation',
'assistant.card.booking.nights': '{count} nuits',
'assistant.card.booking.nights.one': '{count} nuit',
'assistant.card.booking.stops': '{count} escales',
'assistant.card.booking.stops.one': '{count} escale',
'assistant.card.booking.direct': 'Sans escale',
'assistant.card.booking.layoverAt': '{duration} à {place}',
'assistant.card.booking.arrivesLater': 'Arrivée {count} jours plus tard',
'assistant.card.booking.arrivesLater.one': 'Arrivée {count} jour plus tard',
'assistant.card.booking.reference': 'Référence enregistrée',
'assistant.card.booking.referenceHint': 'La référence reste avec la réservation, pas dans la discussion',
'assistant.card.booking.seat': 'Siège {seat}',
'assistant.card.booking.platform': 'Voie {platform}',
'assistant.card.booking.checkInAt': 'Arrivée {time}',
'assistant.card.booking.checkOutAt': 'Départ {time}',
'assistant.card.booking.cancelled': 'Annulée',
'assistant.card.booking.inTrip': 'Dans {trip}',
'assistant.card.booking.range': 'du {from} au {to}',
'assistant.change.verb.addStay': 'Ajouter un hébergement',
'assistant.change.verb.updateStay': 'Modifier le séjour',
'assistant.change.verb.updateReservation': 'Modifier la réservation',
'assistant.tool.set_reservation_travelers': 'Modifier les voyageurs',
'assistant.tool.link_hotel_accommodation': "Relier l'hôtel à ses nuits",
'assistant.tool.update_transport': 'Modifier le transport',
'assistant.tool.delete_transport': 'Supprimer le transport',
'assistant.tool.delete_accommodation': 'Annuler le séjour',
'assistant.tool.reorder_reservations': 'Réordonner les réservations',
'assistant.tool.import_airtrail_flights': 'Importer des vols depuis AirTrail',
'assistant.step.bookings': 'Lecture des réservations',
'assistant.step.stays': 'Lecture des hébergements',
'assistant.step.upcoming': 'Coup d’œil aux prochaines réservations',
'assistant.followUp.bookingsOpen': 'Quelles réservations sont encore en attente ?',
'assistant.followUp.bookingsNights': 'Chaque nuit a-t-elle un hébergement ?',
'assistant.followUp.bookingsConfirm': 'Confirmer les réservations en attente',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Κρατήσεις',
'assistant.card.booking.open': 'Άνοιγμα κράτησης',
'assistant.card.booking.openStay': 'Εμφάνιση στο πλάνο',
'assistant.card.booking.more': 'Ακόμη {count} κρατήσεις',
'assistant.card.booking.more.one': 'Ακόμη {count} κράτηση',
'assistant.card.booking.nights': '{count} νύχτες',
'assistant.card.booking.nights.one': '{count} νύχτα',
'assistant.card.booking.stops': '{count} στάσεις',
'assistant.card.booking.stops.one': '{count} στάση',
'assistant.card.booking.direct': 'Απευθείας',
'assistant.card.booking.layoverAt': '{duration} σε {place}',
'assistant.card.booking.arrivesLater': 'Άφιξη {count} ημέρες αργότερα',
'assistant.card.booking.arrivesLater.one': 'Άφιξη {count} ημέρα αργότερα',
'assistant.card.booking.reference': 'Ο κωδικός κράτησης αποθηκεύτηκε',
'assistant.card.booking.referenceHint': 'Ο κωδικός μένει στην κράτηση, όχι στη συνομιλία',
'assistant.card.booking.seat': 'Θέση {seat}',
'assistant.card.booking.platform': 'Αποβάθρα {platform}',
'assistant.card.booking.checkInAt': 'Άφιξη {time}',
'assistant.card.booking.checkOutAt': 'Αναχώρηση {time}',
'assistant.card.booking.cancelled': 'Ακυρώθηκε',
'assistant.card.booking.inTrip': 'Στο ταξίδι {trip}',
'assistant.card.booking.range': '{from} έως {to}',
'assistant.change.verb.addStay': 'Προσθήκη διαμονής',
'assistant.change.verb.updateStay': 'Αλλαγή διαμονής',
'assistant.change.verb.updateReservation': 'Αλλαγή κράτησης',
'assistant.tool.set_reservation_travelers': 'Αλλαγή ταξιδιωτών',
'assistant.tool.link_hotel_accommodation': 'Σύνδεση του ξενοδοχείου με τις νύχτες του',
'assistant.tool.update_transport': 'Αλλαγή μεταφοράς',
'assistant.tool.delete_transport': 'Διαγραφή μεταφοράς',
'assistant.tool.delete_accommodation': 'Ακύρωση διαμονής',
'assistant.tool.reorder_reservations': 'Αναδιάταξη κρατήσεων',
'assistant.tool.import_airtrail_flights': 'Εισαγωγή πτήσεων από το AirTrail',
'assistant.step.bookings': 'Διαβάζω τις κρατήσεις',
'assistant.step.stays': 'Διαβάζω τα καταλύματά σας',
'assistant.step.upcoming': 'Κοιτάζω τις επόμενες κρατήσεις',
'assistant.followUp.bookingsOpen': 'Ποιες κρατήσεις εκκρεμούν ακόμη;',
'assistant.followUp.bookingsNights': 'Έχει κάθε νύχτα κατάλυμα;',
'assistant.followUp.bookingsConfirm': 'Επιβεβαίωση των εκκρεμών κρατήσεων',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Foglalások',
'assistant.card.booking.open': 'Foglalás megnyitása',
'assistant.card.booking.openStay': 'Megjelenítés a tervben',
'assistant.card.booking.more': 'Még {count} foglalás',
'assistant.card.booking.more.one': 'Még {count} foglalás',
'assistant.card.booking.nights': '{count} éjszaka',
'assistant.card.booking.nights.one': '{count} éjszaka',
'assistant.card.booking.stops': '{count} átszállás',
'assistant.card.booking.stops.one': '{count} átszállás',
'assistant.card.booking.direct': 'Közvetlen',
'assistant.card.booking.layoverAt': '{duration} itt: {place}',
'assistant.card.booking.arrivesLater': 'Érkezés {count} nappal később',
'assistant.card.booking.arrivesLater.one': 'Érkezés {count} nappal később',
'assistant.card.booking.reference': 'Foglalási kód elmentve',
'assistant.card.booking.referenceHint': 'A foglalási kód a foglalásnál marad, nem a csevegésben',
'assistant.card.booking.seat': 'Ülés {seat}',
'assistant.card.booking.platform': 'Vágány {platform}',
'assistant.card.booking.checkInAt': 'Bejelentkezés {time}',
'assistant.card.booking.checkOutAt': 'Kijelentkezés {time}',
'assistant.card.booking.cancelled': 'Lemondva',
'assistant.card.booking.inTrip': 'Utazás: {trip}',
'assistant.card.booking.range': '{from} és {to} között',
'assistant.change.verb.addStay': 'Szállás hozzáadása',
'assistant.change.verb.updateStay': 'Tartózkodás módosítása',
'assistant.change.verb.updateReservation': 'Foglalás módosítása',
'assistant.tool.set_reservation_travelers': 'Utasok módosítása',
'assistant.tool.link_hotel_accommodation': 'Szálloda összekapcsolása az éjszakáival',
'assistant.tool.update_transport': 'Közlekedés módosítása',
'assistant.tool.delete_transport': 'Közlekedés törlése',
'assistant.tool.delete_accommodation': 'Tartózkodás lemondása',
'assistant.tool.reorder_reservations': 'Foglalások átrendezése',
'assistant.tool.import_airtrail_flights': 'Járatok importálása az AirTrailből',
'assistant.step.bookings': 'A foglalások olvasása',
'assistant.step.stays': 'A szállások olvasása',
'assistant.step.upcoming': 'A közelgő foglalások áttekintése',
'assistant.followUp.bookingsOpen': 'Mely foglalások várnak még?',
'assistant.followUp.bookingsNights': 'Minden éjszakára van szállás?',
'assistant.followUp.bookingsConfirm': 'Függő foglalások megerősítése',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Pemesanan',
'assistant.card.booking.open': 'Buka pemesanan',
'assistant.card.booking.openStay': 'Tampilkan di rencana',
'assistant.card.booking.more': '{count} pemesanan lagi',
'assistant.card.booking.nights': '{count} malam',
'assistant.card.booking.stops': '{count} transit',
'assistant.card.booking.direct': 'Langsung',
'assistant.card.booking.layoverAt': '{duration} di {place}',
'assistant.card.booking.arrivesLater': 'Tiba {count} hari kemudian',
'assistant.card.booking.reference': 'Kode pemesanan tersimpan',
'assistant.card.booking.referenceHint': 'Kode pemesanan disimpan bersama pemesanan, bukan di obrolan',
'assistant.card.booking.seat': 'Kursi {seat}',
'assistant.card.booking.platform': 'Peron {platform}',
'assistant.card.booking.checkInAt': 'Masuk {time}',
'assistant.card.booking.checkOutAt': 'Keluar {time}',
'assistant.card.booking.cancelled': 'Dibatalkan',
'assistant.card.booking.inTrip': 'Di {trip}',
'assistant.card.booking.range': '{from} sampai {to}',
'assistant.change.verb.addStay': 'Tambah penginapan',
'assistant.change.verb.updateStay': 'Ubah masa menginap',
'assistant.change.verb.updateReservation': 'Ubah pemesanan',
'assistant.tool.set_reservation_travelers': 'Ubah siapa yang bepergian',
'assistant.tool.link_hotel_accommodation': 'Tautkan hotel ke malam-malamnya',
'assistant.tool.update_transport': 'Ubah transportasi',
'assistant.tool.delete_transport': 'Hapus transportasi',
'assistant.tool.delete_accommodation': 'Batalkan masa menginap',
'assistant.tool.reorder_reservations': 'Urutkan ulang pemesanan',
'assistant.tool.import_airtrail_flights': 'Impor penerbangan dari AirTrail',
'assistant.step.bookings': 'Membaca pemesanan',
'assistant.step.stays': 'Membaca tempat menginap',
'assistant.step.upcoming': 'Melihat pemesanan mendatang',
'assistant.followUp.bookingsOpen': 'Pemesanan mana yang masih tertunda?',
'assistant.followUp.bookingsNights': 'Apakah setiap malam ada penginapan?',
'assistant.followUp.bookingsConfirm': 'Konfirmasi pemesanan yang tertunda',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Prenotazioni',
'assistant.card.booking.open': 'Apri la prenotazione',
'assistant.card.booking.openStay': 'Mostra nel piano',
'assistant.card.booking.more': 'Altre {count} prenotazioni',
'assistant.card.booking.more.one': 'Altra {count} prenotazione',
'assistant.card.booking.nights': '{count} notti',
'assistant.card.booking.nights.one': '{count} notte',
'assistant.card.booking.stops': '{count} scali',
'assistant.card.booking.stops.one': '{count} scalo',
'assistant.card.booking.direct': 'Diretto',
'assistant.card.booking.layoverAt': '{duration} a {place}',
'assistant.card.booking.arrivesLater': 'Arriva {count} giorni dopo',
'assistant.card.booking.arrivesLater.one': 'Arriva {count} giorno dopo',
'assistant.card.booking.reference': 'Codice salvato',
'assistant.card.booking.referenceHint': 'Il codice di prenotazione resta nella prenotazione, non nella chat',
'assistant.card.booking.seat': 'Posto {seat}',
'assistant.card.booking.platform': 'Binario {platform}',
'assistant.card.booking.checkInAt': 'Arrivo {time}',
'assistant.card.booking.checkOutAt': 'Partenza {time}',
'assistant.card.booking.cancelled': 'Annullata',
'assistant.card.booking.inTrip': 'Nel viaggio {trip}',
'assistant.card.booking.range': 'dal {from} al {to}',
'assistant.change.verb.addStay': 'Aggiungi alloggio',
'assistant.change.verb.updateStay': 'Modifica il soggiorno',
'assistant.change.verb.updateReservation': 'Modifica la prenotazione',
'assistant.tool.set_reservation_travelers': 'Cambia chi viaggia',
'assistant.tool.link_hotel_accommodation': "Collega l'hotel alle sue notti",
'assistant.tool.update_transport': 'Modifica il trasporto',
'assistant.tool.delete_transport': 'Elimina il trasporto',
'assistant.tool.delete_accommodation': 'Annulla il soggiorno',
'assistant.tool.reorder_reservations': 'Riordina le prenotazioni',
'assistant.tool.import_airtrail_flights': 'Importa voli da AirTrail',
'assistant.step.bookings': 'Leggo le prenotazioni',
'assistant.step.stays': 'Leggo dove alloggi',
'assistant.step.upcoming': 'Guardo le prossime prenotazioni',
'assistant.followUp.bookingsOpen': 'Quali prenotazioni sono ancora in sospeso?',
'assistant.followUp.bookingsNights': 'Ogni notte ha un alloggio?',
'assistant.followUp.bookingsConfirm': 'Conferma le prenotazioni in sospeso',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': '予約',
'assistant.card.booking.open': '予約を開く',
'assistant.card.booking.openStay': 'プランで表示',
'assistant.card.booking.more': 'ほか {count} 件の予約',
'assistant.card.booking.nights': '{count} 泊',
'assistant.card.booking.stops': '乗り継ぎ {count} 回',
'assistant.card.booking.direct': '直行便',
'assistant.card.booking.layoverAt': '{place} で {duration}',
'assistant.card.booking.arrivesLater': '{count} 日後に到着',
'assistant.card.booking.reference': '予約番号を保存済み',
'assistant.card.booking.referenceHint': '予約番号はチャットではなく予約に保存されます',
'assistant.card.booking.seat': '座席 {seat}',
'assistant.card.booking.platform': '{platform} 番線',
'assistant.card.booking.checkInAt': 'チェックイン {time}',
'assistant.card.booking.checkOutAt': 'チェックアウト {time}',
'assistant.card.booking.cancelled': 'キャンセル済み',
'assistant.card.booking.inTrip': '{trip} の予約',
'assistant.card.booking.range': '{from} から {to}',
'assistant.change.verb.addStay': '宿泊を追加',
'assistant.change.verb.updateStay': '宿泊を変更',
'assistant.change.verb.updateReservation': '予約を変更',
'assistant.tool.set_reservation_travelers': '旅行者を変更',
'assistant.tool.link_hotel_accommodation': 'ホテルを宿泊日に紐付け',
'assistant.tool.update_transport': '移動手段を変更',
'assistant.tool.delete_transport': '移動手段を削除',
'assistant.tool.delete_accommodation': '宿泊をキャンセル',
'assistant.tool.reorder_reservations': '予約を並べ替え',
'assistant.tool.import_airtrail_flights': 'AirTrail からフライトを取り込む',
'assistant.step.bookings': '予約一覧を読み込み中',
'assistant.step.stays': '宿泊先を読み込み中',
'assistant.step.upcoming': '今後の予約を確認中',
'assistant.followUp.bookingsOpen': 'まだ保留中の予約は?',
'assistant.followUp.bookingsNights': '毎晩の宿泊先はありますか?',
'assistant.followUp.bookingsConfirm': '保留中の予約を確定する',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': '예약',
'assistant.card.booking.open': '예약 열기',
'assistant.card.booking.openStay': '일정에서 보기',
'assistant.card.booking.more': '예약 {count}개 더',
'assistant.card.booking.nights': '{count}박',
'assistant.card.booking.stops': '경유 {count}회',
'assistant.card.booking.direct': '직항',
'assistant.card.booking.layoverAt': '{place}에서 {duration}',
'assistant.card.booking.arrivesLater': '{count}일 후 도착',
'assistant.card.booking.reference': '예약 번호 저장됨',
'assistant.card.booking.referenceHint': '예약 번호는 채팅이 아니라 예약에 보관됩니다',
'assistant.card.booking.seat': '좌석 {seat}',
'assistant.card.booking.platform': '{platform}번 승강장',
'assistant.card.booking.checkInAt': '체크인 {time}',
'assistant.card.booking.checkOutAt': '체크아웃 {time}',
'assistant.card.booking.cancelled': '취소됨',
'assistant.card.booking.inTrip': '{trip} 여행',
'assistant.card.booking.range': '{from}부터 {to}까지',
'assistant.change.verb.addStay': '숙소 추가',
'assistant.change.verb.updateStay': '숙박 변경',
'assistant.change.verb.updateReservation': '예약 변경',
'assistant.tool.set_reservation_travelers': '여행자 변경',
'assistant.tool.link_hotel_accommodation': '호텔을 숙박일에 연결',
'assistant.tool.update_transport': '교통편 변경',
'assistant.tool.delete_transport': '교통편 삭제',
'assistant.tool.delete_accommodation': '숙박 취소',
'assistant.tool.reorder_reservations': '예약 순서 변경',
'assistant.tool.import_airtrail_flights': 'AirTrail에서 항공편 가져오기',
'assistant.step.bookings': '예약 목록을 읽는 중',
'assistant.step.stays': '숙소를 읽는 중',
'assistant.step.upcoming': '다가오는 예약을 확인하는 중',
'assistant.followUp.bookingsOpen': '아직 대기 중인 예약은?',
'assistant.followUp.bookingsNights': '모든 밤에 숙소가 있나요?',
'assistant.followUp.bookingsConfirm': '대기 중인 예약 확정',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Boekingen',
'assistant.card.booking.open': 'Boeking openen',
'assistant.card.booking.openStay': 'Tonen in het plan',
'assistant.card.booking.more': 'Nog {count} boekingen',
'assistant.card.booking.more.one': 'Nog {count} boeking',
'assistant.card.booking.nights': '{count} nachten',
'assistant.card.booking.nights.one': '{count} nacht',
'assistant.card.booking.stops': '{count} tussenstops',
'assistant.card.booking.stops.one': '{count} tussenstop',
'assistant.card.booking.direct': 'Rechtstreeks',
'assistant.card.booking.layoverAt': '{duration} overstap in {place}',
'assistant.card.booking.arrivesLater': 'Aankomst {count} dagen later',
'assistant.card.booking.arrivesLater.one': 'Aankomst {count} dag later',
'assistant.card.booking.reference': 'Boekingscode bewaard',
'assistant.card.booking.referenceHint': 'De boekingscode blijft bij de boeking, niet in de chat',
'assistant.card.booking.seat': 'Stoel {seat}',
'assistant.card.booking.platform': 'Spoor {platform}',
'assistant.card.booking.checkInAt': 'Inchecken {time}',
'assistant.card.booking.checkOutAt': 'Uitchecken {time}',
'assistant.card.booking.cancelled': 'Geannuleerd',
'assistant.card.booking.inTrip': 'Bij {trip}',
'assistant.card.booking.range': '{from} tot {to}',
'assistant.change.verb.addStay': 'Accommodatie toevoegen',
'assistant.change.verb.updateStay': 'Verblijf wijzigen',
'assistant.change.verb.updateReservation': 'Boeking wijzigen',
'assistant.tool.set_reservation_travelers': 'Wijzigen wie meereist',
'assistant.tool.link_hotel_accommodation': 'Hotel aan zijn nachten koppelen',
'assistant.tool.update_transport': 'Vervoer wijzigen',
'assistant.tool.delete_transport': 'Vervoer verwijderen',
'assistant.tool.delete_accommodation': 'Verblijf annuleren',
'assistant.tool.reorder_reservations': 'Boekingen herschikken',
'assistant.tool.import_airtrail_flights': 'Vluchten uit AirTrail importeren',
'assistant.step.bookings': 'Boekingen lezen',
'assistant.step.stays': 'Lezen waar je verblijft',
'assistant.step.upcoming': 'Komende boekingen bekijken',
'assistant.followUp.bookingsOpen': 'Welke boekingen staan nog open?',
'assistant.followUp.bookingsNights': 'Heeft elke nacht een verblijf?',
'assistant.followUp.bookingsConfirm': 'Openstaande boekingen bevestigen',
};
export default assistantBooking;
+48 -1
View File
@@ -1,4 +1,51 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Rezerwacje',
'assistant.card.booking.open': 'Otwórz rezerwację',
'assistant.card.booking.openStay': 'Pokaż w planie',
'assistant.card.booking.more': 'Jeszcze {count} rezerwacji',
'assistant.card.booking.more.one': 'Jeszcze {count} rezerwacja',
'assistant.card.booking.more.few': 'Jeszcze {count} rezerwacje',
'assistant.card.booking.more.many': 'Jeszcze {count} rezerwacji',
'assistant.card.booking.nights': '{count} nocy',
'assistant.card.booking.nights.one': '{count} noc',
'assistant.card.booking.nights.few': '{count} noce',
'assistant.card.booking.nights.many': '{count} nocy',
'assistant.card.booking.stops': '{count} przesiadki',
'assistant.card.booking.stops.one': '{count} przesiadka',
'assistant.card.booking.stops.few': '{count} przesiadki',
'assistant.card.booking.stops.many': '{count} przesiadek',
'assistant.card.booking.direct': 'Bezpośredni',
'assistant.card.booking.layoverAt': '{duration} w {place}',
'assistant.card.booking.arrivesLater': 'Przylot {count} dnia później',
'assistant.card.booking.arrivesLater.one': 'Przylot {count} dzień później',
'assistant.card.booking.arrivesLater.few': 'Przylot {count} dni później',
'assistant.card.booking.arrivesLater.many': 'Przylot {count} dni później',
'assistant.card.booking.reference': 'Kod rezerwacji zapisany',
'assistant.card.booking.referenceHint': 'Kod rezerwacji zostaje przy rezerwacji, nie w czacie',
'assistant.card.booking.seat': 'Miejsce {seat}',
'assistant.card.booking.platform': 'Peron {platform}',
'assistant.card.booking.checkInAt': 'Zameldowanie {time}',
'assistant.card.booking.checkOutAt': 'Wymeldowanie {time}',
'assistant.card.booking.cancelled': 'Anulowana',
'assistant.card.booking.inTrip': 'W podróży {trip}',
'assistant.card.booking.range': 'od {from} do {to}',
'assistant.change.verb.addStay': 'Dodaj nocleg',
'assistant.change.verb.updateStay': 'Zmień pobyt',
'assistant.change.verb.updateReservation': 'Zmień rezerwację',
'assistant.tool.set_reservation_travelers': 'Zmień, kto podróżuje',
'assistant.tool.link_hotel_accommodation': 'Powiąż hotel z jego nocami',
'assistant.tool.update_transport': 'Zmień transport',
'assistant.tool.delete_transport': 'Usuń transport',
'assistant.tool.delete_accommodation': 'Anuluj pobyt',
'assistant.tool.reorder_reservations': 'Zmień kolejność rezerwacji',
'assistant.tool.import_airtrail_flights': 'Importuj loty z AirTrail',
'assistant.step.bookings': 'Czytam rezerwacje',
'assistant.step.stays': 'Czytam, gdzie nocujesz',
'assistant.step.upcoming': 'Sprawdzam nadchodzące rezerwacje',
'assistant.followUp.bookingsOpen': 'Które rezerwacje wciąż czekają?',
'assistant.followUp.bookingsNights': 'Czy każda noc ma nocleg?',
'assistant.followUp.bookingsConfirm': 'Potwierdź oczekujące rezerwacje',
};
export default assistantBooking;
+48 -1
View File
@@ -1,4 +1,51 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Бронирования',
'assistant.card.booking.open': 'Открыть бронирование',
'assistant.card.booking.openStay': 'Показать в плане',
'assistant.card.booking.more': 'Ещё {count} бронирования',
'assistant.card.booking.more.one': 'Ещё {count} бронирование',
'assistant.card.booking.more.few': 'Ещё {count} бронирования',
'assistant.card.booking.more.many': 'Ещё {count} бронирований',
'assistant.card.booking.nights': '{count} ночи',
'assistant.card.booking.nights.one': '{count} ночь',
'assistant.card.booking.nights.few': '{count} ночи',
'assistant.card.booking.nights.many': '{count} ночей',
'assistant.card.booking.stops': '{count} пересадки',
'assistant.card.booking.stops.one': '{count} пересадка',
'assistant.card.booking.stops.few': '{count} пересадки',
'assistant.card.booking.stops.many': '{count} пересадок',
'assistant.card.booking.direct': 'Без пересадок',
'assistant.card.booking.layoverAt': '{duration} в {place}',
'assistant.card.booking.arrivesLater': 'Прибытие через {count} дня',
'assistant.card.booking.arrivesLater.one': 'Прибытие через {count} день',
'assistant.card.booking.arrivesLater.few': 'Прибытие через {count} дня',
'assistant.card.booking.arrivesLater.many': 'Прибытие через {count} дней',
'assistant.card.booking.reference': 'Номер брони сохранён',
'assistant.card.booking.referenceHint': 'Номер брони хранится в бронировании, а не в чате',
'assistant.card.booking.seat': 'Место {seat}',
'assistant.card.booking.platform': 'Платформа {platform}',
'assistant.card.booking.checkInAt': 'Заезд {time}',
'assistant.card.booking.checkOutAt': 'Выезд {time}',
'assistant.card.booking.cancelled': 'Отменено',
'assistant.card.booking.inTrip': 'В поездке {trip}',
'assistant.card.booking.range': 'с {from} по {to}',
'assistant.change.verb.addStay': 'Добавить жильё',
'assistant.change.verb.updateStay': 'Изменить проживание',
'assistant.change.verb.updateReservation': 'Изменить бронирование',
'assistant.tool.set_reservation_travelers': 'Изменить, кто едет',
'assistant.tool.link_hotel_accommodation': 'Привязать отель к его ночам',
'assistant.tool.update_transport': 'Изменить транспорт',
'assistant.tool.delete_transport': 'Удалить транспорт',
'assistant.tool.delete_accommodation': 'Отменить проживание',
'assistant.tool.reorder_reservations': 'Изменить порядок бронирований',
'assistant.tool.import_airtrail_flights': 'Импортировать рейсы из AirTrail',
'assistant.step.bookings': 'Читаю бронирования',
'assistant.step.stays': 'Читаю, где вы живёте',
'assistant.step.upcoming': 'Смотрю ближайшие бронирования',
'assistant.followUp.bookingsOpen': 'Какие бронирования ещё ждут подтверждения?',
'assistant.followUp.bookingsNights': 'На каждую ли ночь есть жильё?',
'assistant.followUp.bookingsConfirm': 'Подтвердить ожидающие бронирования',
};
export default assistantBooking;
+44 -1
View File
@@ -1,4 +1,47 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Rezervácie',
'assistant.card.booking.open': 'Otvoriť rezerváciu',
'assistant.card.booking.openStay': 'Zobraziť v pláne',
'assistant.card.booking.more': 'Ďalších {count} rezervácií',
'assistant.card.booking.more.one': 'Ešte {count} rezervácia',
'assistant.card.booking.more.few': 'Ďalšie {count} rezervácie',
'assistant.card.booking.nights': '{count} nocí',
'assistant.card.booking.nights.one': '{count} noc',
'assistant.card.booking.nights.few': '{count} noci',
'assistant.card.booking.stops': '{count} prestupov',
'assistant.card.booking.stops.one': '{count} prestup',
'assistant.card.booking.stops.few': '{count} prestupy',
'assistant.card.booking.direct': 'Priamy spoj',
'assistant.card.booking.layoverAt': '{duration} v {place}',
'assistant.card.booking.arrivesLater': 'Prílet o {count} dní neskôr',
'assistant.card.booking.arrivesLater.one': 'Prílet o {count} deň neskôr',
'assistant.card.booking.arrivesLater.few': 'Prílet o {count} dni neskôr',
'assistant.card.booking.reference': 'Kód rezervácie uložený',
'assistant.card.booking.referenceHint': 'Kód rezervácie zostáva pri rezervácii, nie v chate',
'assistant.card.booking.seat': 'Sedadlo {seat}',
'assistant.card.booking.platform': 'Nástupište {platform}',
'assistant.card.booking.checkInAt': 'Príchod {time}',
'assistant.card.booking.checkOutAt': 'Odchod {time}',
'assistant.card.booking.cancelled': 'Zrušené',
'assistant.card.booking.inTrip': 'V ceste {trip}',
'assistant.card.booking.range': '{from} až {to}',
'assistant.change.verb.addStay': 'Pridať ubytovanie',
'assistant.change.verb.updateStay': 'Zmeniť pobyt',
'assistant.change.verb.updateReservation': 'Zmeniť rezerváciu',
'assistant.tool.set_reservation_travelers': 'Zmeniť, kto cestuje',
'assistant.tool.link_hotel_accommodation': 'Prepojiť hotel s jeho nocami',
'assistant.tool.update_transport': 'Zmeniť dopravu',
'assistant.tool.delete_transport': 'Zmazať dopravu',
'assistant.tool.delete_accommodation': 'Zrušiť pobyt',
'assistant.tool.reorder_reservations': 'Preradiť rezervácie',
'assistant.tool.import_airtrail_flights': 'Importovať lety z AirTrail',
'assistant.step.bookings': 'Čítam rezervácie',
'assistant.step.stays': 'Čítam, kde bývaš',
'assistant.step.upcoming': 'Pozerám nadchádzajúce rezervácie',
'assistant.followUp.bookingsOpen': 'Ktoré rezervácie ešte čakajú?',
'assistant.followUp.bookingsNights': 'Má každá noc ubytovanie?',
'assistant.followUp.bookingsConfirm': 'Potvrdiť čakajúce rezervácie',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Bokningar',
'assistant.card.booking.open': 'Öppna bokningen',
'assistant.card.booking.openStay': 'Visa i planen',
'assistant.card.booking.more': '{count} bokningar till',
'assistant.card.booking.more.one': '{count} bokning till',
'assistant.card.booking.nights': '{count} nätter',
'assistant.card.booking.nights.one': '{count} natt',
'assistant.card.booking.stops': '{count} mellanlandningar',
'assistant.card.booking.stops.one': '{count} mellanlandning',
'assistant.card.booking.direct': 'Direktresa',
'assistant.card.booking.layoverAt': '{duration} i {place}',
'assistant.card.booking.arrivesLater': 'Ankommer {count} dagar senare',
'assistant.card.booking.arrivesLater.one': 'Ankommer {count} dag senare',
'assistant.card.booking.reference': 'Bokningsnummer sparat',
'assistant.card.booking.referenceHint': 'Bokningsnumret stannar i bokningen, inte i chatten',
'assistant.card.booking.seat': 'Plats {seat}',
'assistant.card.booking.platform': 'Spår {platform}',
'assistant.card.booking.checkInAt': 'Incheckning {time}',
'assistant.card.booking.checkOutAt': 'Utcheckning {time}',
'assistant.card.booking.cancelled': 'Avbokad',
'assistant.card.booking.inTrip': 'I {trip}',
'assistant.card.booking.range': '{from} till {to}',
'assistant.change.verb.addStay': 'Lägg till boende',
'assistant.change.verb.updateStay': 'Ändra vistelsen',
'assistant.change.verb.updateReservation': 'Ändra bokningen',
'assistant.tool.set_reservation_travelers': 'Ändra vilka som reser',
'assistant.tool.link_hotel_accommodation': 'Koppla hotellet till dess nätter',
'assistant.tool.update_transport': 'Ändra transporten',
'assistant.tool.delete_transport': 'Ta bort transporten',
'assistant.tool.delete_accommodation': 'Avboka vistelsen',
'assistant.tool.reorder_reservations': 'Ordna om bokningarna',
'assistant.tool.import_airtrail_flights': 'Importera flyg från AirTrail',
'assistant.step.bookings': 'Läser bokningarna',
'assistant.step.stays': 'Läser var du bor',
'assistant.step.upcoming': 'Tittar på kommande bokningar',
'assistant.followUp.bookingsOpen': 'Vilka bokningar väntar fortfarande?',
'assistant.followUp.bookingsNights': 'Har varje natt ett boende?',
'assistant.followUp.bookingsConfirm': 'Bekräfta de väntande bokningarna',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'การจอง',
'assistant.card.booking.open': 'เปิดการจอง',
'assistant.card.booking.openStay': 'แสดงในแผน',
'assistant.card.booking.more': 'การจองอีก {count} รายการ',
'assistant.card.booking.nights': '{count} คืน',
'assistant.card.booking.stops': 'ต่อเครื่อง {count} ครั้ง',
'assistant.card.booking.direct': 'บินตรง',
'assistant.card.booking.layoverAt': '{duration} ที่ {place}',
'assistant.card.booking.arrivesLater': 'ถึง {count} วันถัดไป',
'assistant.card.booking.reference': 'บันทึกรหัสการจองแล้ว',
'assistant.card.booking.referenceHint': 'รหัสการจองเก็บไว้กับการจอง ไม่ใช่ในแชท',
'assistant.card.booking.seat': 'ที่นั่ง {seat}',
'assistant.card.booking.platform': 'ชานชาลา {platform}',
'assistant.card.booking.checkInAt': 'เช็กอิน {time}',
'assistant.card.booking.checkOutAt': 'เช็กเอาต์ {time}',
'assistant.card.booking.cancelled': 'ยกเลิกแล้ว',
'assistant.card.booking.inTrip': 'ในทริป {trip}',
'assistant.card.booking.range': '{from} ถึง {to}',
'assistant.change.verb.addStay': 'เพิ่มที่พัก',
'assistant.change.verb.updateStay': 'เปลี่ยนการเข้าพัก',
'assistant.change.verb.updateReservation': 'เปลี่ยนการจอง',
'assistant.tool.set_reservation_travelers': 'เปลี่ยนผู้เดินทาง',
'assistant.tool.link_hotel_accommodation': 'เชื่อมโรงแรมกับคืนที่พัก',
'assistant.tool.update_transport': 'เปลี่ยนการเดินทาง',
'assistant.tool.delete_transport': 'ลบการเดินทาง',
'assistant.tool.delete_accommodation': 'ยกเลิกการเข้าพัก',
'assistant.tool.reorder_reservations': 'จัดลำดับการจองใหม่',
'assistant.tool.import_airtrail_flights': 'นำเข้าเที่ยวบินจาก AirTrail',
'assistant.step.bookings': 'กำลังอ่านการจอง',
'assistant.step.stays': 'กำลังอ่านที่พัก',
'assistant.step.upcoming': 'กำลังดูการจองที่จะมาถึง',
'assistant.followUp.bookingsOpen': 'การจองไหนยังรอยืนยันอยู่?',
'assistant.followUp.bookingsNights': 'ทุกคืนมีที่พักหรือยัง?',
'assistant.followUp.bookingsConfirm': 'ยืนยันการจองที่รออยู่',
};
export default assistantBooking;
+40 -1
View File
@@ -1,4 +1,43 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Rezervasyonlar',
'assistant.card.booking.open': 'Rezervasyonu aç',
'assistant.card.booking.openStay': 'Planda göster',
'assistant.card.booking.more': '{count} rezervasyon daha',
'assistant.card.booking.more.one': '{count} rezervasyon daha',
'assistant.card.booking.nights': '{count} gece',
'assistant.card.booking.nights.one': '{count} gece',
'assistant.card.booking.stops': '{count} aktarma',
'assistant.card.booking.stops.one': '{count} aktarma',
'assistant.card.booking.direct': 'Aktarmasız',
'assistant.card.booking.layoverAt': '{place} içinde {duration}',
'assistant.card.booking.arrivesLater': '{count} gün sonra varış',
'assistant.card.booking.arrivesLater.one': '{count} gün sonra varış',
'assistant.card.booking.reference': 'Rezervasyon kodu kaydedildi',
'assistant.card.booking.referenceHint': 'Rezervasyon kodu sohbette değil, rezervasyonda saklanır',
'assistant.card.booking.seat': 'Koltuk {seat}',
'assistant.card.booking.platform': 'Peron {platform}',
'assistant.card.booking.checkInAt': 'Giriş {time}',
'assistant.card.booking.checkOutAt': 'Çıkış {time}',
'assistant.card.booking.cancelled': 'İptal edildi',
'assistant.card.booking.inTrip': '{trip} içinde',
'assistant.card.booking.range': '{from} ile {to} arası',
'assistant.change.verb.addStay': 'Konaklama ekle',
'assistant.change.verb.updateStay': 'Konaklamayı değiştir',
'assistant.change.verb.updateReservation': 'Rezervasyonu değiştir',
'assistant.tool.set_reservation_travelers': 'Kimlerin seyahat ettiğini değiştir',
'assistant.tool.link_hotel_accommodation': 'Oteli gecelerine bağla',
'assistant.tool.update_transport': 'Ulaşımı değiştir',
'assistant.tool.delete_transport': 'Ulaşımı sil',
'assistant.tool.delete_accommodation': 'Konaklamayı iptal et',
'assistant.tool.reorder_reservations': 'Rezervasyonları yeniden sırala',
'assistant.tool.import_airtrail_flights': "AirTrail'den uçuşları içe aktar",
'assistant.step.bookings': 'Rezervasyonlar okunuyor',
'assistant.step.stays': 'Konaklamalar okunuyor',
'assistant.step.upcoming': 'Yaklaşan rezervasyonlara bakılıyor',
'assistant.followUp.bookingsOpen': 'Hangi rezervasyonlar hâlâ bekliyor?',
'assistant.followUp.bookingsNights': 'Her gece için konaklama var mı?',
'assistant.followUp.bookingsConfirm': 'Bekleyen rezervasyonları onayla',
};
export default assistantBooking;
+48 -1
View File
@@ -1,4 +1,51 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Бронювання',
'assistant.card.booking.open': 'Відкрити бронювання',
'assistant.card.booking.openStay': 'Показати в плані',
'assistant.card.booking.more': 'Ще {count} бронювання',
'assistant.card.booking.more.one': 'Ще {count} бронювання',
'assistant.card.booking.more.few': 'Ще {count} бронювання',
'assistant.card.booking.more.many': 'Ще {count} бронювань',
'assistant.card.booking.nights': '{count} ночі',
'assistant.card.booking.nights.one': '{count} ніч',
'assistant.card.booking.nights.few': '{count} ночі',
'assistant.card.booking.nights.many': '{count} ночей',
'assistant.card.booking.stops': '{count} пересадки',
'assistant.card.booking.stops.one': '{count} пересадка',
'assistant.card.booking.stops.few': '{count} пересадки',
'assistant.card.booking.stops.many': '{count} пересадок',
'assistant.card.booking.direct': 'Без пересадок',
'assistant.card.booking.layoverAt': '{duration} у {place}',
'assistant.card.booking.arrivesLater': 'Прибуття через {count} дня',
'assistant.card.booking.arrivesLater.one': 'Прибуття через {count} день',
'assistant.card.booking.arrivesLater.few': 'Прибуття через {count} дні',
'assistant.card.booking.arrivesLater.many': 'Прибуття через {count} днів',
'assistant.card.booking.reference': 'Номер бронювання збережено',
'assistant.card.booking.referenceHint': 'Номер бронювання зберігається в бронюванні, а не в чаті',
'assistant.card.booking.seat': 'Місце {seat}',
'assistant.card.booking.platform': 'Платформа {platform}',
'assistant.card.booking.checkInAt': 'Заїзд {time}',
'assistant.card.booking.checkOutAt': 'Виїзд {time}',
'assistant.card.booking.cancelled': 'Скасовано',
'assistant.card.booking.inTrip': 'У поїздці {trip}',
'assistant.card.booking.range': 'з {from} по {to}',
'assistant.change.verb.addStay': 'Додати житло',
'assistant.change.verb.updateStay': 'Змінити проживання',
'assistant.change.verb.updateReservation': 'Змінити бронювання',
'assistant.tool.set_reservation_travelers': 'Змінити, хто їде',
'assistant.tool.link_hotel_accommodation': "Прив'язати готель до його ночей",
'assistant.tool.update_transport': 'Змінити транспорт',
'assistant.tool.delete_transport': 'Видалити транспорт',
'assistant.tool.delete_accommodation': 'Скасувати проживання',
'assistant.tool.reorder_reservations': 'Змінити порядок бронювань',
'assistant.tool.import_airtrail_flights': 'Імпортувати рейси з AirTrail',
'assistant.step.bookings': 'Читаю бронювання',
'assistant.step.stays': 'Читаю, де ви живете',
'assistant.step.upcoming': 'Дивлюся найближчі бронювання',
'assistant.followUp.bookingsOpen': 'Які бронювання ще чекають?',
'assistant.followUp.bookingsNights': 'Чи є житло на кожну ніч?',
'assistant.followUp.bookingsConfirm': 'Підтвердити бронювання, що очікують',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': 'Đặt chỗ',
'assistant.card.booking.open': 'Mở đặt chỗ',
'assistant.card.booking.openStay': 'Hiển thị trong kế hoạch',
'assistant.card.booking.more': 'Còn {count} đặt chỗ',
'assistant.card.booking.nights': '{count} đêm',
'assistant.card.booking.stops': '{count} điểm dừng',
'assistant.card.booking.direct': 'Bay thẳng',
'assistant.card.booking.layoverAt': '{duration} tại {place}',
'assistant.card.booking.arrivesLater': 'Đến nơi sau {count} ngày',
'assistant.card.booking.reference': 'Đã lưu mã đặt chỗ',
'assistant.card.booking.referenceHint': 'Mã đặt chỗ được giữ trong đặt chỗ, không trong cuộc trò chuyện',
'assistant.card.booking.seat': 'Ghế {seat}',
'assistant.card.booking.platform': 'Sân ga {platform}',
'assistant.card.booking.checkInAt': 'Nhận phòng {time}',
'assistant.card.booking.checkOutAt': 'Trả phòng {time}',
'assistant.card.booking.cancelled': 'Đã hủy',
'assistant.card.booking.inTrip': 'Trong {trip}',
'assistant.card.booking.range': 'từ {from} đến {to}',
'assistant.change.verb.addStay': 'Thêm chỗ ở',
'assistant.change.verb.updateStay': 'Thay đổi kỳ lưu trú',
'assistant.change.verb.updateReservation': 'Thay đổi đặt chỗ',
'assistant.tool.set_reservation_travelers': 'Thay đổi người đi',
'assistant.tool.link_hotel_accommodation': 'Liên kết khách sạn với các đêm',
'assistant.tool.update_transport': 'Thay đổi phương tiện',
'assistant.tool.delete_transport': 'Xóa phương tiện',
'assistant.tool.delete_accommodation': 'Hủy kỳ lưu trú',
'assistant.tool.reorder_reservations': 'Sắp xếp lại đặt chỗ',
'assistant.tool.import_airtrail_flights': 'Nhập chuyến bay từ AirTrail',
'assistant.step.bookings': 'Đang đọc các đặt chỗ',
'assistant.step.stays': 'Đang đọc nơi bạn ở',
'assistant.step.upcoming': 'Đang xem các đặt chỗ sắp tới',
'assistant.followUp.bookingsOpen': 'Đặt chỗ nào vẫn đang chờ?',
'assistant.followUp.bookingsNights': 'Đêm nào cũng có chỗ ở chưa?',
'assistant.followUp.bookingsConfirm': 'Xác nhận các đặt chỗ đang chờ',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': '預訂',
'assistant.card.booking.open': '開啟預訂',
'assistant.card.booking.openStay': '在計畫中顯示',
'assistant.card.booking.more': '還有 {count} 項預訂',
'assistant.card.booking.nights': '{count} 晚',
'assistant.card.booking.stops': '轉機 {count} 次',
'assistant.card.booking.direct': '直飛',
'assistant.card.booking.layoverAt': '在{place}停留 {duration}',
'assistant.card.booking.arrivesLater': '{count} 天後抵達',
'assistant.card.booking.reference': '已儲存預訂代號',
'assistant.card.booking.referenceHint': '預訂代號保存在預訂中,而不是聊天裡',
'assistant.card.booking.seat': '座位 {seat}',
'assistant.card.booking.platform': '{platform} 月台',
'assistant.card.booking.checkInAt': '入住 {time}',
'assistant.card.booking.checkOutAt': '退房 {time}',
'assistant.card.booking.cancelled': '已取消',
'assistant.card.booking.inTrip': '屬於 {trip}',
'assistant.card.booking.range': '{from} 至 {to}',
'assistant.change.verb.addStay': '新增住宿',
'assistant.change.verb.updateStay': '變更住宿',
'assistant.change.verb.updateReservation': '變更預訂',
'assistant.tool.set_reservation_travelers': '變更旅客',
'assistant.tool.link_hotel_accommodation': '將飯店連結到住宿日期',
'assistant.tool.update_transport': '變更交通',
'assistant.tool.delete_transport': '刪除交通',
'assistant.tool.delete_accommodation': '取消住宿',
'assistant.tool.reorder_reservations': '重新排列預訂',
'assistant.tool.import_airtrail_flights': '從 AirTrail 匯入航班',
'assistant.step.bookings': '正在讀取預訂',
'assistant.step.stays': '正在讀取住宿',
'assistant.step.upcoming': '正在查看即將到來的預訂',
'assistant.followUp.bookingsOpen': '哪些預訂仍待確認?',
'assistant.followUp.bookingsNights': '每晚都有住處嗎?',
'assistant.followUp.bookingsConfirm': '確認待定的預訂',
};
export default assistantBooking;
+36 -1
View File
@@ -1,4 +1,39 @@
import type { TranslationStrings } from '../types';
const assistantBooking: TranslationStrings = {};
const assistantBooking: TranslationStrings = {
'assistant.card.booking.list': '预订',
'assistant.card.booking.open': '打开预订',
'assistant.card.booking.openStay': '在计划中显示',
'assistant.card.booking.more': '还有 {count} 项预订',
'assistant.card.booking.nights': '{count} 晚',
'assistant.card.booking.stops': '经停 {count} 次',
'assistant.card.booking.direct': '直达',
'assistant.card.booking.layoverAt': '在{place}停留 {duration}',
'assistant.card.booking.arrivesLater': '{count} 天后到达',
'assistant.card.booking.reference': '已保存预订号',
'assistant.card.booking.referenceHint': '预订号保存在预订中,而不是聊天里',
'assistant.card.booking.seat': '座位 {seat}',
'assistant.card.booking.platform': '{platform} 站台',
'assistant.card.booking.checkInAt': '入住 {time}',
'assistant.card.booking.checkOutAt': '退房 {time}',
'assistant.card.booking.cancelled': '已取消',
'assistant.card.booking.inTrip': '属于 {trip}',
'assistant.card.booking.range': '{from} 至 {to}',
'assistant.change.verb.addStay': '添加住宿',
'assistant.change.verb.updateStay': '更改住宿',
'assistant.change.verb.updateReservation': '更改预订',
'assistant.tool.set_reservation_travelers': '更改出行人',
'assistant.tool.link_hotel_accommodation': '将酒店关联到住宿日期',
'assistant.tool.update_transport': '更改交通',
'assistant.tool.delete_transport': '删除交通',
'assistant.tool.delete_accommodation': '取消住宿',
'assistant.tool.reorder_reservations': '重新排列预订',
'assistant.tool.import_airtrail_flights': '从 AirTrail 导入航班',
'assistant.step.bookings': '正在读取预订',
'assistant.step.stays': '正在读取住宿',
'assistant.step.upcoming': '正在查看即将到来的预订',
'assistant.followUp.bookingsOpen': '哪些预订还在待确认?',
'assistant.followUp.bookingsNights': '每晚都有住处吗?',
'assistant.followUp.bookingsConfirm': '确认待定的预订',
};
export default assistantBooking;
@@ -0,0 +1,25 @@
import { listAccommodationsRequestSchema, listReservationsRequestSchema } from './reservation-read.schema';
import { describe, expect, it } from 'vitest';
describe('listReservationsRequestSchema', () => {
it('RESREAD-001: takes a trip alone, a kind filter and a day', () => {
expect(listReservationsRequestSchema.safeParse({ tripId: 3 }).success).toBe(true);
expect(listReservationsRequestSchema.safeParse({ tripId: 3, kinds: ['transport'], dayId: 9 }).success).toBe(true);
expect(listReservationsRequestSchema.safeParse({ tripId: 3, kinds: ['booking', 'transport'] }).success).toBe(true);
});
it('RESREAD-002: refuses an unknown kind, an empty kind list, a bad id and a missing trip', () => {
expect(listReservationsRequestSchema.safeParse({ tripId: 3, kinds: ['hotel'] }).success).toBe(false);
expect(listReservationsRequestSchema.safeParse({ tripId: 3, kinds: [] }).success).toBe(false);
expect(listReservationsRequestSchema.safeParse({ tripId: 3, dayId: 0 }).success).toBe(false);
expect(listReservationsRequestSchema.safeParse({ kinds: ['booking'] }).success).toBe(false);
});
});
describe('listAccommodationsRequestSchema', () => {
it('RESREAD-003: takes the trip and nothing else is required', () => {
expect(listAccommodationsRequestSchema.safeParse({ tripId: 3 }).success).toBe(true);
expect(listAccommodationsRequestSchema.safeParse({ tripId: -1 }).success).toBe(false);
});
});
@@ -0,0 +1,37 @@
import { idSchema } from '../common/primitives.schema';
import { z } from 'zod';
/**
* The trip reads of the bookings an assistant makes over MCP. `get_trip_summary`
* carries every booking with its metadata, which the provider never sees (a
* flight number or a seat lives there); these two answer the bookings and the
* stays alone, with the readable details pulled out of the metadata.
*/
/** What a booking is, as a filter: getting there (a flight, a train, a hire car) or anything booked on the way. */
export const RESERVATION_READ_KINDS = ['transport', 'booking'] as const;
export type ReservationReadKind = (typeof RESERVATION_READ_KINDS)[number];
/** `list_reservations`: the trip's bookings, of one kind or both, on one day or all of them. */
export const listReservationsRequestSchema = z.object({
tripId: idSchema,
kinds: z
.array(z.enum(RESERVATION_READ_KINDS))
.min(1)
.max(RESERVATION_READ_KINDS.length)
.optional()
.describe(
'Only these kinds: "transport" (flights, trains, hire cars and other rides) or "booking" (hotels, tables, tickets). Both when left out.',
),
dayId: idSchema
.optional()
.describe(
'Only the bookings on this day: those that start or end on it, a stopover leg on it, or a stay checking in on it.',
),
});
export type ListReservationsRequest = z.infer<typeof listReservationsRequestSchema>;
/** `list_accommodations`: where the trip sleeps, stay by stay. */
export const listAccommodationsRequestSchema = z.object({ tripId: idSchema });
export type ListAccommodationsRequest = z.infer<typeof listAccommodationsRequestSchema>;