feat(journey): set a journey's status by hand (#762)

This commit is contained in:
Maurice
2026-10-01 13:03:46 +02:00
parent 3063606f56
commit 477f41693d
39 changed files with 212 additions and 7 deletions
@@ -199,6 +199,22 @@ describe('JourneySettingsDialog', () => {
expect(onSaved).toHaveBeenCalledTimes(1)
})
it('FE-JRN-SETTINGS-762: sets the status by hand on the spot and back to automatic', async () => {
const user = userEvent.setup()
const { onRefresh } = mountDialog()
expect(screen.getByText('Follows the dates of the linked trips. Without a trip the journey stays a draft.')).toBeInTheDocument()
await user.click(screen.getByRole('button', { name: 'Live' }))
await waitFor(() => expect(updateJourney).toHaveBeenCalledWith(3, { status_override: 'live' }))
expect(onRefresh).toHaveBeenCalled()
updateJourney.mockClear()
mountDialog(buildJourney({ status_override: 'completed' }))
expect(screen.getAllByRole('button', { name: 'Completed' }).some(b => b.getAttribute('aria-pressed') === 'true')).toBe(true)
await user.click(screen.getAllByRole('button', { name: 'Automatic' })[1])
await waitFor(() => expect(updateJourney).toHaveBeenCalledWith(3, { status_override: null }))
})
it('FE-JRN-SETTINGS-011: restores an archived journey', async () => {
const user = userEvent.setup()
mountDialog(buildJourney({ status: 'archived' }))
@@ -8,7 +8,7 @@ import { useToast } from '../shared/Toast'
import ConfirmDialog from '../shared/ConfirmDialog'
import { Tooltip } from '../shared/Tooltip'
import { DeleteButton, DialogButton, DialogFooter, DialogHeader, DialogSection, DialogShell, DialogTile, FooterSpacer, NEUTRAL_TINT, fs } from '../shared/DialogShell'
import { AddRowButton, EditorField, INPUT } from '../shared/dialogParts'
import { AddRowButton, EditorField, INPUT, Segmented } from '../shared/dialogParts'
import JourneyShareSection from './JourneyShareSection'
import type { JourneyContributor, JourneyDetail } from '../../store/journeyStore'
import { pickGradient } from '../../pages/journeyDetail/JourneyDetailPage.helpers'
@@ -145,6 +145,23 @@ export function JourneySettingsDialog({ journey, onClose, onSaved, onOpenInvite,
}
}
// The state shown for the journey, set by hand (#762). Saved on the spot like
// the switches; 'auto' stores null and hands it back to the trip dates.
const [savingStatus, setSavingStatus] = useState(false)
const statusChoice = journey.status_override ?? 'auto'
const handleStatusChange = async (next: 'auto' | 'draft' | 'live' | 'completed') => {
if (next === statusChoice || savingStatus) return
setSavingStatus(true)
try {
await updateJourney(journey.id, { status_override: next === 'auto' ? null : next })
onRefresh()
} catch {
toast.error(t('journey.settings.saveFailed'))
} finally {
setSavingStatus(false)
}
}
const handleDelete = async () => {
try {
await deleteJourney(journey.id)
@@ -246,6 +263,27 @@ export function JourneySettingsDialog({ journey, onClose, onSaved, onOpenInvite,
/>
</EditorField>
{/* The journey's state, by hand or from the trips (#762) */}
<DialogSection label={t('journey.settings.status')}>
<div className={savingStatus ? 'opacity-60' : undefined}>
<Segmented<'auto' | 'draft' | 'live' | 'completed'>
label={t('journey.settings.status')}
value={statusChoice}
onChange={next => { void handleStatusChange(next) }}
fill
options={[
{ value: 'auto', label: t('journey.settings.statusAuto') },
{ value: 'draft', label: t('journey.status.draft') },
{ value: 'live', label: t('journey.frontpage.live') },
{ value: 'completed', label: t('journey.status.completed') },
]}
/>
</div>
<p className="m-0 mt-2 leading-normal text-content-faint" style={fs(11.5)}>
{t(statusChoice === 'auto' ? 'journey.settings.statusAutoHint' : 'journey.settings.statusManualHint')}
</p>
</DialogSection>
{/* Trip GPX tracks on the journey map (#2194) */}
<DialogSection label={t('journey.settings.tracks')}>
<div className={ROWS}>
+1 -1
View File
@@ -106,7 +106,7 @@ function JourneyDetailPageDesktop() {
: []
const sortedDates = [...new Set([...dayGroups.keys(), ...suggestionDates])]
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
const lifecycle = computeJourneyLifecycle(current.status, tripDateMin || null, tripDateMax || null)
const lifecycle = computeJourneyLifecycle(current.status, tripDateMin || null, tripDateMax || null, current.status_override)
const showMobileCombined = isMobile && view === 'timeline'
const showMobileGallery = isMobile && view === 'gallery'
+1 -1
View File
@@ -419,7 +419,7 @@ function JourneyCard({ journey, onClick }: { journey: Journey & { entry_count?:
const entryCount = j.entry_count ?? 0
const photoCount = j.photo_count ?? 0
const placeCount = j.place_count ?? 0
const lifecycle = computeJourneyLifecycle(j.status, j.trip_date_min, j.trip_date_max)
const lifecycle = computeJourneyLifecycle(j.status, j.trip_date_min, j.trip_date_max, j.status_override)
return (
<button
+2 -2
View File
@@ -58,7 +58,7 @@ export function useJourney() {
if (searchQuery.trim() || journeys.length === 0) return null
const live = journeys.find(j => {
const j2 = j as any
return computeJourneyLifecycle(j.status, j2.trip_date_min, j2.trip_date_max) === 'live'
return computeJourneyLifecycle(j.status, j2.trip_date_min, j2.trip_date_max, j.status_override) === 'live'
})
return live ?? journeys[0]
}, [journeys, searchQuery])
@@ -68,7 +68,7 @@ export function useJourney() {
const activeJourneyIsLive = useMemo(() => {
if (!activeJourney) return false
const j2 = activeJourney as any
return computeJourneyLifecycle(activeJourney.status, j2.trip_date_min, j2.trip_date_max) === 'live'
return computeJourneyLifecycle(activeJourney.status, j2.trip_date_min, j2.trip_date_max, activeJourney.status_override) === 'live'
}, [activeJourney])
const filteredJourneys = useMemo(() => {
+2
View File
@@ -12,6 +12,8 @@ export interface Journey {
cover_gradient?: string | null
cover_image?: string | null
status: 'draft' | 'active' | 'completed' | 'archived'
/** The state the owner set by hand (#762); null or absent follows the trip dates. */
status_override?: 'draft' | 'live' | 'completed' | null
/**
* Draw the GPX tracks of the journey's linked trips on its map (#2194).
* Off unless the owner asks for it — see the migration for why the default
+12
View File
@@ -89,3 +89,15 @@ describe('computeJourneyLifecycle — local today at the midnight window', () =>
expect(computeJourneyLifecycle('active', null, '2026-08-24')).toBe('completed') // ended yesterday
})
})
describe('status set by hand (#762)', () => {
it('wins over the trip dates and over having no trip, but not over archived', () => {
expect(computeJourneyLifecycle('active', null, null, 'live')).toBe('live')
expect(computeJourneyLifecycle('active', null, null, 'completed')).toBe('completed')
expect(computeJourneyLifecycle('active', '2000-01-01', '2000-01-02', 'draft')).toBe('draft')
expect(computeJourneyLifecycle('archived', null, null, 'live')).toBe('archived')
expect(computeJourneyLifecycle('active', null, null, null)).toBe('draft')
expect(computeJourneyLifecycle('active', null, null, 'bogus')).toBe('draft')
})
})
+5
View File
@@ -2,12 +2,17 @@ import { localIsoDate } from './localDate'
export type JourneyLifecycle = 'archived' | 'live' | 'upcoming' | 'completed' | 'draft'
export type JourneyStatusOverride = 'draft' | 'live' | 'completed'
export function computeJourneyLifecycle(
status: string,
tripDateMin: string | null | undefined,
tripDateMax: string | null | undefined,
/** The owner's own pick (#762); wins over the dates, never over archived. */
override?: string | null,
): JourneyLifecycle {
if (status === 'archived') return 'archived'
if (override === 'draft' || override === 'live' || override === 'completed') return override
if (tripDateMin && tripDateMax) {
const today = localIsoDate()
+9
View File
@@ -5421,6 +5421,15 @@ function runMigrations(db: Database.Database): void {
if (!has('quantity')) db.exec('ALTER TABLE packing_template_items ADD COLUMN quantity INTEGER NOT NULL DEFAULT 1');
if (!has('bag_name')) db.exec('ALTER TABLE packing_template_items ADD COLUMN bag_name TEXT');
},
/**
* A journey's state as its owner sets it (#762): draft, live or completed.
* NULL keeps the state derived from the linked trips' dates, which is what
* every journey had so far; a journey with no trip could only ever be a draft.
*/
() => {
const cols = db.prepare("SELECT name FROM pragma_table_info('journeys')").all() as { name: string }[];
if (!cols.some(c => c.name === 'status_override')) db.exec('ALTER TABLE journeys ADD COLUMN status_override TEXT');
},
];
if (currentVersion < migrations.length) {
@@ -351,6 +351,7 @@ export class JourneyDomainService {
cover_gradient: string;
cover_image: string;
status: string;
status_override: string | null;
show_trip_tracks: boolean | number;
show_verdict: boolean | number;
show_mood: boolean | number;
@@ -362,12 +363,15 @@ export class JourneyDomainService {
if (!this.isOwner(journeyId, userId)) return null;
const ALLOWED_STATUSES = ['draft', 'active', 'completed', 'archived'];
// null hands the state back to the trip dates (#762).
const ALLOWED_OVERRIDES: (string | null)[] = [null, 'draft', 'live', 'completed'];
const allowed = [
'title',
'subtitle',
'cover_gradient',
'cover_image',
'status',
'status_override',
'show_trip_tracks',
'show_verdict',
'show_mood',
@@ -381,6 +385,7 @@ export class JourneyDomainService {
for (const [key, val] of Object.entries(data)) {
if (val !== undefined && allowed.includes(key)) {
if (key === 'status' && !ALLOWED_STATUSES.includes(val as string)) continue;
if (key === 'status_override' && !ALLOWED_OVERRIDES.includes(val as string | null)) continue;
fields.push(`${key} = ?`);
values.push(BOOLEAN_FIELDS.has(key) ? (val ? 1 : 0) : val);
}
+3 -2
View File
@@ -241,12 +241,13 @@ export class JourneyMcp {
@Tool({
name: 'update_journey',
description: "Update an existing journey's title, subtitle, cover, or status. Owner only.",
description: "Update an existing journey's title, subtitle, cover, or status. Owner only. status_override sets the state shown for the journey (draft, live, completed) instead of deriving it from the linked trips' dates; null goes back to the dates.",
inputSchema: {
journeyId: z.number().int().positive(),
title: z.string().min(1).max(200).optional(),
subtitle: z.string().max(300).optional(),
status: z.enum(['draft', 'active', 'completed', 'archived']).optional(),
status_override: z.enum(['draft', 'live', 'completed']).nullable().optional().describe('Shown state set by hand, or null to follow the trip dates'),
show_verdict: z.boolean().optional().describe('Whether entries in this journey offer a pros/cons list'),
show_mood: z.boolean().optional().describe('Whether entries in this journey offer a mood'),
show_weather: z.boolean().optional().describe('Whether entries in this journey offer a weather note'),
@@ -257,7 +258,7 @@ export class JourneyMcp {
})
updateJourney(
{ journeyId, ...data }: {
journeyId: number; title?: string; subtitle?: string; status?: string;
journeyId: number; title?: string; subtitle?: string; status?: string; status_override?: string | null;
show_verdict?: boolean; show_mood?: boolean; show_weather?: boolean;
},
ctx: McpContext,
@@ -337,6 +337,15 @@ describe('updateJourney', () => {
expect(result!.title).toBe('Same');
});
it('JOURNEY-SVC-762: the owner sets the shown state by hand, null hands it back, anything else is ignored', () => {
const { user } = createUser(testDb);
const journey = createJourney(testDb, user.id);
expect(svc.updateJourney(journey.id, user.id, { status_override: 'live' })!.status_override).toBe('live');
expect(svc.updateJourney(journey.id, user.id, { status_override: 'upcoming' })!.status_override).toBe('live');
expect(svc.updateJourney(journey.id, user.id, { status_override: null })!.status_override).toBeNull();
});
it('JOURNEY-SVC-021b: accepts archived status', () => {
const { user } = createUser(testDb);
const journey = createJourney(testDb, user.id, { title: 'To Archive' });
+4
View File
@@ -224,6 +224,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'مسارات GPX',
'journey.settings.showTripTracks': 'إظهار جميع مسارات GPX للرحلات',
'journey.settings.showTripTracksHint': 'يرسم على الخريطة المسارات المسجَّلة من الرحلات المرتبطة.',
'journey.settings.status': 'الحالة',
'journey.settings.statusAuto': 'تلقائي',
'journey.settings.statusAutoHint': 'يتبع تواريخ الرحلات المرتبطة. بدون رحلة تبقى الرحلة مسودة.',
'journey.settings.statusManualHint': 'مضبوطة يدويًا. لن تغيرها تواريخ الرحلة حتى تعود إلى الوضع التلقائي.',
'journey.settings.delete': 'Delete', // en-fallback
'journey.settings.deleteJourney': 'Delete Journey', // en-fallback
'journey.settings.deleteMessage': 'Delete "{title}"? All entries and photos will be lost.', // en-fallback
+4
View File
@@ -249,6 +249,10 @@ const journey: TranslationStrings = {
'journey.settings.showTripTracks': 'Bütün səyahət GPX izlərini göstər',
'journey.settings.showTripTracksHint':
'Əlaqələndirilmiş səyahətlərdə qeydə alınmış marşrutları xəritədə göstərir.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Avtomatik',
'journey.settings.statusAutoHint': 'Bağlı səfərlərin tarixlərinə uyğunlaşır. Səfər olmadan jurnal qaralama qalır.',
'journey.settings.statusManualHint': 'Əllə təyin olunub. Avtomatikə qaytarana qədər səfər tarixləri onu dəyişmir.',
'journey.settings.endJourney': 'Səyahət gündəliyini arxivləşdir',
'journey.settings.reopenJourney': 'Səyahət gündəliyini bərpa et',
'journey.settings.archived': 'Səyahət gündəliyi arxivləşdirildi',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Trilhas GPX',
'journey.settings.showTripTracks': 'Mostrar todas as trilhas GPX das viagens',
'journey.settings.showTripTracksHint': 'Desenha no mapa as rotas gravadas das viagens vinculadas.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automático',
'journey.settings.statusAutoHint': 'Segue as datas das viagens vinculadas. Sem viagem, a jornada continua como rascunho.',
'journey.settings.statusManualHint': 'Definido manualmente. As datas da viagem não o alteram até você voltar para automático.',
'journey.settings.endJourney': 'Arquivar Jornada',
'journey.settings.reopenJourney': 'Restaurar Jornada',
'journey.settings.archived': 'Jornada arquivada',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Traces GPX',
'journey.settings.showTripTracks': 'Mostra totes les traces GPX dels viatges',
'journey.settings.showTripTracksHint': 'Dibuixa al mapa les rutes enregistrades dels viatges enllaçats.',
'journey.settings.status': 'Estat',
'journey.settings.statusAuto': 'Automàtic',
'journey.settings.statusAutoHint': 'Segueix les dates dels viatges vinculats. Sense viatge, el diari es queda com a esborrany.',
'journey.settings.statusManualHint': 'Definit a mà. Les dates del viatge ja no el canvien fins que tornis a automàtic.',
'journey.settings.endJourney': 'Arxiva el viatge',
'journey.settings.reopenJourney': 'Restaura el viatge',
'journey.settings.archived': 'Viatge arxivat',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Stopy GPX',
'journey.settings.showTripTracks': 'Zobrazit všechny GPX stopy z cest',
'journey.settings.showTripTracksHint': 'Vykreslí na mapě zaznamenané trasy z propojených cest.',
'journey.settings.status': 'Stav',
'journey.settings.statusAuto': 'Automaticky',
'journey.settings.statusAutoHint': 'Řídí se daty propojených výletů. Bez výletu zůstane deník konceptem.',
'journey.settings.statusManualHint': 'Nastaveno ručně. Data výletu ho nezmění, dokud nepřepnete zpět na automaticky.',
'journey.settings.endJourney': 'Archivovat cestu',
'journey.settings.reopenJourney': 'Obnovit cestu',
'journey.settings.archived': 'Cesta archivována',
+4
View File
@@ -202,6 +202,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-Tracks',
'journey.settings.showTripTracks': 'Alle GPX-Tracks der Reisen anzeigen',
'journey.settings.showTripTracksHint': 'Zeichnet die aufgezeichneten Routen der verknüpften Reisen auf die Karte.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automatisch',
'journey.settings.statusAutoHint': 'Richtet sich nach den Daten der verknüpften Trips. Ohne Trip bleibt die Journey ein Entwurf.',
'journey.settings.statusManualHint': 'Von Hand gesetzt. Die Trip-Daten ändern ihn nicht mehr, bis du wieder auf automatisch stellst.',
'journey.settings.endJourney': 'Reise archivieren',
'journey.settings.reopenJourney': 'Reise wiederherstellen',
'journey.settings.archived': 'Reise archiviert',
+4
View File
@@ -210,6 +210,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX Tracks',
'journey.settings.showTripTracks': 'Show all trip GPX tracks',
'journey.settings.showTripTracksHint': 'Draws the recorded routes from the linked trips on the map.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automatic',
'journey.settings.statusAutoHint': 'Follows the dates of the linked trips. Without a trip the journey stays a draft.',
'journey.settings.statusManualHint': 'Set by hand. The trip dates no longer change it until you switch back to automatic.',
'journey.settings.endJourney': 'Archive Journey',
'journey.settings.reopenJourney': 'Restore Journey',
'journey.settings.archived': 'Journey archived',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Rutas GPX',
'journey.settings.showTripTracks': 'Mostrar todas las rutas GPX de los viajes',
'journey.settings.showTripTracksHint': 'Dibuja en el mapa las rutas grabadas de los viajes vinculados.',
'journey.settings.status': 'Estado',
'journey.settings.statusAuto': 'Automático',
'journey.settings.statusAutoHint': 'Sigue las fechas de los viajes vinculados. Sin viaje, la travesía se queda como borrador.',
'journey.settings.statusManualHint': 'Definido a mano. Las fechas del viaje ya no lo cambian hasta que vuelvas a automático.',
'journey.settings.endJourney': 'Archivar viaje',
'journey.settings.reopenJourney': 'Restaurar viaje',
'journey.settings.archived': 'Viaje archivado',
+4
View File
@@ -212,6 +212,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-rajad',
'journey.settings.showTripTracks': 'Näita kõiki reiside GPX-radu',
'journey.settings.showTripTracksHint': 'Kuvab kaardil seotud reiside salvestatud teekonnad.',
'journey.settings.status': 'Olek',
'journey.settings.statusAuto': 'Automaatne',
'journey.settings.statusAutoHint': 'Järgib seotud reiside kuupäevi. Ilma reisita jääb teekond mustandiks.',
'journey.settings.statusManualHint': 'Määratud käsitsi. Reisi kuupäevad ei muuda seda enam, kuni lülitad tagasi automaatsele.',
'journey.settings.endJourney': 'Arhiveeri reisilugu',
'journey.settings.reopenJourney': 'Taasta reisilugu',
'journey.settings.archived': 'Reisilugu arhiveeritud',
+4
View File
@@ -199,6 +199,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Traces GPX',
'journey.settings.showTripTracks': 'Afficher toutes les traces GPX des voyages',
'journey.settings.showTripTracksHint': 'Trace sur la carte les itinéraires enregistrés des voyages liés.',
'journey.settings.status': 'Statut',
'journey.settings.statusAuto': 'Automatique',
'journey.settings.statusAutoHint': 'Suit les dates des voyages liés. Sans voyage, le carnet reste un brouillon.',
'journey.settings.statusManualHint': 'Défini à la main. Les dates du voyage ne le changent plus tant que vous ne repassez pas en automatique.',
'journey.settings.endJourney': 'Archiver le journal',
'journey.settings.reopenJourney': 'Restaurer le journal',
'journey.settings.archived': 'Journal archivé',
+4
View File
@@ -205,6 +205,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Διαδρομές GPX',
'journey.settings.showTripTracks': 'Εμφάνιση όλων των διαδρομών GPX των ταξιδιών',
'journey.settings.showTripTracksHint': 'Σχεδιάζει στον χάρτη τις καταγεγραμμένες διαδρομές από τα συνδεδεμένα ταξίδια.',
'journey.settings.status': 'Κατάσταση',
'journey.settings.statusAuto': 'Αυτόματα',
'journey.settings.statusAutoHint': 'Ακολουθεί τις ημερομηνίες των συνδεδεμένων ταξιδιών. Χωρίς ταξίδι, το ημερολόγιο μένει πρόχειρο.',
'journey.settings.statusManualHint': 'Ορισμένη χειροκίνητα. Οι ημερομηνίες του ταξιδιού δεν την αλλάζουν μέχρι να επιστρέψετε στο αυτόματο.',
'journey.settings.endJourney': 'Αρχειοθέτηση Ταξιδιού',
'journey.settings.reopenJourney': 'Επαναφορά Ταξιδιού',
'journey.settings.archived': 'Το ταξίδι αρχειοθετήθηκε',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-nyomvonalak',
'journey.settings.showTripTracks': 'Az utazások összes GPX-nyomvonalának megjelenítése',
'journey.settings.showTripTracksHint': 'A kapcsolt utazások rögzített útvonalait rajzolja a térképre.',
'journey.settings.status': 'Állapot',
'journey.settings.statusAuto': 'Automatikus',
'journey.settings.statusAutoHint': 'A kapcsolt utak dátumait követi. Út nélkül a napló piszkozat marad.',
'journey.settings.statusManualHint': 'Kézzel beállítva. Az út dátumai nem változtatják meg, amíg vissza nem váltasz automatikusra.',
'journey.settings.endJourney': 'Út archiválása',
'journey.settings.reopenJourney': 'Út visszaállítása',
'journey.settings.archived': 'Út archiválva',
+4
View File
@@ -197,6 +197,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Jalur GPX',
'journey.settings.showTripTracks': 'Tampilkan semua jalur GPX perjalanan',
'journey.settings.showTripTracksHint': 'Menggambar rute terekam dari perjalanan yang tertaut pada peta.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Otomatis',
'journey.settings.statusAutoHint': 'Mengikuti tanggal perjalanan yang ditautkan. Tanpa perjalanan, jurnal tetap berupa draf.',
'journey.settings.statusManualHint': 'Diatur manual. Tanggal perjalanan tidak lagi mengubahnya sampai kamu kembali ke otomatis.',
'journey.settings.endJourney': 'Arsipkan Perjalanan',
'journey.settings.reopenJourney': 'Pulihkan Perjalanan',
'journey.settings.archived': 'Perjalanan diarsipkan',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Tracce GPX',
'journey.settings.showTripTracks': 'Mostra tutte le tracce GPX dei viaggi',
'journey.settings.showTripTracksHint': 'Disegna sulla mappa i percorsi registrati dei viaggi collegati.',
'journey.settings.status': 'Stato',
'journey.settings.statusAuto': 'Automatico',
'journey.settings.statusAutoHint': 'Segue le date dei viaggi collegati. Senza viaggio il diario resta una bozza.',
'journey.settings.statusManualHint': 'Impostato a mano. Le date del viaggio non lo cambiano più finché non torni ad automatico.',
'journey.settings.endJourney': 'Archivia il viaggio',
'journey.settings.reopenJourney': 'Ripristina il viaggio',
'journey.settings.archived': 'Viaggio archiviato',
+4
View File
@@ -200,6 +200,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPXトラック',
'journey.settings.showTripTracks': '旅行のGPXトラックをすべて表示',
'journey.settings.showTripTracksHint': 'リンクされた旅行の記録済みルートを地図に描画します。',
'journey.settings.status': 'ステータス',
'journey.settings.statusAuto': '自動',
'journey.settings.statusAutoHint': 'リンクした旅行の日付に従います。旅行がない場合は下書きのままです。',
'journey.settings.statusManualHint': '手動で設定されています。自動に戻すまで旅行の日付では変わりません。',
'journey.settings.endJourney': '日記をアーカイブ',
'journey.settings.reopenJourney': '日記を復元',
'journey.settings.archived': '日記をアーカイブしました',
+4
View File
@@ -199,6 +199,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX 트랙',
'journey.settings.showTripTracks': '여행의 모든 GPX 트랙 표시',
'journey.settings.showTripTracksHint': '연결된 여행의 기록된 경로를 지도에 그립니다.',
'journey.settings.status': '상태',
'journey.settings.statusAuto': '자동',
'journey.settings.statusAutoHint': '연결된 여행의 날짜를 따릅니다. 여행이 없으면 초안으로 남습니다.',
'journey.settings.statusManualHint': '직접 설정했습니다. 자동으로 되돌릴 때까지 여행 날짜로 바뀌지 않습니다.',
'journey.settings.endJourney': 'Journey 보관',
'journey.settings.reopenJourney': 'Journey 복원',
'journey.settings.archived': 'Journey가 보관되었습니다',
+4
View File
@@ -199,6 +199,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-tracks',
'journey.settings.showTripTracks': 'Alle GPX-tracks van reizen tonen',
'journey.settings.showTripTracksHint': 'Tekent de opgenomen routes van de gekoppelde reizen op de kaart.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automatisch',
'journey.settings.statusAutoHint': 'Volgt de data van de gekoppelde trips. Zonder trip blijft de journey een concept.',
'journey.settings.statusManualHint': 'Handmatig ingesteld. De tripdata veranderen het niet meer tot je terugzet op automatisch.',
'journey.settings.endJourney': 'Reis archiveren',
'journey.settings.reopenJourney': 'Reis herstellen',
'journey.settings.archived': 'Reis gearchiveerd',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Ślady GPX',
'journey.settings.showTripTracks': 'Pokaż wszystkie ślady GPX z podróży',
'journey.settings.showTripTracksHint': 'Rysuje na mapie zapisane trasy z powiązanych podróży.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automatycznie',
'journey.settings.statusAutoHint': 'Zależy od dat powiązanych podróży. Bez podróży dziennik pozostaje szkicem.',
'journey.settings.statusManualHint': 'Ustawiony ręcznie. Daty podróży go nie zmienią, dopóki nie wrócisz do trybu automatycznego.',
'journey.settings.endJourney': 'Archiwizuj podróż',
'journey.settings.reopenJourney': 'Przywróć podróż',
'journey.settings.archived': 'Podróż zarchiwizowana',
+4
View File
@@ -198,6 +198,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-треки',
'journey.settings.showTripTracks': 'Показывать все GPX-треки поездок',
'journey.settings.showTripTracksHint': 'Рисует на карте записанные маршруты из связанных поездок.',
'journey.settings.status': 'Статус',
'journey.settings.statusAuto': 'Автоматически',
'journey.settings.statusAutoHint': 'Следует датам связанных поездок. Без поездки журнал остаётся черновиком.',
'journey.settings.statusManualHint': 'Задан вручную. Даты поездки больше не меняют его, пока вы не вернёте автоматический режим.',
'journey.settings.endJourney': 'Архивировать путешествие',
'journey.settings.reopenJourney': 'Восстановить путешествие',
'journey.settings.archived': 'Путешествие архивировано',
+4
View File
@@ -210,6 +210,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Stopy GPX',
'journey.settings.showTripTracks': 'Zobraziť všetky GPX stopy z ciest',
'journey.settings.showTripTracksHint': 'Vykreslí na mape zaznamenané trasy z prepojených ciest.',
'journey.settings.status': 'Stav',
'journey.settings.statusAuto': 'Automaticky',
'journey.settings.statusAutoHint': 'Riadi sa dátumami prepojených výletov. Bez výletu zostane denník konceptom.',
'journey.settings.statusManualHint': 'Nastavené ručne. Dátumy výletu ho nezmenia, kým neprepnete späť na automaticky.',
'journey.settings.endJourney': 'Archivovať cestu',
'journey.settings.reopenJourney': 'Obnoviť cestu',
'journey.settings.archived': 'Cesta archivovaná',
+4
View File
@@ -203,6 +203,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-spår',
'journey.settings.showTripTracks': 'Visa alla GPX-spår från resor',
'journey.settings.showTripTracksHint': 'Ritar de inspelade rutterna från de länkade resorna på kartan.',
'journey.settings.status': 'Status',
'journey.settings.statusAuto': 'Automatiskt',
'journey.settings.statusAutoHint': 'Följer datumen för de länkade resorna. Utan resa förblir resedagboken ett utkast.',
'journey.settings.statusManualHint': 'Satt för hand. Resans datum ändrar det inte längre förrän du växlar tillbaka till automatiskt.',
'journey.settings.endJourney': 'Arkivera Journey',
'journey.settings.reopenJourney': 'Återställ Journey',
'journey.settings.archived': 'Journey arkiverad',
+4
View File
@@ -210,6 +210,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': "เส้นทาง GPX",
'journey.settings.showTripTracks': "แสดงเส้นทาง GPX ของการเดินทางทั้งหมด",
'journey.settings.showTripTracksHint': "วาดเส้นทางที่บันทึกไว้จากการเดินทางที่เชื่อมโยงบนแผนที่",
'journey.settings.status': 'สถานะ',
'journey.settings.statusAuto': 'อัตโนมัติ',
'journey.settings.statusAutoHint': 'ตามวันที่ของทริปที่เชื่อมไว้ หากไม่มีทริป บันทึกจะเป็นฉบับร่าง',
'journey.settings.statusManualHint': 'ตั้งเอง วันที่ของทริปจะไม่เปลี่ยนสถานะนี้จนกว่าจะกลับเป็นอัตโนมัติ',
'journey.settings.endJourney': "ปิดการเดินทาง",
'journey.settings.reopenJourney': "เปิดการเดินทางอีกครั้ง",
'journey.settings.archived': "เก็บถาวรการเดินทางแล้ว",
+4
View File
@@ -200,6 +200,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX İzleri',
'journey.settings.showTripTracks': 'Tüm gezi GPX izlerini göster',
'journey.settings.showTripTracksHint': 'Bağlı gezilerdeki kayıtlı rotaları haritaya çizer.',
'journey.settings.status': 'Durum',
'journey.settings.statusAuto': 'Otomatik',
'journey.settings.statusAutoHint': 'Bağlı gezilerin tarihlerini izler. Gezi olmadan günlük taslak kalır.',
'journey.settings.statusManualHint': 'Elle ayarlandı. Otomatiğe dönene kadar gezi tarihleri bunu değiştirmez.',
'journey.settings.endJourney': "Journey'i Arşivle",
'journey.settings.reopenJourney': "Journey'i geri aç",
'journey.settings.archived': 'Journey arşivlendi',
+4
View File
@@ -200,6 +200,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX-треки',
'journey.settings.showTripTracks': 'Показувати всі GPX-треки подорожей',
'journey.settings.showTripTracksHint': 'Малює на карті записані маршрути зі зв’язаних подорожей.',
'journey.settings.status': 'Статус',
'journey.settings.statusAuto': 'Автоматично',
'journey.settings.statusAutoHint': "Залежить від дат пов'язаних поїздок. Без поїздки журнал лишається чернеткою.",
'journey.settings.statusManualHint': 'Встановлено вручну. Дати поїздки більше не змінюють його, доки не повернете автоматичний режим.',
'journey.settings.endJourney': 'Архівувати подорож',
'journey.settings.reopenJourney': 'Відновити подорож',
'journey.settings.archived': 'Подорож архівовано',
+4
View File
@@ -203,6 +203,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'Tuyến GPX',
'journey.settings.showTripTracks': 'Hiện tất cả tuyến GPX của chuyến đi',
'journey.settings.showTripTracksHint': 'Vẽ lên bản đồ các tuyến đường đã ghi từ những chuyến đi được liên kết.',
'journey.settings.status': 'Trạng thái',
'journey.settings.statusAuto': 'Tự động',
'journey.settings.statusAutoHint': 'Theo ngày của các chuyến đi đã liên kết. Không có chuyến đi thì nhật ký vẫn là bản nháp.',
'journey.settings.statusManualHint': 'Đặt thủ công. Ngày của chuyến đi sẽ không đổi nó nữa cho đến khi bạn chuyển lại tự động.',
'journey.settings.endJourney': 'Hành trình lưu trữ',
'journey.settings.reopenJourney': 'Khôi phục hành trình',
'journey.settings.archived': 'Đã lưu trữ hành trình',
+4
View File
@@ -196,6 +196,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX 軌跡',
'journey.settings.showTripTracks': '顯示所有行程的 GPX 軌跡',
'journey.settings.showTripTracksHint': '在地圖上繪製關聯行程中的已記錄路線。',
'journey.settings.status': '狀態',
'journey.settings.statusAuto': '自動',
'journey.settings.statusAutoHint': '跟隨連結行程的日期。沒有行程時,旅記維持為草稿。',
'journey.settings.statusManualHint': '已手動設定。在切回自動之前,行程日期不會再改變它。',
'journey.settings.endJourney': '封存旅程',
'journey.settings.reopenJourney': '還原旅程',
'journey.settings.archived': '旅程已封存',
+4
View File
@@ -196,6 +196,10 @@ const journey: TranslationStrings = {
'journey.settings.tracks': 'GPX 轨迹',
'journey.settings.showTripTracks': '显示所有行程的 GPX 轨迹',
'journey.settings.showTripTracksHint': '在地图上绘制关联行程中的已记录路线。',
'journey.settings.status': '状态',
'journey.settings.statusAuto': '自动',
'journey.settings.statusAutoHint': '跟随关联行程的日期。没有行程时,旅记保持为草稿。',
'journey.settings.statusManualHint': '已手动设置。在切回自动之前,行程日期不会再改变它。',
'journey.settings.endJourney': '归档旅程',
'journey.settings.reopenJourney': '恢复旅程',
'journey.settings.archived': '旅程已归档',