From 49f97af3fb9c95ccfbf93a8f3b60016608f2f60f Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 4 Sep 2026 23:04:10 +0200 Subject: [PATCH] fix(roadtrip): the range figure keeps counting until something actually refuels Reported off a real day: Berlin said 245 km since the last fill-up and Sanssouci said 121, as if the tank had been filled in between. It had not. The budget was being zeroed at every warning, so the first figure was right and every one after it was the length of one leg rather than the distance on the tank. A warning is not a fill-up. Only a fuel or charging stop resets it now, which is what makes putting one in the answer rather than a formality: the same day reads 125, 370, 519 without one, and collapses to a single mark with one. Nothing is flagged on a fuel stop either. Reaching a petrol station on an empty tank is the plan working, and a warning there would sit on the one stop that answers it. Also: the stop number sits level with the middle of its row rather than at the top, the way the corridor list already places its badges. A number pinned to the first line drifts off as soon as a stop carries a stay and a walk under its name. --- .../Roadtrip/RoadtripCorridorPanel.tsx | 35 +++++++------ .../components/Roadtrip/RoadtripSidebar.tsx | 17 +++++-- .../components/Roadtrip/roadtripModel.test.ts | 50 +++++++++++++++---- .../src/components/Roadtrip/roadtripModel.ts | 18 ++++--- shared/src/i18n/ar/roadtrip.ts | 6 +++ shared/src/i18n/br/roadtrip.ts | 6 +++ shared/src/i18n/ca/roadtrip.ts | 6 +++ shared/src/i18n/cs/roadtrip.ts | 6 +++ shared/src/i18n/de/roadtrip.ts | 6 +++ shared/src/i18n/en/roadtrip.ts | 6 +++ shared/src/i18n/es/roadtrip.ts | 6 +++ shared/src/i18n/fr/roadtrip.ts | 6 +++ shared/src/i18n/gr/roadtrip.ts | 6 +++ shared/src/i18n/hu/roadtrip.ts | 6 +++ shared/src/i18n/id/roadtrip.ts | 6 +++ shared/src/i18n/it/roadtrip.ts | 6 +++ shared/src/i18n/ja/roadtrip.ts | 6 +++ shared/src/i18n/ko/roadtrip.ts | 6 +++ shared/src/i18n/nl/roadtrip.ts | 6 +++ shared/src/i18n/pl/roadtrip.ts | 6 +++ shared/src/i18n/ru/roadtrip.ts | 6 +++ shared/src/i18n/sv/roadtrip.ts | 6 +++ shared/src/i18n/tr/roadtrip.ts | 6 +++ shared/src/i18n/uk/roadtrip.ts | 6 +++ shared/src/i18n/vi/roadtrip.ts | 6 +++ shared/src/i18n/zh-TW/roadtrip.ts | 6 +++ shared/src/i18n/zh/roadtrip.ts | 6 +++ 27 files changed, 222 insertions(+), 36 deletions(-) diff --git a/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx b/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx index ef6236c50..4761fb68f 100644 --- a/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx +++ b/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx @@ -1,7 +1,6 @@ import React from 'react' import { - Fuel, Zap, ParkingSquare, Tent, Utensils, Camera, Search, Plus, RotateCw, - AlertTriangle, MapPin, X, type LucideIcon, + Search, Plus, RotateCw, AlertTriangle, X, BedDouble, MapPin, } from 'lucide-react' import { useTranslation } from '../../i18n/TranslationContext' import { Tooltip } from '../shared/Tooltip' @@ -90,18 +89,26 @@ function ResultRow({ poi, onAdd }: { poi: CorridorPoi; onAdd?: () => void }): Re {/* Always there, quiet until the row is under the pointer: a button that only exists on hover is one a keyboard user has to find by faith. */} - {onAdd ? ( - - - - ) : null} + {onAdd ? (() => { + // One button, two meanings. Somewhere to sleep ends the day rather than + // interrupting the drive, so the icon and the label say that before the dialog + // opens instead of after. + const night = poi.category === 'hotel' + const label = night ? t('roadtrip.stay.nightAction') : t('roadtrip.poi.add') + const Icon = night ? BedDouble : Plus + return ( + + + + ) + })() : null} ) } diff --git a/client/src/components/Roadtrip/RoadtripSidebar.tsx b/client/src/components/Roadtrip/RoadtripSidebar.tsx index 8610c8659..84adc3f51 100644 --- a/client/src/components/Roadtrip/RoadtripSidebar.tsx +++ b/client/src/components/Roadtrip/RoadtripSidebar.tsx @@ -576,7 +576,7 @@ function Arrival({ entry }: { entry: ScheduleEntry }): React.ReactElement { ) } -function Stop({ stop, number, entry, late, driveFindings, selected, continues, onSelect, onMove, canMove, onEditStay }: { +function Stop({ stop, number, entry, late, driveFindings, selected, continues, starts, onSelect, onMove, canMove, onEditStay }: { stop: RoadtripStop /** Position within the day — the same count the map badges its markers with. */ number: number @@ -587,6 +587,8 @@ function Stop({ stop, number, entry, late, driveFindings, selected, continues, o selected: boolean /** Whether the chain goes on below, so the marker keeps hold of the line. */ continues: boolean + /** First row of the day: no line above it, because the chain starts here. */ + starts?: boolean onSelect?: () => void /** Moves this stop by one place. Absent means the chain is read-only. */ onMove?: (delta: number) => void @@ -614,16 +616,20 @@ function Stop({ stop, number, entry, late, driveFindings, selected, continues, o className="group grid w-full rounded-lg text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent" style={RAIL_GRID} > - {/* The marker and the line below it share one column, so the chain runs unbroken - from stop to stop rather than restarting under whatever the row happens to hold. */} + {/* The marker sits level with the middle of the row rather than at its top, the + way the corridor list already places its own badges: a number pinned to the + first line drifts away from the row as soon as a stop carries a stay and a walk + under its name. The line grows above and below it, so the chain still runs + unbroken from stop to stop. */} + {starts ? null : } {number} - {continues ? : null} + {continues ? : null} {/* The fill stops at the rail: the number is part of the chain, not part of the row @@ -810,6 +816,7 @@ function DaySection({ day, selectedAssignmentId, onSelectStop, onReorderStop, on driveFindings={day.driveWarnings.filter(w => w.index === i)} selected={selectedAssignmentId === stop.assignmentId} continues={i < last} + starts={i === 0} onSelect={onSelectStop ? () => onSelectStop(stop.placeId, stop.assignmentId) : undefined} onMove={onReorderStop ? delta => onReorderStop(day.dayId, stop.assignmentId, i + delta) : undefined} canMove={{ up: i > 0, down: i < last }} diff --git a/client/src/components/Roadtrip/roadtripModel.test.ts b/client/src/components/Roadtrip/roadtripModel.test.ts index 1e8ad75dc..3f33ff957 100644 --- a/client/src/components/Roadtrip/roadtripModel.test.ts +++ b/client/src/components/Roadtrip/roadtripModel.test.ts @@ -289,14 +289,28 @@ describe('deriveDriveWarnings', () => { { legMinutes: null, dayMinutes: null, rangeKm: 100 }, 0, ) - // 21.5 + 103.4 on arrival at HEM, then 244.7 on arrival at Berlin, because the budget - // starts over after each finding. + // 21.5 + 103.4 on arrival at HEM, and then it keeps counting, because nothing on this + // trip fills up. expect(out.warnings).toEqual([ { index: 2, code: 'range', sinceKm: 125 }, - { index: 3, code: 'range', sinceKm: 245 }, + { index: 3, code: 'range', sinceKm: 370 }, ]) }) + it('FE-ROADTRIP-MODEL-070: arriving at a petrol station is the plan, not a warning', () => { + // Same trip, but HEM is marked as fuel. Reaching it with an empty tank is exactly + // what it is there for, so nothing is flagged on it; the budget still starts over, + // and the next stretch is measured from there. + const out = deriveDriveWarnings( + [leg(20, 21.5), leg(62, 103.4), leg(155, 244.7)], + [false, false, true, false], + { legMinutes: null, dayMinutes: null, rangeKm: 100 }, + 0, + ) + expect(out.warnings).toEqual([{ index: 3, code: 'range', sinceKm: 245 }]) + // 245 and not 370: HEM filled the tank, so Berlin counts from there. + }) + const noLimits = { legMinutes: null, dayMinutes: null, rangeKm: null } const leg = (minutes: number, km: number) => ({ duration: minutes * 60, distance: km * 1000 }) @@ -329,20 +343,34 @@ describe('deriveDriveWarnings', () => { expect(out.day).toEqual({ code: 'dayDriving', minutes: 400, limitMinutes: 360 }) }) - it('FE-ROADTRIP-MODEL-063: the range runs out once and then starts over', () => { - // Without the reset, a 1800 km trip on a 600 km range flags every leg after the first - // overrun, which is a column of red nobody reads. With it the marks stand one range - // apart and each means "fill up around here". + it('FE-ROADTRIP-MODEL-063: the figure keeps counting until something actually refuels', () => { + // A warning is not a fill-up. Zeroing the budget at one made every figure after the + // first wrong: the second stop would claim a fresh tank while the same one is still + // in the car. const out = deriveDriveWarnings( [leg(60, 300), leg(60, 400), leg(60, 300), leg(60, 400)], [false, false, false, false, false], { ...noLimits, rangeKm: 600 }, 0, ) - expect(out.warnings.map(w => w.code)).toEqual(['range', 'range']) - // 300 + 400 on arrival at stop 2, which is exactly what adding up the two drive bands - // above it gives. - expect(out.warnings[0]).toEqual({ index: 2, code: 'range', sinceKm: 700 }) + expect(out.warnings).toEqual([ + { index: 2, code: 'range', sinceKm: 700 }, + { index: 3, code: 'range', sinceKm: 1000 }, + { index: 4, code: 'range', sinceKm: 1400 }, + ]) + }) + + it('FE-ROADTRIP-MODEL-071: adding a fuel stop is what stops the run of warnings', () => { + // The same drive with a charger at stop 2. Nothing is flagged there, because reaching + // it on an empty tank is what it is for; everything after counts from zero again, so + // the three-warning run above collapses to one. + const out = deriveDriveWarnings( + [leg(60, 300), leg(60, 400), leg(60, 300), leg(60, 400)], + [false, false, true, false, false], + { ...noLimits, rangeKm: 600 }, + 0, + ) + expect(out.warnings).toEqual([{ index: 4, code: 'range', sinceKm: 700 }]) }) it('FE-ROADTRIP-MODEL-064: filling up starts the budget over, resting does not', () => { diff --git a/client/src/components/Roadtrip/roadtripModel.ts b/client/src/components/Roadtrip/roadtripModel.ts index 49dd79c5a..9b8ec45e8 100644 --- a/client/src/components/Roadtrip/roadtripModel.ts +++ b/client/src/components/Roadtrip/roadtripModel.ts @@ -304,10 +304,13 @@ export function sumLegSeconds(legSeconds: (number | undefined)[]): number { * an hour of the day would simply never fire. All three limits are therefore durations and * kilometres, which exist as soon as a leg has routed. * - * The range budget carries across midnight, because a tank does not empty overnight, and - * resets to zero after a finding: without that reset, one trip of 1800 km on a 600 km - * range flags every leg after the first overrun, which is a column of red nobody reads. - * With it, the marks stand one range apart and each one means "fill up around here". + * The range budget resets at a fuel or charging stop and NOWHERE ELSE. It carries across + * midnight, because a tank does not empty overnight, and it keeps counting past a finding, + * because a warning is not a fill-up. Zeroing it there made the second figure wrong and + * every one after it: a day reading 245 km at one stop and 121 at the next claims the 121 + * is a fresh tank, when it is 366 on the same one. A run of warnings down a stretch with + * no fuel on it is not noise; it is the answer, and it stops the moment a fuel or + * charging stop is put in. * * An unrouted leg gives the budget up entirely rather than guessing, the same way the * schedule abandons its cursor: a distance we do not have cannot be added to one we do. @@ -341,9 +344,12 @@ export function deriveDriveWarnings( budget = null } else if (budget !== null) { budget += metres / 1000 - if (limits.rangeKm && budget > limits.rangeKm) { + // Not on a stop that fills up: arriving at a petrol station with an empty tank is + // the plan working, not a problem, and a warning there would sit on the one stop + // that answers it. No reset either — a warning is not a fill-up, and the figure has + // to keep counting until a fuel or charging stop actually puts one in. + if (limits.rangeKm && budget > limits.rangeKm && !refuelsAt[at]) { warnings.push({ index: at, code: 'range', sinceKm: Math.round(budget) }) - budget = 0 } } } diff --git a/shared/src/i18n/ar/roadtrip.ts b/shared/src/i18n/ar/roadtrip.ts index cbd7e92ed..0b4535992 100644 --- a/shared/src/i18n/ar/roadtrip.ts +++ b/shared/src/i18n/ar/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'غير محددة', 'roadtrip.stop.none': 'وجهة', 'roadtrip.stop.kindHelp': 'التوقف في الطريق يُرسم على المسار ولا يُحتسب ضمن عدد التوقفات.', + 'roadtrip.stay.mode.pause': 'استراحة', + 'roadtrip.stay.mode.night': 'مبيت', + 'roadtrip.stay.checkOutDay': 'المغادرة في', + 'roadtrip.stay.dayNumber': 'اليوم {number}', + 'roadtrip.stay.nightAdded': 'أُضيف كمبيت', + 'roadtrip.stay.nightAction': 'إضافة كمبيت', 'roadtrip.poi.rest': 'استراحة', 'roadtrip.poi.campsite': 'مخيم', 'roadtrip.poi.food': 'طعام', diff --git a/shared/src/i18n/br/roadtrip.ts b/shared/src/i18n/br/roadtrip.ts index b2cb362d8..f9048e136 100644 --- a/shared/src/i18n/br/roadtrip.ts +++ b/shared/src/i18n/br/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Nenhum definido', 'roadtrip.stop.none': 'Um destino', 'roadtrip.stop.kindHelp': 'Uma parada no caminho é desenhada no trajeto e não é contada.', + 'roadtrip.stay.mode.pause': 'Pausa', + 'roadtrip.stay.mode.night': 'Pernoite', + 'roadtrip.stay.checkOutDay': 'Saída em', + 'roadtrip.stay.dayNumber': 'Dia {number}', + 'roadtrip.stay.nightAdded': 'Adicionado como pernoite', + 'roadtrip.stay.nightAction': 'Adicionar como pernoite', 'roadtrip.poi.rest': 'Área de descanso', 'roadtrip.poi.campsite': 'Camping', 'roadtrip.poi.food': 'Comida', diff --git a/shared/src/i18n/ca/roadtrip.ts b/shared/src/i18n/ca/roadtrip.ts index 7fca4f9f7..0cb15311a 100644 --- a/shared/src/i18n/ca/roadtrip.ts +++ b/shared/src/i18n/ca/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Cap definit', 'roadtrip.stop.none': 'Una destinació', 'roadtrip.stop.kindHelp': 'Una parada al camí es dibuixa sobre el trajecte i no es compta.', + 'roadtrip.stay.mode.pause': 'Parada', + 'roadtrip.stay.mode.night': 'Pernoctar', + 'roadtrip.stay.checkOutDay': 'Sortida el', + 'roadtrip.stay.dayNumber': 'Dia {number}', + 'roadtrip.stay.nightAdded': 'Afegit com a pernoctació', + 'roadtrip.stay.nightAction': 'Afegeix com a pernoctació', 'roadtrip.poi.rest': 'Àrea de descans', 'roadtrip.poi.campsite': 'Càmping', 'roadtrip.poi.food': 'Menjar', diff --git a/shared/src/i18n/cs/roadtrip.ts b/shared/src/i18n/cs/roadtrip.ts index 9dd5acfc8..5d65b343e 100644 --- a/shared/src/i18n/cs/roadtrip.ts +++ b/shared/src/i18n/cs/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Nenastaveno', 'roadtrip.stop.none': 'Cíl cesty', 'roadtrip.stop.kindHelp': 'Zastávka po cestě se kreslí na trase a nepočítá se.', + 'roadtrip.stay.mode.pause': 'Pauza', + 'roadtrip.stay.mode.night': 'Nocleh', + 'roadtrip.stay.checkOutDay': 'Odjezd', + 'roadtrip.stay.dayNumber': 'Den {number}', + 'roadtrip.stay.nightAdded': 'Přidáno jako nocleh', + 'roadtrip.stay.nightAction': 'Přidat jako nocleh', 'roadtrip.poi.rest': 'Odpočívadlo', 'roadtrip.poi.campsite': 'Kemp', 'roadtrip.poi.food': 'Jídlo', diff --git a/shared/src/i18n/de/roadtrip.ts b/shared/src/i18n/de/roadtrip.ts index 7f57b1981..eaa85f6f7 100644 --- a/shared/src/i18n/de/roadtrip.ts +++ b/shared/src/i18n/de/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Keine gesetzt', 'roadtrip.stop.none': 'Ein Ziel', 'roadtrip.stop.kindHelp': 'Ein Halt unterwegs wird auf der Fahrt gezeichnet und nicht mitgezählt.', + 'roadtrip.stay.mode.pause': 'Pause', + 'roadtrip.stay.mode.night': 'Übernachten', + 'roadtrip.stay.checkOutDay': 'Abreise am', + 'roadtrip.stay.dayNumber': 'Tag {number}', + 'roadtrip.stay.nightAdded': 'Als Übernachtung hinzugefügt', + 'roadtrip.stay.nightAction': 'Als Übernachtung hinzufügen', 'roadtrip.poi.rest': 'Rastplatz', 'roadtrip.poi.campsite': 'Campingplatz', 'roadtrip.poi.food': 'Essen', diff --git a/shared/src/i18n/en/roadtrip.ts b/shared/src/i18n/en/roadtrip.ts index 0d7c40a2d..4e4c18ffb 100644 --- a/shared/src/i18n/en/roadtrip.ts +++ b/shared/src/i18n/en/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'None set', 'roadtrip.stop.none': 'A destination', 'roadtrip.stop.kindHelp': 'A pause on the way is drawn on the drive and left out of the stop count.', + 'roadtrip.stay.mode.pause': 'Pause', + 'roadtrip.stay.mode.night': 'Overnight', + 'roadtrip.stay.checkOutDay': 'Check out on', + 'roadtrip.stay.dayNumber': 'Day {number}', + 'roadtrip.stay.nightAdded': 'Added as an overnight stay', + 'roadtrip.stay.nightAction': 'Add as an overnight stay', 'roadtrip.poi.rest': 'Rest area', 'roadtrip.poi.campsite': 'Campsite', 'roadtrip.poi.food': 'Food', diff --git a/shared/src/i18n/es/roadtrip.ts b/shared/src/i18n/es/roadtrip.ts index e83107ce9..3d767f934 100644 --- a/shared/src/i18n/es/roadtrip.ts +++ b/shared/src/i18n/es/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Ninguno definido', 'roadtrip.stop.none': 'Un destino', 'roadtrip.stop.kindHelp': 'Una parada en el camino se dibuja sobre el trayecto y no se cuenta.', + 'roadtrip.stay.mode.pause': 'Parada', + 'roadtrip.stay.mode.night': 'Pernoctar', + 'roadtrip.stay.checkOutDay': 'Salida el', + 'roadtrip.stay.dayNumber': 'Día {number}', + 'roadtrip.stay.nightAdded': 'Añadido como pernoctación', + 'roadtrip.stay.nightAction': 'Añadir como pernoctación', 'roadtrip.poi.rest': 'Área de descanso', 'roadtrip.poi.campsite': 'Camping', 'roadtrip.poi.food': 'Comida', diff --git a/shared/src/i18n/fr/roadtrip.ts b/shared/src/i18n/fr/roadtrip.ts index aeebbfff9..a76d8eacc 100644 --- a/shared/src/i18n/fr/roadtrip.ts +++ b/shared/src/i18n/fr/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Aucune définie', 'roadtrip.stop.none': 'Une destination', 'roadtrip.stop.kindHelp': 'Un arrêt en chemin est dessiné sur le trajet et n’est pas compté.', + 'roadtrip.stay.mode.pause': 'Pause', + 'roadtrip.stay.mode.night': 'Nuitée', + 'roadtrip.stay.checkOutDay': 'Départ le', + 'roadtrip.stay.dayNumber': 'Jour {number}', + 'roadtrip.stay.nightAdded': 'Ajouté comme nuitée', + 'roadtrip.stay.nightAction': 'Ajouter comme nuitée', 'roadtrip.poi.rest': 'Aire de repos', 'roadtrip.poi.campsite': 'Camping', 'roadtrip.poi.food': 'Restauration', diff --git a/shared/src/i18n/gr/roadtrip.ts b/shared/src/i18n/gr/roadtrip.ts index 1c452e27e..b3338f053 100644 --- a/shared/src/i18n/gr/roadtrip.ts +++ b/shared/src/i18n/gr/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Δεν έχουν οριστεί', 'roadtrip.stop.none': 'Προορισμός', 'roadtrip.stop.kindHelp': 'Μια στάση στον δρόμο σχεδιάζεται πάνω στη διαδρομή και δεν προσμετράται.', + 'roadtrip.stay.mode.pause': 'Στάση', + 'roadtrip.stay.mode.night': 'Διανυκτέρευση', + 'roadtrip.stay.checkOutDay': 'Αναχώρηση', + 'roadtrip.stay.dayNumber': 'Ημέρα {number}', + 'roadtrip.stay.nightAdded': 'Προστέθηκε ως διανυκτέρευση', + 'roadtrip.stay.nightAction': 'Προσθήκη ως διανυκτέρευση', 'roadtrip.poi.rest': 'Χώρος ανάπαυσης', 'roadtrip.poi.campsite': 'Κάμπινγκ', 'roadtrip.poi.food': 'Φαγητό', diff --git a/shared/src/i18n/hu/roadtrip.ts b/shared/src/i18n/hu/roadtrip.ts index e3666f45b..6594941d6 100644 --- a/shared/src/i18n/hu/roadtrip.ts +++ b/shared/src/i18n/hu/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Nincs beállítva', 'roadtrip.stop.none': 'Úti cél', 'roadtrip.stop.kindHelp': 'Az útközbeni megálló az útvonalra kerül, és nem számít bele.', + 'roadtrip.stay.mode.pause': 'Szünet', + 'roadtrip.stay.mode.night': 'Éjszakázás', + 'roadtrip.stay.checkOutDay': 'Kijelentkezés', + 'roadtrip.stay.dayNumber': '{number}. nap', + 'roadtrip.stay.nightAdded': 'Hozzáadva éjszakázásként', + 'roadtrip.stay.nightAction': 'Hozzáadás éjszakázásként', 'roadtrip.poi.rest': 'Pihenőhely', 'roadtrip.poi.campsite': 'Kemping', 'roadtrip.poi.food': 'Étkezés', diff --git a/shared/src/i18n/id/roadtrip.ts b/shared/src/i18n/id/roadtrip.ts index c87edc901..c76908285 100644 --- a/shared/src/i18n/id/roadtrip.ts +++ b/shared/src/i18n/id/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Belum diatur', 'roadtrip.stop.none': 'Sebuah tujuan', 'roadtrip.stop.kindHelp': 'Perhentian di jalan digambar pada rute dan tidak dihitung.', + 'roadtrip.stay.mode.pause': 'Istirahat', + 'roadtrip.stay.mode.night': 'Menginap', + 'roadtrip.stay.checkOutDay': 'Check out', + 'roadtrip.stay.dayNumber': 'Hari {number}', + 'roadtrip.stay.nightAdded': 'Ditambahkan sebagai menginap', + 'roadtrip.stay.nightAction': 'Tambahkan sebagai menginap', 'roadtrip.poi.rest': 'Tempat istirahat', 'roadtrip.poi.campsite': 'Perkemahan', 'roadtrip.poi.food': 'Makanan', diff --git a/shared/src/i18n/it/roadtrip.ts b/shared/src/i18n/it/roadtrip.ts index bd42c75ee..5c6ebbbda 100644 --- a/shared/src/i18n/it/roadtrip.ts +++ b/shared/src/i18n/it/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Nessuno impostato', 'roadtrip.stop.none': 'Una destinazione', 'roadtrip.stop.kindHelp': 'Una sosta lungo il percorso viene disegnata sulla tratta e non viene contata.', + 'roadtrip.stay.mode.pause': 'Sosta', + 'roadtrip.stay.mode.night': 'Pernottamento', + 'roadtrip.stay.checkOutDay': 'Partenza il', + 'roadtrip.stay.dayNumber': 'Giorno {number}', + 'roadtrip.stay.nightAdded': 'Aggiunto come pernottamento', + 'roadtrip.stay.nightAction': 'Aggiungi come pernottamento', 'roadtrip.poi.rest': 'Area di sosta', 'roadtrip.poi.campsite': 'Campeggio', 'roadtrip.poi.food': 'Ristoro', diff --git a/shared/src/i18n/ja/roadtrip.ts b/shared/src/i18n/ja/roadtrip.ts index bcc230370..21ecbce17 100644 --- a/shared/src/i18n/ja/roadtrip.ts +++ b/shared/src/i18n/ja/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': '未設定', 'roadtrip.stop.none': '目的地', 'roadtrip.stop.kindHelp': '途中の立ち寄りは走行線上に描かれ、停車数には数えません。', + 'roadtrip.stay.mode.pause': '休憩', + 'roadtrip.stay.mode.night': '宿泊', + 'roadtrip.stay.checkOutDay': 'チェックアウト日', + 'roadtrip.stay.dayNumber': '{number}日目', + 'roadtrip.stay.nightAdded': '宿泊として追加しました', + 'roadtrip.stay.nightAction': '宿泊として追加', 'roadtrip.poi.rest': 'サービスエリア', 'roadtrip.poi.campsite': 'キャンプ場', 'roadtrip.poi.food': '食事', diff --git a/shared/src/i18n/ko/roadtrip.ts b/shared/src/i18n/ko/roadtrip.ts index 92fc9573e..6625efc92 100644 --- a/shared/src/i18n/ko/roadtrip.ts +++ b/shared/src/i18n/ko/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': '설정 안 됨', 'roadtrip.stop.none': '목적지', 'roadtrip.stop.kindHelp': '경유 정차는 주행 경로에 표시되며 정차 수에 포함되지 않습니다.', + 'roadtrip.stay.mode.pause': '휴식', + 'roadtrip.stay.mode.night': '숙박', + 'roadtrip.stay.checkOutDay': '체크아웃 날짜', + 'roadtrip.stay.dayNumber': '{number}일차', + 'roadtrip.stay.nightAdded': '숙박으로 추가했습니다', + 'roadtrip.stay.nightAction': '숙박으로 추가', 'roadtrip.poi.rest': '휴게소', 'roadtrip.poi.campsite': '캠핑장', 'roadtrip.poi.food': '식사', diff --git a/shared/src/i18n/nl/roadtrip.ts b/shared/src/i18n/nl/roadtrip.ts index 4cd4277a0..caa162ce4 100644 --- a/shared/src/i18n/nl/roadtrip.ts +++ b/shared/src/i18n/nl/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Geen ingesteld', 'roadtrip.stop.none': 'Een bestemming', 'roadtrip.stop.kindHelp': 'Een stop onderweg wordt op de rit getekend en telt niet mee.', + 'roadtrip.stay.mode.pause': 'Pauze', + 'roadtrip.stay.mode.night': 'Overnachten', + 'roadtrip.stay.checkOutDay': 'Uitchecken op', + 'roadtrip.stay.dayNumber': 'Dag {number}', + 'roadtrip.stay.nightAdded': 'Toegevoegd als overnachting', + 'roadtrip.stay.nightAction': 'Toevoegen als overnachting', 'roadtrip.poi.rest': 'Rustplaats', 'roadtrip.poi.campsite': 'Camping', 'roadtrip.poi.food': 'Eten', diff --git a/shared/src/i18n/pl/roadtrip.ts b/shared/src/i18n/pl/roadtrip.ts index cadd4f4be..17249cd7c 100644 --- a/shared/src/i18n/pl/roadtrip.ts +++ b/shared/src/i18n/pl/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Brak ustawionych', 'roadtrip.stop.none': 'Cel podróży', 'roadtrip.stop.kindHelp': 'Postój po drodze rysowany jest na trasie i nie jest liczony.', + 'roadtrip.stay.mode.pause': 'Postój', + 'roadtrip.stay.mode.night': 'Nocleg', + 'roadtrip.stay.checkOutDay': 'Wymeldowanie', + 'roadtrip.stay.dayNumber': 'Dzień {number}', + 'roadtrip.stay.nightAdded': 'Dodano jako nocleg', + 'roadtrip.stay.nightAction': 'Dodaj jako nocleg', 'roadtrip.poi.rest': 'Miejsce odpoczynku', 'roadtrip.poi.campsite': 'Kemping', 'roadtrip.poi.food': 'Jedzenie', diff --git a/shared/src/i18n/ru/roadtrip.ts b/shared/src/i18n/ru/roadtrip.ts index b4b807a99..e2c309045 100644 --- a/shared/src/i18n/ru/roadtrip.ts +++ b/shared/src/i18n/ru/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Не заданы', 'roadtrip.stop.none': 'Пункт назначения', 'roadtrip.stop.kindHelp': 'Остановка в пути рисуется на маршруте и не учитывается в счёте.', + 'roadtrip.stay.mode.pause': 'Остановка', + 'roadtrip.stay.mode.night': 'Ночёвка', + 'roadtrip.stay.checkOutDay': 'Выезд', + 'roadtrip.stay.dayNumber': 'День {number}', + 'roadtrip.stay.nightAdded': 'Добавлено как ночёвка', + 'roadtrip.stay.nightAction': 'Добавить как ночёвку', 'roadtrip.poi.rest': 'Зона отдыха', 'roadtrip.poi.campsite': 'Кемпинг', 'roadtrip.poi.food': 'Еда', diff --git a/shared/src/i18n/sv/roadtrip.ts b/shared/src/i18n/sv/roadtrip.ts index 2efc87400..5c490df95 100644 --- a/shared/src/i18n/sv/roadtrip.ts +++ b/shared/src/i18n/sv/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Inga angivna', 'roadtrip.stop.none': 'Ett resmål', 'roadtrip.stop.kindHelp': 'Ett stopp på vägen ritas på körningen och räknas inte.', + 'roadtrip.stay.mode.pause': 'Paus', + 'roadtrip.stay.mode.night': 'Övernattning', + 'roadtrip.stay.checkOutDay': 'Utcheckning', + 'roadtrip.stay.dayNumber': 'Dag {number}', + 'roadtrip.stay.nightAdded': 'Tillagd som övernattning', + 'roadtrip.stay.nightAction': 'Lägg till som övernattning', 'roadtrip.poi.rest': 'Rastplats', 'roadtrip.poi.campsite': 'Campingplats', 'roadtrip.poi.food': 'Mat', diff --git a/shared/src/i18n/tr/roadtrip.ts b/shared/src/i18n/tr/roadtrip.ts index 6881f2c30..0550743f8 100644 --- a/shared/src/i18n/tr/roadtrip.ts +++ b/shared/src/i18n/tr/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Ayarlanmadı', 'roadtrip.stop.none': 'Bir varış noktası', 'roadtrip.stop.kindHelp': 'Yol üzerindeki mola sürüşe çizilir ve sayıma girmez.', + 'roadtrip.stay.mode.pause': 'Mola', + 'roadtrip.stay.mode.night': 'Konaklama', + 'roadtrip.stay.checkOutDay': 'Çıkış günü', + 'roadtrip.stay.dayNumber': '{number}. gün', + 'roadtrip.stay.nightAdded': 'Konaklama olarak eklendi', + 'roadtrip.stay.nightAction': 'Konaklama olarak ekle', 'roadtrip.poi.rest': 'Dinlenme alanı', 'roadtrip.poi.campsite': 'Kamp alanı', 'roadtrip.poi.food': 'Yemek', diff --git a/shared/src/i18n/uk/roadtrip.ts b/shared/src/i18n/uk/roadtrip.ts index fd92332bd..4c4f90543 100644 --- a/shared/src/i18n/uk/roadtrip.ts +++ b/shared/src/i18n/uk/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Не задано', 'roadtrip.stop.none': 'Пункт призначення', 'roadtrip.stop.kindHelp': 'Зупинка в дорозі малюється на маршруті й не рахується.', + 'roadtrip.stay.mode.pause': 'Зупинка', + 'roadtrip.stay.mode.night': 'Ночівля', + 'roadtrip.stay.checkOutDay': 'Виїзд', + 'roadtrip.stay.dayNumber': 'День {number}', + 'roadtrip.stay.nightAdded': 'Додано як ночівлю', + 'roadtrip.stay.nightAction': 'Додати як ночівлю', 'roadtrip.poi.rest': 'Зона відпочинку', 'roadtrip.poi.campsite': 'Кемпінг', 'roadtrip.poi.food': 'Їжа', diff --git a/shared/src/i18n/vi/roadtrip.ts b/shared/src/i18n/vi/roadtrip.ts index c249535cd..2f00b4aa5 100644 --- a/shared/src/i18n/vi/roadtrip.ts +++ b/shared/src/i18n/vi/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': 'Chưa đặt', 'roadtrip.stop.none': 'Một điểm đến', 'roadtrip.stop.kindHelp': 'Điểm dừng dọc đường được vẽ trên chặng và không tính vào số điểm dừng.', + 'roadtrip.stay.mode.pause': 'Nghỉ', + 'roadtrip.stay.mode.night': 'Qua đêm', + 'roadtrip.stay.checkOutDay': 'Trả phòng ngày', + 'roadtrip.stay.dayNumber': 'Ngày {number}', + 'roadtrip.stay.nightAdded': 'Đã thêm làm nơi nghỉ đêm', + 'roadtrip.stay.nightAction': 'Thêm làm nơi nghỉ đêm', 'roadtrip.poi.rest': 'Trạm dừng nghỉ', 'roadtrip.poi.campsite': 'Khu cắm trại', 'roadtrip.poi.food': 'Đồ ăn', diff --git a/shared/src/i18n/zh-TW/roadtrip.ts b/shared/src/i18n/zh-TW/roadtrip.ts index 0a9ffefad..a08c257fb 100644 --- a/shared/src/i18n/zh-TW/roadtrip.ts +++ b/shared/src/i18n/zh-TW/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': '未設定', 'roadtrip.stop.none': '目的地', 'roadtrip.stop.kindHelp': '途中停靠會畫在行程線上,且不計入停靠數。', + 'roadtrip.stay.mode.pause': '停留', + 'roadtrip.stay.mode.night': '過夜', + 'roadtrip.stay.checkOutDay': '退房日', + 'roadtrip.stay.dayNumber': '第 {number} 天', + 'roadtrip.stay.nightAdded': '已新增為過夜住宿', + 'roadtrip.stay.nightAction': '新增為過夜住宿', 'roadtrip.poi.rest': '休息站', 'roadtrip.poi.campsite': '露營地', 'roadtrip.poi.food': '餐飲', diff --git a/shared/src/i18n/zh/roadtrip.ts b/shared/src/i18n/zh/roadtrip.ts index 555c4b3a8..c1dd71b28 100644 --- a/shared/src/i18n/zh/roadtrip.ts +++ b/shared/src/i18n/zh/roadtrip.ts @@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = { 'roadtrip.limit.none': '未设置', 'roadtrip.stop.none': '目的地', 'roadtrip.stop.kindHelp': '途中停靠会画在行程线上,且不计入停靠数。', + 'roadtrip.stay.mode.pause': '停留', + 'roadtrip.stay.mode.night': '过夜', + 'roadtrip.stay.checkOutDay': '退房日', + 'roadtrip.stay.dayNumber': '第 {number} 天', + 'roadtrip.stay.nightAdded': '已添加为过夜住宿', + 'roadtrip.stay.nightAction': '添加为过夜住宿', 'roadtrip.poi.rest': '服务区', 'roadtrip.poi.campsite': '露营地', 'roadtrip.poi.food': '餐饮',