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 ( +
+ + + {open && ( +
+ {suggestions.map(suggestion => ( + onAccept(suggestion, target)} + onDismiss={() => onDismiss(suggestion)} + /> + ))} +
+ )} +
+ ) +} 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;