diff --git a/client/src/components/Dawarich/DawarichSuggestionsPanel.tsx b/client/src/components/Dawarich/DawarichSuggestionsPanel.tsx
index 8d9b0360f..8c15ce977 100644
--- a/client/src/components/Dawarich/DawarichSuggestionsPanel.tsx
+++ b/client/src/components/Dawarich/DawarichSuggestionsPanel.tsx
@@ -277,7 +277,14 @@ export default function DawarichSuggestionsPanel({
* The actions fade in on hover on a pointer device and stay visible on touch,
* where there is no hover to reveal them.
*/
-function SuggestionRow({
+/**
+ * One stay, as a card with its actions clipped to the side.
+ *
+ * Exported because the journal draws these rows in its own timeline now — folded into a
+ * day rather than stacked in a panel above it — and a second copy of a row this detailed
+ * would be two things to keep in step, plus a straight hit on the duplication budget.
+ */
+export function SuggestionRow({
suggestion,
busy,
allowJournal = false,
diff --git a/client/src/components/Journey/JourneyDayDawarich.tsx b/client/src/components/Journey/JourneyDayDawarich.tsx
new file mode 100644
index 000000000..ed5fae2ac
--- /dev/null
+++ b/client/src/components/Journey/JourneyDayDawarich.tsx
@@ -0,0 +1,96 @@
+import React, { useState } from 'react'
+import { ChevronDown, ChevronRight } from 'lucide-react'
+import type { DawarichSuggestion, DawarichSuggestionTarget } from '@trek/shared'
+import { useTranslation } from '../../i18n'
+import DawarichIcon from '../shared/DawarichIcon'
+import { SuggestionRow } from '../Dawarich/DawarichSuggestionsPanel'
+import { clockOf } from '../Dawarich/dawarichSuggestionModel'
+
+/**
+ * The stays Dawarich recorded on ONE day of the journal, folded into that day.
+ *
+ * They used to be a panel above the timeline: every open stay of every day, stacked over
+ * the entries, so a fortnight of driving put forty rows between the reader and their own
+ * first entry. The list belongs where the day is (discussion with Roel, 16.09.), and a
+ * day of driving still produces four to eleven stays, so the day shows one line with a
+ * count and opens on a tap.
+ *
+ * Shut, it reads as one more card in the day: the mark says where it came from without a
+ * word of explanation, and the times say which part of the day it covers. Open, it is the
+ * same rows the panel drew, which is why `SuggestionRow` is imported rather than copied.
+ *
+ * It never appears on a day with nothing pending: an integration that is connected and
+ * quiet should be invisible, not a permanent empty row on every day of the journey.
+ */
+export default function JourneyDayDawarich({
+ suggestions,
+ busyId,
+ onAccept,
+ onDismiss,
+}: {
+ /** The open stays of this day, in the order they were lived. */
+ suggestions: DawarichSuggestion[]
+ /** The stay a write is in flight for, or null. */
+ busyId: number | null
+ onAccept: (suggestion: DawarichSuggestion, target: DawarichSuggestionTarget) => void
+ onDismiss: (suggestion: DawarichSuggestion) => void
+}): React.ReactElement | null {
+ const { t } = useTranslation()
+ const [open, setOpen] = useState(false)
+
+ if (suggestions.length === 0) return null
+
+ // From the first arrival to the last departure: what part of the day this covers, in
+ // one line, so the row says something even while it is shut.
+ const from = clockOf(suggestions[0]!.startedAt)
+ const to = clockOf(suggestions[suggestions.length - 1]!.endedAt)
+ const span = from && to ? `${from} – ${to}` : from
+
+ return (
+
+ )
+}
diff --git a/client/src/pages/JourneyDetailPage.tsx b/client/src/pages/JourneyDetailPage.tsx
index 8d618df2f..a1807d29f 100644
--- a/client/src/pages/JourneyDetailPage.tsx
+++ b/client/src/pages/JourneyDetailPage.tsx
@@ -14,7 +14,7 @@ import {
Plus, ChevronUp, ChevronDown, Eye, EyeOff, BookOpen, Image, Search, X,
} from 'lucide-react'
import MobileMapTimeline from '../components/Journey/MobileMapTimeline'
-import DawarichSuggestionsPanel from '../components/Dawarich/DawarichSuggestionsPanel'
+import JourneyDayDawarich from '../components/Journey/JourneyDayDawarich'
import MobileEntryView from '../components/Journey/MobileEntryView'
import { useJourneyStore } from '../store/journeyStore'
import { computeJourneyLifecycle } from '../utils/journeyLifecycle'
@@ -47,6 +47,7 @@ function JourneyDetailPageDesktop() {
unlinkTrip, setUnlinkTrip, showSettings, setShowSettings,
hideSkeletons, setHideSkeletons,
query, setQuery, dismissSuggestion, restoreSuggestions, openAtEntryId,
+ dawarichByDate, dawarichBusyId, acceptDawarich, dismissDawarich,
mapRef, fullMapRef, galleryUploadRef, galleryProviders, setGalleryProviders, galleryBrowseRef,
activeLocationId, handleMarkerClick, handleLocationClick,
mapEntries, sidebarMapItems, tripDates, isMobile, tracks,
@@ -70,7 +71,14 @@ function JourneyDetailPageDesktop() {
query,
)
const dayGroups = groupByDate(timelineEntries)
- const sortedDates = [...dayGroups.keys()].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
+ // A stay falls on the day it happened, and that is often a day the journal has no entry
+ // on yet — which is the whole point of offering it. Those days join the timeline so the
+ // stay can be reached; without them the only way to a quiet day's stays would be to
+ // write an entry on it first. Not while a search is running: a day whose entries the
+ // query filtered out is not a day the reader is looking at.
+ const suggestionDates = canEditEntries && !query ? [...dawarichByDate.keys()] : []
+ const sortedDates = [...new Set([...dayGroups.keys(), ...suggestionDates])]
+ .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
const tripDateMin = current.trips.length
? current.trips.reduce((min: string, t: any) => t.start_date && (!min || t.start_date < min) ? t.start_date : min, '')
@@ -413,19 +421,6 @@ function JourneyDetailPageDesktop() {
{/* Timeline (desktop only — mobile uses fullscreen combined view above) */}
{!isMobile && (
- {/* Stays Dawarich recorded over this journal's dates, waiting to
- be turned into entries (#2279). Above the timeline because
- that is what they become; renders nothing when there is
- nothing pending. */}
- {canEditEntries && (
- { void loadJourney(current.id) }}
- />
- )}
-
{sortedDates.length === 0 && (
{
- const entries = dayGroups.get(date)!
+ // Empty on a day that only has stays waiting on it.
+ const entries = dayGroups.get(date) ?? []
+ const stays = canEditEntries ? dawarichByDate.get(date) ?? [] : []
const fd = formatDate(date, locale)
const locations = [...new Set(entries.map(e => e.location_name).filter(Boolean))]
@@ -550,6 +547,16 @@ function JourneyDetailPageDesktop() {
)
})}
+
+ {/* What Dawarich recorded on this day, folded into it. One line
+ with a count, the mark for where it came from, and the rows on
+ a tap. Nothing at all on a day with nothing pending. */}
+
)
})}
diff --git a/client/src/pages/journeyDetail/useJourneyDetail.ts b/client/src/pages/journeyDetail/useJourneyDetail.ts
index 7d267bcd9..dbb5efdba 100644
--- a/client/src/pages/journeyDetail/useJourneyDetail.ts
+++ b/client/src/pages/journeyDetail/useJourneyDetail.ts
@@ -12,6 +12,8 @@ import { useIsMobile } from '../../hooks/useIsMobile'
import { lockBodyScroll } from '../../utils/bodyScrollLock'
import type { JourneyEntry } from '../../store/journeyStore'
import { createDraftJourneyEntry } from './JourneyDetailPage.helpers'
+import { useDawarichSuggestions } from '../../hooks/useDawarichSuggestions'
+import type { DawarichSuggestion, DawarichSuggestionTarget } from '@trek/shared'
import { useDawarichJournalTrail } from '../../hooks/useDawarichJournalTrail'
@@ -298,6 +300,44 @@ export function useJourneyDetail() {
}
}, [current, loadJourney, toast, t])
+ /**
+ * The stays Dawarich recorded over this journal's dates, by the day they happened on.
+ *
+ * Read here rather than inside a panel so the timeline can fold each day's stays into
+ * that day (discussion with Roel, 16.09.): stacked above the entries, a fortnight of
+ * driving put forty rows between the reader and their own first entry.
+ *
+ * Only what is still open — an accepted stay is an entry on the timeline already, and a
+ * dismissed one was waved away on purpose. Within a day the order is the order they were
+ * lived in, which is what makes a run of them read as an afternoon.
+ */
+ const dawarich = useDawarichSuggestions()
+ const dawarichByDate = useMemo(() => {
+ const byDate = new Map()
+ for (const stay of dawarich.suggestions) {
+ if (stay.state !== 'new') continue
+ const bucket = byDate.get(stay.localDate)
+ if (bucket) bucket.push(stay)
+ else byDate.set(stay.localDate, [stay])
+ }
+ for (const stays of byDate.values()) stays.sort((a, b) => (a.startedAt < b.startedAt ? -1 : 1))
+ return byDate
+ }, [dawarich.suggestions])
+
+ /**
+ * Accepting writes the stay into THIS journal and reloads it, which is how the new entry
+ * reaches the timeline the stay was standing in.
+ */
+ const acceptDawarich = useCallback(async (suggestion: DawarichSuggestion, target: DawarichSuggestionTarget) => {
+ if (!current) return
+ const ok = await dawarich.accept(suggestion.id, { target, journalId: current.id })
+ if (ok) await loadJourney(current.id)
+ }, [dawarich, current, loadJourney])
+
+ const dismissDawarich = useCallback((suggestion: DawarichSuggestion) => {
+ void dawarich.dismiss(suggestion.id)
+ }, [dawarich])
+
const handleMarkerClick = useCallback((entryId: string) => {
const el = document.querySelector(`[data-entry-id="${entryId}"]`)
if (!el) return
@@ -503,6 +543,7 @@ export function useJourneyDetail() {
unlinkTrip, setUnlinkTrip, showSettings, setShowSettings,
hideSkeletons, setHideSkeletons,
query, setQuery, dismissSuggestion, restoreSuggestions,
+ dawarichByDate, dawarichBusyId: dawarich.busyId, acceptDawarich, dismissDawarich,
openAtEntryId,
mapRef, fullMapRef, galleryUploadRef, galleryProviders, setGalleryProviders, galleryBrowseRef,
activeLocationId, handleMarkerClick, handleLocationClick,
diff --git a/shared/src/i18n/ar/dawarich.ts b/shared/src/i18n/ar/dawarich.ts
index 64b5be2fe..8af889d73 100644
--- a/shared/src/i18n/ar/dawarich.ts
+++ b/shared/src/i18n/ar/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'على بُعد {km} كم',
'dawarich.bucket.rule': 'تُحتسب الأمنية محققة ضمن {meters} م وبعد {minutes} دقيقة في المكان.',
+ 'dawarich.journey.dayStays.one': 'إقامة واحدة من Dawarich',
+ 'dawarich.journey.dayStays.other': 'إقامات من Dawarich: {count}',
};
export default dawarich;
diff --git a/shared/src/i18n/br/dawarich.ts b/shared/src/i18n/br/dawarich.ts
index 73fe3f5b8..2d3dfda88 100644
--- a/shared/src/i18n/br/dawarich.ts
+++ b/shared/src/i18n/br/dawarich.ts
@@ -175,6 +175,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'a {km} km',
'dawarich.bucket.rule': 'Um desejo conta como alcançado a até {meters} m e após {minutes} minutos no local.',
+ 'dawarich.journey.dayStays.one': '1 parada do Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} paradas do Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/ca/dawarich.ts b/shared/src/i18n/ca/dawarich.ts
index bbc9aa412..bf9980e1e 100644
--- a/shared/src/i18n/ca/dawarich.ts
+++ b/shared/src/i18n/ca/dawarich.ts
@@ -174,6 +174,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'a {km} km',
'dawarich.bucket.rule': 'Un desig es considera assolit a menys de {meters} m i després de {minutes} minuts al lloc.',
+ 'dawarich.journey.dayStays.one': '1 estada de Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} estades de Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/cs/dawarich.ts b/shared/src/i18n/cs/dawarich.ts
index d8361290f..766db6edb 100644
--- a/shared/src/i18n/cs/dawarich.ts
+++ b/shared/src/i18n/cs/dawarich.ts
@@ -174,6 +174,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km daleko',
'dawarich.bucket.rule': 'Přání se počítá jako splněné do {meters} m a po {minutes} minutách na místě.',
+ 'dawarich.journey.dayStays.one': '1 zastávka z Dawarichu',
+ 'dawarich.journey.dayStays.other': 'Zastávky z Dawarichu: {count}',
};
export default dawarich;
diff --git a/shared/src/i18n/de/dawarich.ts b/shared/src/i18n/de/dawarich.ts
index 78283b868..dc96d0c2c 100644
--- a/shared/src/i18n/de/dawarich.ts
+++ b/shared/src/i18n/de/dawarich.ts
@@ -178,6 +178,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km entfernt',
'dawarich.bucket.rule': 'Ein Wunsch gilt ab {meters} m Nähe und {minutes} Minuten vor Ort als erreicht.',
+ 'dawarich.journey.dayStays.one': '1 Aufenthalt von Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} Aufenthalte von Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/en/dawarich.ts b/shared/src/i18n/en/dawarich.ts
index a04011cee..b9f16e240 100644
--- a/shared/src/i18n/en/dawarich.ts
+++ b/shared/src/i18n/en/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km away',
'dawarich.bucket.rule': 'A wish counts as reached within {meters} m and after {minutes} minutes on the spot.',
+ 'dawarich.journey.dayStays.one': '1 stay from Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} stays from Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/es/dawarich.ts b/shared/src/i18n/es/dawarich.ts
index 8a5aa2874..17555db93 100644
--- a/shared/src/i18n/es/dawarich.ts
+++ b/shared/src/i18n/es/dawarich.ts
@@ -175,6 +175,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'a {km} km',
'dawarich.bucket.rule': 'Un deseo cuenta como cumplido a menos de {meters} m y tras {minutes} minutos en el lugar.',
+ 'dawarich.journey.dayStays.one': '1 estancia de Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} estancias de Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/fr/dawarich.ts b/shared/src/i18n/fr/dawarich.ts
index 0c4612a55..fef3d0e81 100644
--- a/shared/src/i18n/fr/dawarich.ts
+++ b/shared/src/i18n/fr/dawarich.ts
@@ -177,6 +177,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'à {km} km',
'dawarich.bucket.rule': 'Une envie est atteinte à moins de {meters} m et après {minutes} minutes sur place.',
+ 'dawarich.journey.dayStays.one': '1 arrêt depuis Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} arrêts depuis Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/gr/dawarich.ts b/shared/src/i18n/gr/dawarich.ts
index a0f9d0767..5773befc5 100644
--- a/shared/src/i18n/gr/dawarich.ts
+++ b/shared/src/i18n/gr/dawarich.ts
@@ -178,6 +178,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} χλμ. μακριά',
'dawarich.bucket.rule': 'Μια επιθυμία μετράει ως εκπληρωμένη σε απόσταση έως {meters} μ. και μετά από {minutes} λεπτά στο σημείο.',
+ 'dawarich.journey.dayStays.one': '1 στάση από το Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} στάσεις από το Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/hu/dawarich.ts b/shared/src/i18n/hu/dawarich.ts
index a4d9c0269..1a41b1bff 100644
--- a/shared/src/i18n/hu/dawarich.ts
+++ b/shared/src/i18n/hu/dawarich.ts
@@ -176,6 +176,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km-re',
'dawarich.bucket.rule': 'Egy kívánság {meters} méteren belül és {minutes} perc helyszíni idő után számít teljesítettnek.',
+ 'dawarich.journey.dayStays.one': '1 tartózkodás a Dawarichból',
+ 'dawarich.journey.dayStays.other': '{count} tartózkodás a Dawarichból',
};
export default dawarich;
diff --git a/shared/src/i18n/id/dawarich.ts b/shared/src/i18n/id/dawarich.ts
index 3c3fbd380..33e4c4aad 100644
--- a/shared/src/i18n/id/dawarich.ts
+++ b/shared/src/i18n/id/dawarich.ts
@@ -175,6 +175,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km dari sana',
'dawarich.bucket.rule': 'Sebuah keinginan dianggap tercapai dalam radius {meters} m dan setelah {minutes} menit di lokasi.',
+ 'dawarich.journey.dayStays.one': '1 persinggahan dari Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} persinggahan dari Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/it/dawarich.ts b/shared/src/i18n/it/dawarich.ts
index 7194634df..b54bf27f1 100644
--- a/shared/src/i18n/it/dawarich.ts
+++ b/shared/src/i18n/it/dawarich.ts
@@ -177,6 +177,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'a {km} km',
'dawarich.bucket.rule': 'Un desiderio è raggiunto entro {meters} m e dopo {minutes} minuti sul posto.',
+ 'dawarich.journey.dayStays.one': '1 sosta da Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} soste da Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/ja/dawarich.ts b/shared/src/i18n/ja/dawarich.ts
index c14076f82..093ca4c16 100644
--- a/shared/src/i18n/ja/dawarich.ts
+++ b/shared/src/i18n/ja/dawarich.ts
@@ -178,6 +178,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km 先',
'dawarich.bucket.rule': '{meters} m 以内に {minutes} 分以上滞在すると、願いがかなったとみなします。',
+ 'dawarich.journey.dayStays.one': 'Dawarich の滞在 1 件',
+ 'dawarich.journey.dayStays.other': 'Dawarich の滞在 {count} 件',
};
export default dawarich;
diff --git a/shared/src/i18n/ko/dawarich.ts b/shared/src/i18n/ko/dawarich.ts
index 5a7de299d..eff2104dd 100644
--- a/shared/src/i18n/ko/dawarich.ts
+++ b/shared/src/i18n/ko/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km 거리',
'dawarich.bucket.rule': '{meters} m 이내에서 {minutes}분 이상 머무르면 소원을 이룬 것으로 봅니다.',
+ 'dawarich.journey.dayStays.one': 'Dawarich 체류 1곳',
+ 'dawarich.journey.dayStays.other': 'Dawarich 체류 {count}곳',
};
export default dawarich;
diff --git a/shared/src/i18n/nl/dawarich.ts b/shared/src/i18n/nl/dawarich.ts
index ae8595e4a..9790bfbfc 100644
--- a/shared/src/i18n/nl/dawarich.ts
+++ b/shared/src/i18n/nl/dawarich.ts
@@ -175,6 +175,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km verderop',
'dawarich.bucket.rule': 'Een wens telt als bereikt binnen {meters} m en na {minutes} minuten ter plaatse.',
+ 'dawarich.journey.dayStays.one': '1 stop van Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} stops van Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/pl/dawarich.ts b/shared/src/i18n/pl/dawarich.ts
index 3b1dfffd0..078a9c1be 100644
--- a/shared/src/i18n/pl/dawarich.ts
+++ b/shared/src/i18n/pl/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km stąd',
'dawarich.bucket.rule': 'Marzenie uznaje się za spełnione w promieniu {meters} m i po {minutes} minutach na miejscu.',
+ 'dawarich.journey.dayStays.one': '1 postój z Dawarich',
+ 'dawarich.journey.dayStays.other': 'Postoje z Dawarich: {count}',
};
export default dawarich;
diff --git a/shared/src/i18n/ru/dawarich.ts b/shared/src/i18n/ru/dawarich.ts
index 7668aed45..e28722fb0 100644
--- a/shared/src/i18n/ru/dawarich.ts
+++ b/shared/src/i18n/ru/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'в {km} км',
'dawarich.bucket.rule': 'Желание считается исполненным в пределах {meters} м и после {minutes} минут на месте.',
+ 'dawarich.journey.dayStays.one': '1 остановка из Dawarich',
+ 'dawarich.journey.dayStays.other': 'Остановки из Dawarich: {count}',
};
export default dawarich;
diff --git a/shared/src/i18n/sv/dawarich.ts b/shared/src/i18n/sv/dawarich.ts
index 3b223d381..f15bbe445 100644
--- a/shared/src/i18n/sv/dawarich.ts
+++ b/shared/src/i18n/sv/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km bort',
'dawarich.bucket.rule': 'En önskning räknas som uppfylld inom {meters} m och efter {minutes} minuter på plats.',
+ 'dawarich.journey.dayStays.one': '1 stopp från Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} stopp från Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/tr/dawarich.ts b/shared/src/i18n/tr/dawarich.ts
index 90572524a..78e59e83e 100644
--- a/shared/src/i18n/tr/dawarich.ts
+++ b/shared/src/i18n/tr/dawarich.ts
@@ -176,6 +176,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} km uzakta',
'dawarich.bucket.rule': 'Bir dilek {meters} m yakınlıkta ve yerinde {minutes} dakika sonra ulaşılmış sayılır.',
+ 'dawarich.journey.dayStays.one': "Dawarich'ten 1 durak",
+ 'dawarich.journey.dayStays.other': "Dawarich'ten {count} durak",
};
export default dawarich;
diff --git a/shared/src/i18n/uk/dawarich.ts b/shared/src/i18n/uk/dawarich.ts
index e782b68af..833654444 100644
--- a/shared/src/i18n/uk/dawarich.ts
+++ b/shared/src/i18n/uk/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'за {km} км',
'dawarich.bucket.rule': 'Бажання вважається здійсненим у межах {meters} м і після {minutes} хвилин на місці.',
+ 'dawarich.journey.dayStays.one': '1 зупинка з Dawarich',
+ 'dawarich.journey.dayStays.other': 'Зупинки з Dawarich: {count}',
};
export default dawarich;
diff --git a/shared/src/i18n/vi/dawarich.ts b/shared/src/i18n/vi/dawarich.ts
index 7e71521c6..c0319cf27 100644
--- a/shared/src/i18n/vi/dawarich.ts
+++ b/shared/src/i18n/vi/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': 'cách {km} km',
'dawarich.bucket.rule': 'Một điều ước được tính là đã đến khi trong vòng {meters} m và sau {minutes} phút tại chỗ.',
+ 'dawarich.journey.dayStays.one': '1 điểm dừng từ Dawarich',
+ 'dawarich.journey.dayStays.other': '{count} điểm dừng từ Dawarich',
};
export default dawarich;
diff --git a/shared/src/i18n/zh-TW/dawarich.ts b/shared/src/i18n/zh-TW/dawarich.ts
index 15193ca61..0cf112de1 100644
--- a/shared/src/i18n/zh-TW/dawarich.ts
+++ b/shared/src/i18n/zh-TW/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} 公里外',
'dawarich.bucket.rule': '在 {meters} 公尺內停留 {minutes} 分鐘以上,才算實現心願。',
+ 'dawarich.journey.dayStays.one': '來自 Dawarich 的 1 個停留',
+ 'dawarich.journey.dayStays.other': '來自 Dawarich 的 {count} 個停留',
};
export default dawarich;
diff --git a/shared/src/i18n/zh/dawarich.ts b/shared/src/i18n/zh/dawarich.ts
index 0ad930c11..0def059f4 100644
--- a/shared/src/i18n/zh/dawarich.ts
+++ b/shared/src/i18n/zh/dawarich.ts
@@ -173,6 +173,8 @@ const dawarich: TranslationStrings = {
'dawarich.bucket.kilometersAway': '{km} 公里外',
'dawarich.bucket.rule': '在 {meters} 米以内停留 {minutes} 分钟以上,才算实现心愿。',
+ 'dawarich.journey.dayStays.one': '来自 Dawarich 的 1 个停留',
+ 'dawarich.journey.dayStays.other': '来自 Dawarich 的 {count} 个停留',
};
export default dawarich;