From 532010aa790d7eb5f0f28896d2d47ea63ccc107b Mon Sep 17 00:00:00 2001 From: Maurice Date: Sun, 18 Oct 2026 22:04:41 +0200 Subject: [PATCH] feat(journey): the journal settings list who a linked trip lets in Under the contributors, the journey settings on desktop and phone get a section of their own, Through trips, with everyone a trip's journal link lets in, their role and the trip they come through. It is read only there, since the trip's settings manage it, and it leaves out whoever is a contributor already. getJourneyFull answers it as trip_access. --- .../JourneyDetailPageSettingsDialog.test.tsx | 13 +++++++ .../JourneyDetailPageSettingsDialog.tsx | 33 ++++++++++++++++- .../screens/journey/MJourneySettingsSheet.tsx | 25 ++++++++++--- client/src/store/journeyStore.ts | 12 +++++++ .../journey/MJourneySettingsSheet.test.tsx | 11 ++++++ .../JourneyContributors.repository.ts | 36 ++++++++++++++++++- .../nest/journey/journey-domain.service.ts | 11 +++--- .../TripJournalLinks.repository.test.ts | 17 +++++++++ shared/src/i18n/ar/journey.ts | 3 ++ shared/src/i18n/az/journey.ts | 4 +++ shared/src/i18n/br/journey.ts | 4 +++ shared/src/i18n/ca/journey.ts | 4 +++ shared/src/i18n/cs/journey.ts | 4 +++ shared/src/i18n/de/journey.ts | 4 +++ shared/src/i18n/en/journey.ts | 4 +++ shared/src/i18n/es/journey.ts | 4 +++ shared/src/i18n/et/journey.ts | 4 +++ shared/src/i18n/fr/journey.ts | 4 +++ shared/src/i18n/gr/journey.ts | 4 +++ shared/src/i18n/hu/journey.ts | 4 +++ shared/src/i18n/id/journey.ts | 4 +++ shared/src/i18n/it/journey.ts | 4 +++ shared/src/i18n/ja/journey.ts | 3 ++ shared/src/i18n/ko/journey.ts | 3 ++ shared/src/i18n/nl/journey.ts | 4 +++ shared/src/i18n/pl/journey.ts | 4 +++ shared/src/i18n/ru/journey.ts | 4 +++ shared/src/i18n/sk/journey.ts | 4 +++ shared/src/i18n/sv/journey.ts | 4 +++ shared/src/i18n/th/journey.ts | 3 ++ shared/src/i18n/tr/journey.ts | 4 +++ shared/src/i18n/uk/journey.ts | 4 +++ shared/src/i18n/vi/journey.ts | 4 +++ shared/src/i18n/zh-TW/journey.ts | 3 ++ shared/src/i18n/zh/journey.ts | 3 ++ 35 files changed, 248 insertions(+), 12 deletions(-) diff --git a/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx b/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx index 365654835..3adb569c9 100644 --- a/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx +++ b/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx @@ -98,6 +98,19 @@ describe('JourneySettingsDialog', () => { await screen.findByRole('button', { name: /create share link/i }) }) + it('FE-JRN-SETTINGS-2683: lists the people a linked trip lets in under their own heading, and nothing without', () => { + const { unmount } = mountDialog() + expect(screen.queryByText('Through trips')).not.toBeInTheDocument() + unmount() + + mountDialog(buildJourney({ + trip_access: [{ user_id: 7, role: 'viewer', username: 'lena', avatar: null, trip_id: 5, trip_title: 'Italy Trip' }], + })) + expect(screen.getByText('Through trips')).toBeInTheDocument() + expect(screen.getByText('lena')).toBeInTheDocument() + expect(screen.getByText('via Italy Trip')).toBeInTheDocument() + }) + it('FE-JRN-SETTINGS-002: saves the edited title and subtitle', async () => { const user = userEvent.setup() const { onSaved } = mountDialog() diff --git a/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx b/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx index 0439a5f7c..9036172b7 100644 --- a/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx +++ b/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx @@ -7,7 +7,7 @@ import { DeleteButton, DialogButton, DialogFooter, DialogHeader, DialogSection, import { AddRowButton, EditorField, INPUT, Segmented } from '../shared/dialogParts' import JourneyShareSection from './JourneyShareSection' import { useJourneySettings } from './useJourneySettings' -import type { JourneyContributor, JourneyDetail } from '../../store/journeyStore' +import type { JourneyContributor, JourneyDetail, JourneyTripAccess } from '../../store/journeyStore' import { pickGradient } from '../../pages/journeyDetail/JourneyDetailPage.helpers' import { AddTripDialog } from './JourneyDetailPageAddTripDialog' import ToggleSwitch from '../Settings/ToggleSwitch' @@ -277,6 +277,8 @@ export function JourneySettingsDialog({ journey, onClose, onSaved, onOpenInvite, {t('journey.contributors.invite')} + + @@ -324,3 +326,32 @@ export function JourneySettingsDialog({ journey, onClose, onSaved, onOpenInvite, ) } + +/** + * Who a trip's linked journal lets in (#2683), under its own heading below the + * contributors: shown here, but managed in that trip's settings, so read only. + */ +function TripAccessSection({ access, roleLabel }: { + access: JourneyTripAccess[] | undefined + roleLabel: (role: JourneyContributor['role']) => string +}) { + const { t } = useTranslation() + if (!access?.length) return null + return ( + +

{t('journey.contributors.viaTripsHint')}

+
+ {access.map(a => ( +
+ +
+
{a.username}
+
{t('journey.contributors.viaTrip', { trip: a.trip_title })}
+
+ {roleLabel(a.role)} +
+ ))} +
+
+ ) +} diff --git a/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx b/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx index be3774e48..fe2f56f12 100644 --- a/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx +++ b/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx @@ -1,8 +1,5 @@ import { useRef, useState } from 'react' -import { - X, Image, Plus, Trash2, UserPlus, Link as LinkIcon, - List, Grid3x3, MapPin, Route, Archive, ArchiveRestore, Undo2, -} from 'lucide-react' +import { X, Image, Plus, Trash2, UserPlus, Link as LinkIcon, List, Grid3x3, MapPin, Route, Archive, ArchiveRestore, Undo2, Link2 } from 'lucide-react' import MSheet from '../../components/MSheet' import MIconBtn from '../../components/MIconBtn' import MToggle from '../../components/MToggle' @@ -237,6 +234,26 @@ export default function MJourneySettingsSheet({ {t('journey.contributors.invite')} + {/* Through a trip's linked journal (#2683): shown, but changed in that trip. */} + {!!journey.trip_access?.length && ( + <> +
{t('journey.contributors.viaTrips')}
+

{t('journey.contributors.viaTripsHint')}

+ {journey.trip_access.map(a => ( +
+ + + {a.username} + {t('journey.contributors.viaTrip', { trip: a.trip_title })} + + + {a.role} + +
+ ))} + + )} + {/* Public share */}
{t('journey.share.publicShare')}
{!shareLink ? ( diff --git a/client/src/store/journeyStore.ts b/client/src/store/journeyStore.ts index 1faa1b1c2..9b44f78a4 100644 --- a/client/src/store/journeyStore.ts +++ b/client/src/store/journeyStore.ts @@ -141,11 +141,23 @@ export interface JourneyContributor { avatar?: string | null } +/** Someone a trip's linked journal lets in, with the trip they come through (#2683). */ +export interface JourneyTripAccess { + user_id: number + role: 'editor' | 'viewer' + username: string + avatar?: string | null + trip_id: number + trip_title: string +} + export interface JourneyDetail extends Journey { entries: JourneyEntry[] gallery: GalleryPhoto[] trips: JourneyTrip[] contributors: JourneyContributor[] + /** Who the trips' journal links let in besides the contributors, managed in those trips. */ + trip_access?: JourneyTripAccess[] stats: { entries: number; photos: number; places: number } hide_skeletons?: boolean /** How many suggestions were waved away one at a time, so the settings sheet can offer them back. */ diff --git a/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx b/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx index b76732601..41af7234a 100644 --- a/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx +++ b/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx @@ -89,6 +89,17 @@ describe('MJourneySettingsSheet', () => { expect(screen.getByText('8 places')).toBeInTheDocument(); }); + it('FE-MOB-JSET-2683: lists the people a linked trip lets in, and nothing without', async () => { + const { unmount } = setup(); + expect(screen.queryByText('Through trips')).not.toBeInTheDocument(); + unmount(); + + setup({ trip_access: [{ user_id: 7, role: 'editor', username: 'lena', avatar: null, trip_id: 3, trip_title: 'Tokyo trip' }] }); + expect(await screen.findByText('Through trips')).toBeInTheDocument(); + expect(screen.getByText('lena')).toBeInTheDocument(); + expect(screen.getByText('via Tokyo trip')).toBeInTheDocument(); + }); + it('FE-MOB-JSET-002: shows the empty hint when no trip is linked', async () => { setup({ trips: [] }); expect(await screen.findByText('No trips linked')).toBeInTheDocument(); diff --git a/server/src/db/repositories/JourneyContributors.repository.ts b/server/src/db/repositories/JourneyContributors.repository.ts index 11d30a4ee..1942da289 100644 --- a/server/src/db/repositories/JourneyContributors.repository.ts +++ b/server/src/db/repositories/JourneyContributors.repository.ts @@ -1,6 +1,12 @@ import type { JourneyContributors } from '../entities/JourneyContributors.entity'; import type { DB } from '../kysely/db'; -import { readLinkHideSkeletons, readLinkRole, type TripJournalLinkKyselyDB } from './TripJournalLinks.repository'; +import { + linkReach, + readLinkHideSkeletons, + readLinkRole, + type TripJournalLinkKyselyDB, + type TripJournalLinkRole, +} from './TripJournalLinks.repository'; import { TrekRepository } from './_shared/trek-repository'; /** JG18's contributor-list row (`getJourneyFull`) — the junction plus the joined username/avatar. */ @@ -16,6 +22,16 @@ export interface JourneyContributorListRow { /** The `journey_contributors`/`users` tables {@link JourneyContributorsRepository.listForJourney} reads. */ type JourneyContributorListKyselyDB = Pick; +/** Someone a trip's journal link lets in, with the trip they come through (#2683). */ +export interface JourneyTripAccessRow { + user_id: number; + role: TripJournalLinkRole; + username: string; + avatar: string | null; + trip_id: number; + trip_title: string; +} + /** The table the access reads below take a person's own contributor row from. */ type JourneyContributorRowKyselyDB = Pick; @@ -79,6 +95,24 @@ export class JourneyContributorsRepository extends TrekRepository { + const direct = new Set((await this.listForJourney(journeyId)).map((c) => c.user_id)); + const rows = await linkReach(this.kysely()) + .innerJoin('users as u', 'u.id', 'm.user_id') + .select(['m.user_id', 'm.role', 'u.username', 'u.avatar', 't.id as trip_id', 't.title as trip_title']) + .where('l.journey_id', '=', journeyId) + .orderBy('u.username', 'asc') + .execute(); + return rows + .filter((r) => !direct.has(r.user_id)) + .map((r) => ({ ...r, role: r.role === 'editor' ? 'editor' : 'viewer' })); + } + /** JG18 — `getJourneyFull`'s contributor list, joined to `users` for `username`/`avatar` (`avatar_url` is computed in the SERVICE, unchanged). */ async listForJourney(journeyId: number): Promise { const rows = await this.kysely() diff --git a/server/src/nest/journey/journey-domain.service.ts b/server/src/nest/journey/journey-domain.service.ts index d8a3485f0..752dbfe46 100644 --- a/server/src/nest/journey/journey-domain.service.ts +++ b/server/src/nest/journey/journey-domain.service.ts @@ -270,12 +270,10 @@ export class JourneyDomainService { // linked trips (JG17) const trips = await this.journeyTripsRepo.listForJourney(journeyId); - // contributors (JG18) - const contributorsRaw = await this.contributorsRepo.listForJourney(journeyId); - const contributors = contributorsRaw.map((c) => ({ - ...c, - avatar_url: avatarUrl(c), - })); + const withAvatar = (rows: R[]) => rows.map((r) => ({ ...r, avatar_url: avatarUrl(r) })); + const contributors = withAvatar(await this.contributorsRepo.listForJourney(journeyId)); // JG18 + // Who a trip's journal link lets in besides them (#2683), shown apart in the settings. + const tripAccess = withAvatar(await this.contributorsRepo.listTripAccessForJourney(journeyId)); // stats const entryCount = entries.filter((e) => e.type === 'entry').length; @@ -306,6 +304,7 @@ export class JourneyDomainService { gallery, trips, contributors, + trip_access: tripAccess, stats: { entries: entryCount, photos: photoCount, places: places.length }, hide_skeletons: hideSkeletons, // What the eye toggle cannot say: how much was waved away one at a time, and diff --git a/server/tests/unit/db/repositories/TripJournalLinks.repository.test.ts b/server/tests/unit/db/repositories/TripJournalLinks.repository.test.ts index 1c80a2a36..28e01207e 100644 --- a/server/tests/unit/db/repositories/TripJournalLinks.repository.test.ts +++ b/server/tests/unit/db/repositories/TripJournalLinks.repository.test.ts @@ -171,4 +171,21 @@ describe('TripJournalLinksRepository', () => { expect(await links.findForTrip(s.trip.id)).toBeNull(); expect(await links.listMembers(s.trip.id)).toEqual([]); }); + it('TJLREPO-008: the journal lists who the links let in, per trip, apart from its contributors', async () => { + const s = await scene(); + await links.upsertLink(s.trip.id, s.journal.id, s.owner.id, 1); + await links.replaceMembers( + s.trip.id, + [ + { user_id: s.tom.id, role: 'editor' }, + { user_id: s.lena.id, role: 'viewer' }, + ], + 1, + ); + await addJourneyContributor(t, s.journal.id, s.tom.id, 'viewer'); + + const access = await contributors.listTripAccessForJourney(s.journal.id); + expect(access.map((a) => [a.username, a.role, a.trip_id])).toEqual([['Lena', 'viewer', s.trip.id]]); + expect(access[0]?.trip_title).toBe(s.trip.title); + }); }); diff --git a/shared/src/i18n/ar/journey.ts b/shared/src/i18n/ar/journey.ts index 624d6af8c..069b80e28 100644 --- a/shared/src/i18n/ar/journey.ts +++ b/shared/src/i18n/ar/journey.ts @@ -241,6 +241,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'عبر الرحلات', + 'journey.contributors.viaTripsHint': 'يمكنهم فتح هذه اليوميات لأن رحلة ترتبط بها. غيّر ذلك من إعدادات الرحلة.', + 'journey.contributors.viaTrip': 'عبر {trip}', 'journey.share.publicShare': 'Public Share', // en-fallback 'journey.share.createLink': 'Create share link', // en-fallback 'journey.share.linkCreated': 'Share link created', // en-fallback diff --git a/shared/src/i18n/az/journey.ts b/shared/src/i18n/az/journey.ts index f792dcdae..f6f855de0 100644 --- a/shared/src/i18n/az/journey.ts +++ b/shared/src/i18n/az/journey.ts @@ -206,6 +206,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': '{username} bu səyahət gündəliyindən çıxarılsın?', 'journey.contributors.removed': 'İştirakçı çıxarıldı', 'journey.contributors.removeFailed': 'İştirakçını çıxarmaq mümkün olmadı', + 'journey.contributors.viaTrips': 'Səyahətlər vasitəsilə', + 'journey.contributors.viaTripsHint': + 'Bu gündəliyi aça bilirlər, çünki bir səyahət onu bağlayır. Bunu səyahətin parametrlərində dəyişin.', + 'journey.contributors.viaTrip': '{trip} vasitəsilə', 'journey.share.publicShare': 'İctimai paylaşım', 'journey.share.createLink': 'Paylaşım linki yarat', diff --git a/shared/src/i18n/br/journey.ts b/shared/src/i18n/br/journey.ts index c6cd13f08..acc2ccd59 100644 --- a/shared/src/i18n/br/journey.ts +++ b/shared/src/i18n/br/journey.ts @@ -265,6 +265,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Por meio de viagens', + 'journey.contributors.viaTripsHint': + 'Podem abrir este diário porque uma viagem o vincula. Altere isso nas configurações da viagem.', + 'journey.contributors.viaTrip': 'por {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/ca/journey.ts b/shared/src/i18n/ca/journey.ts index 1511fc76e..fcf942aa6 100644 --- a/shared/src/i18n/ca/journey.ts +++ b/shared/src/i18n/ca/journey.ts @@ -265,6 +265,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': "Vols eliminar {username} d'aquesta travesia?", 'journey.contributors.removed': 'Col·laborador eliminat', 'journey.contributors.removeFailed': "No s'ha pogut eliminar el col·laborador", + 'journey.contributors.viaTrips': 'A través de viatges', + 'journey.contributors.viaTripsHint': + 'Poden obrir aquest diari perquè un viatge el vincula. Canvia-ho a la configuració del viatge.', + 'journey.contributors.viaTrip': 'a través de {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/cs/journey.ts b/shared/src/i18n/cs/journey.ts index 44ec4fcc9..9bce80035 100644 --- a/shared/src/i18n/cs/journey.ts +++ b/shared/src/i18n/cs/journey.ts @@ -270,6 +270,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Přes cesty', + 'journey.contributors.viaTripsHint': + 'Mohou tento deník otevřít, protože ho cesta propojuje. Změňte to v nastavení cesty.', + 'journey.contributors.viaTrip': 'přes {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/de/journey.ts b/shared/src/i18n/de/journey.ts index f0d0047f0..72ad48565 100644 --- a/shared/src/i18n/de/journey.ts +++ b/shared/src/i18n/de/journey.ts @@ -180,6 +180,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': '{username} aus dieser Journey entfernen?', 'journey.contributors.removed': 'Mitwirkender entfernt', 'journey.contributors.removeFailed': 'Entfernen fehlgeschlagen', + 'journey.contributors.viaTrips': 'Über Reisen', + 'journey.contributors.viaTripsHint': + 'Sie können dieses Journal öffnen, weil eine Reise es verknüpft. Ändern lässt sich das in den Einstellungen der Reise.', + 'journey.contributors.viaTrip': 'über {trip}', 'journey.share.publicShare': 'Öffentlicher Link', 'journey.share.createLink': 'Link erstellen', 'journey.share.linkCreated': 'Link erstellt', diff --git a/shared/src/i18n/en/journey.ts b/shared/src/i18n/en/journey.ts index 7584c22bf..5371fefbc 100644 --- a/shared/src/i18n/en/journey.ts +++ b/shared/src/i18n/en/journey.ts @@ -188,6 +188,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', 'journey.contributors.removed': 'Contributor removed', 'journey.contributors.removeFailed': 'Failed to remove contributor', + 'journey.contributors.viaTrips': 'Through trips', + 'journey.contributors.viaTripsHint': + "They can open this journal because a trip links it. Change that in the trip's settings.", + 'journey.contributors.viaTrip': 'via {trip}', 'journey.share.publicShare': 'Public Share', 'journey.share.createLink': 'Create share link', 'journey.share.linkCreated': 'Share link created', diff --git a/shared/src/i18n/es/journey.ts b/shared/src/i18n/es/journey.ts index 275244765..d3c0370be 100644 --- a/shared/src/i18n/es/journey.ts +++ b/shared/src/i18n/es/journey.ts @@ -265,6 +265,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'A través de viajes', + 'journey.contributors.viaTripsHint': + 'Pueden abrir este diario porque un viaje lo vincula. Cámbialo en los ajustes del viaje.', + 'journey.contributors.viaTrip': 'a través de {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/et/journey.ts b/shared/src/i18n/et/journey.ts index ea30fb624..6e27ec081 100644 --- a/shared/src/i18n/et/journey.ts +++ b/shared/src/i18n/et/journey.ts @@ -190,6 +190,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Kas eemaldada {username} sellest reisiloost?', 'journey.contributors.removed': 'Kaasautor eemaldatud', 'journey.contributors.removeFailed': 'Kaasautori eemaldamine ebaõnnestus', + 'journey.contributors.viaTrips': 'Reiside kaudu', + 'journey.contributors.viaTripsHint': + 'Nad saavad selle päeviku avada, sest reis seob selle. Muuda seda reisi seadetes.', + 'journey.contributors.viaTrip': '{trip} kaudu', 'journey.share.publicShare': 'Avalik jagamine', 'journey.share.createLink': 'Loo jagamislink', 'journey.share.linkCreated': 'Jagamislink loodud', diff --git a/shared/src/i18n/fr/journey.ts b/shared/src/i18n/fr/journey.ts index d90c27b14..405f1a2bd 100644 --- a/shared/src/i18n/fr/journey.ts +++ b/shared/src/i18n/fr/journey.ts @@ -265,6 +265,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Via des voyages', + 'journey.contributors.viaTripsHint': + "Ces personnes peuvent ouvrir ce journal parce qu'un voyage le lie. Modifiez-le dans les paramètres du voyage.", + 'journey.contributors.viaTrip': 'via {trip}', // same-as-en 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/gr/journey.ts b/shared/src/i18n/gr/journey.ts index 408625d35..931dff69b 100644 --- a/shared/src/i18n/gr/journey.ts +++ b/shared/src/i18n/gr/journey.ts @@ -183,6 +183,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Αφαίρεση {username} από αυτό το ταξίδι;', 'journey.contributors.removed': 'Ο συνεισφέρων αφαιρέθηκε', 'journey.contributors.removeFailed': 'Αποτυχία αφαίρεσης συνεισφέροντα', + 'journey.contributors.viaTrips': 'Μέσω ταξιδιών', + 'journey.contributors.viaTripsHint': + 'Μπορούν να ανοίξουν αυτό το ημερολόγιο επειδή ένα ταξίδι το συνδέει. Αλλάξτε το στις ρυθμίσεις του ταξιδιού.', + 'journey.contributors.viaTrip': 'μέσω {trip}', 'journey.share.publicShare': 'Δημόσια Κοινοποίηση', 'journey.share.createLink': 'Δημιουργία συνδέσμου κοινής χρήσης', 'journey.share.linkCreated': 'Ο σύνδεσμος κοινής χρήσης δημιουργήθηκε', diff --git a/shared/src/i18n/hu/journey.ts b/shared/src/i18n/hu/journey.ts index 7d7612223..a75296657 100644 --- a/shared/src/i18n/hu/journey.ts +++ b/shared/src/i18n/hu/journey.ts @@ -264,6 +264,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Utazásokon át', + 'journey.contributors.viaTripsHint': + 'Azért nyithatják meg ezt a naplót, mert egy utazás kapcsolja. Ezt az utazás beállításaiban módosíthatod.', + 'journey.contributors.viaTrip': '{trip} útján', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/id/journey.ts b/shared/src/i18n/id/journey.ts index 45b6bdce4..eca375ea2 100644 --- a/shared/src/i18n/id/journey.ts +++ b/shared/src/i18n/id/journey.ts @@ -257,6 +257,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Melalui perjalanan', + 'journey.contributors.viaTripsHint': + 'Mereka bisa membuka jurnal ini karena sebuah perjalanan menautkannya. Ubah di pengaturan perjalanan.', + 'journey.contributors.viaTrip': 'melalui {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/it/journey.ts b/shared/src/i18n/it/journey.ts index ca28cf3d6..ccbbef7a8 100644 --- a/shared/src/i18n/it/journey.ts +++ b/shared/src/i18n/it/journey.ts @@ -264,6 +264,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Tramite viaggi', + 'journey.contributors.viaTripsHint': + 'Possono aprire questo diario perché un viaggio lo collega. Modificalo nelle impostazioni del viaggio.', + 'journey.contributors.viaTrip': 'tramite {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/ja/journey.ts b/shared/src/i18n/ja/journey.ts index 03fb57a7d..3c8403be4 100644 --- a/shared/src/i18n/ja/journey.ts +++ b/shared/src/i18n/ja/journey.ts @@ -173,6 +173,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': '{username}をこの日記から削除しますか?', 'journey.contributors.removed': '参加者を削除しました', 'journey.contributors.removeFailed': '削除に失敗しました', + 'journey.contributors.viaTrips': '旅行経由', + 'journey.contributors.viaTripsHint': '旅行がこのジャーナルをリンクしているため開けます。変更は旅行の設定で行います。', + 'journey.contributors.viaTrip': '{trip} 経由', 'journey.share.publicShare': '公開共有', 'journey.share.createLink': '共有リンクを作成', 'journey.share.linkCreated': '共有リンクを作成しました', diff --git a/shared/src/i18n/ko/journey.ts b/shared/src/i18n/ko/journey.ts index 92b5e0842..1f60a59fd 100644 --- a/shared/src/i18n/ko/journey.ts +++ b/shared/src/i18n/ko/journey.ts @@ -172,6 +172,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': '{username}을(를) 이 Journey에서 제거할까요?', 'journey.contributors.removed': '기여자가 제거되었습니다', 'journey.contributors.removeFailed': '기여자 제거 실패', + 'journey.contributors.viaTrips': '여행을 통해', + 'journey.contributors.viaTripsHint': '여행이 이 저널을 연결하고 있어 열 수 있습니다. 여행 설정에서 변경하세요.', + 'journey.contributors.viaTrip': '{trip} 통해', 'journey.share.publicShare': '공개 공유', 'journey.share.createLink': '공유 링크 만들기', 'journey.share.linkCreated': '공유 링크가 생성되었습니다', diff --git a/shared/src/i18n/nl/journey.ts b/shared/src/i18n/nl/journey.ts index cd3075032..8e2b8da48 100644 --- a/shared/src/i18n/nl/journey.ts +++ b/shared/src/i18n/nl/journey.ts @@ -266,6 +266,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Via reizen', + 'journey.contributors.viaTripsHint': + 'Zij kunnen dit dagboek openen omdat een reis het koppelt. Wijzig dat in de instellingen van de reis.', + 'journey.contributors.viaTrip': 'via {trip}', // same-as-en 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/pl/journey.ts b/shared/src/i18n/pl/journey.ts index b276a33a5..f81602e52 100644 --- a/shared/src/i18n/pl/journey.ts +++ b/shared/src/i18n/pl/journey.ts @@ -278,6 +278,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Przez podróże', + 'journey.contributors.viaTripsHint': + 'Mogą otworzyć ten dziennik, bo podróż go łączy. Zmień to w ustawieniach podróży.', + 'journey.contributors.viaTrip': 'przez {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/ru/journey.ts b/shared/src/i18n/ru/journey.ts index 8ad56ec55..9277d3d3c 100644 --- a/shared/src/i18n/ru/journey.ts +++ b/shared/src/i18n/ru/journey.ts @@ -278,6 +278,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': 'Через поездки', + 'journey.contributors.viaTripsHint': + 'Они могут открыть этот дневник, потому что его привязала поездка. Измените это в настройках поездки.', + 'journey.contributors.viaTrip': 'через {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/sk/journey.ts b/shared/src/i18n/sk/journey.ts index 18a9ea216..c808bb3da 100644 --- a/shared/src/i18n/sk/journey.ts +++ b/shared/src/i18n/sk/journey.ts @@ -193,6 +193,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Odstrániť {username} z tohto cestovného denníka?', 'journey.contributors.removed': 'Prispievateľ odstránený', 'journey.contributors.removeFailed': 'Odstránenie prispievateľa zlyhalo', + 'journey.contributors.viaTrips': 'Cez cesty', + 'journey.contributors.viaTripsHint': + 'Môžu tento denník otvoriť, pretože ho cesta prepája. Zmeňte to v nastaveniach cesty.', + 'journey.contributors.viaTrip': 'cez {trip}', 'journey.share.publicShare': 'Verejné zdieľanie', 'journey.share.createLink': 'Vytvoriť odkaz na zdieľanie', 'journey.share.linkCreated': 'Odkaz na zdieľanie vytvorený', diff --git a/shared/src/i18n/sv/journey.ts b/shared/src/i18n/sv/journey.ts index 97b0cb569..296e35494 100644 --- a/shared/src/i18n/sv/journey.ts +++ b/shared/src/i18n/sv/journey.ts @@ -181,6 +181,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Ta bort {username} från denna journey?', 'journey.contributors.removed': 'Medverkare borttagen', 'journey.contributors.removeFailed': 'Kunde inte ta bort medverkare', + 'journey.contributors.viaTrips': 'Via resor', + 'journey.contributors.viaTripsHint': + 'De kan öppna dagboken eftersom en resa kopplar den. Ändra det i resans inställningar.', + 'journey.contributors.viaTrip': 'via {trip}', // same-as-en 'journey.share.publicShare': 'Offentlig delning', 'journey.share.createLink': 'Skapa en delningslänk', 'journey.share.linkCreated': 'Länk för delning har skapats', diff --git a/shared/src/i18n/th/journey.ts b/shared/src/i18n/th/journey.ts index 3ca5a0fb0..f3ed803d9 100644 --- a/shared/src/i18n/th/journey.ts +++ b/shared/src/i18n/th/journey.ts @@ -183,6 +183,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'ลบ {username} ออกจากการเดินทางนี้หรือไม่', 'journey.contributors.removed': 'ผู้ร่วมให้ข้อมูลถูกลบออก', 'journey.contributors.removeFailed': 'ไม่สามารถลบผู้ร่วมให้ข้อมูลได้', + 'journey.contributors.viaTrips': 'ผ่านทริป', + 'journey.contributors.viaTripsHint': 'พวกเขาเปิดบันทึกนี้ได้เพราะทริปหนึ่งเชื่อมไว้ เปลี่ยนได้ในการตั้งค่าของทริป', + 'journey.contributors.viaTrip': 'ผ่าน {trip}', 'journey.share.publicShare': 'แบ่งปันสาธารณะ', 'journey.share.createLink': 'สร้างลิงก์แชร์', 'journey.share.linkCreated': 'สร้างลิงก์แชร์แล้ว', diff --git a/shared/src/i18n/tr/journey.ts b/shared/src/i18n/tr/journey.ts index dbaf617c0..c01c6a32c 100644 --- a/shared/src/i18n/tr/journey.ts +++ b/shared/src/i18n/tr/journey.ts @@ -178,6 +178,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': "{username} bu journey'den kaldırılsın mı?", 'journey.contributors.removed': 'Katkıda bulunan kaldırıldı', 'journey.contributors.removeFailed': 'Katkıda bulunan kaldırılamadı', + 'journey.contributors.viaTrips': 'Seyahatler üzerinden', + 'journey.contributors.viaTripsHint': + 'Bir seyahat bu günlüğü bağladığı için açabiliyorlar. Bunu seyahatin ayarlarından değiştir.', + 'journey.contributors.viaTrip': '{trip} üzerinden', 'journey.share.publicShare': 'Herkese açık paylaşım', 'journey.share.createLink': 'Paylaşım bağlantısı oluştur', 'journey.share.linkCreated': 'Paylaşım bağlantısı oluşturuldu', diff --git a/shared/src/i18n/uk/journey.ts b/shared/src/i18n/uk/journey.ts index 238a511e7..29f5e0ee2 100644 --- a/shared/src/i18n/uk/journey.ts +++ b/shared/src/i18n/uk/journey.ts @@ -187,6 +187,10 @@ const journey: TranslationStrings = { 'journey.contributors.remove': 'Вилучити учасника', 'journey.contributors.removeConfirm': 'Вилучити {username} з цієї подорожі?', 'journey.contributors.removeFailed': 'Не вдалося вилучити учасника', + 'journey.contributors.viaTrips': 'Через подорожі', + 'journey.contributors.viaTripsHint': + 'Вони можуть відкрити цей щоденник, бо його привʼязала подорож. Змініть це в налаштуваннях подорожі.', + 'journey.contributors.viaTrip': 'через {trip}', 'journey.contributors.removed': 'Учасника вилучено', 'journey.share.publicShare': 'Публічний доступ', 'journey.share.createLink': 'Створити посилання для спільного доступу', diff --git a/shared/src/i18n/vi/journey.ts b/shared/src/i18n/vi/journey.ts index ea2b820f1..47ca318ef 100644 --- a/shared/src/i18n/vi/journey.ts +++ b/shared/src/i18n/vi/journey.ts @@ -176,6 +176,10 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Xóa {username} khỏi hành trình này?', 'journey.contributors.removed': 'Đã xóa người đóng góp', 'journey.contributors.removeFailed': 'Không thể xóa người đóng góp', + 'journey.contributors.viaTrips': 'Qua chuyến đi', + 'journey.contributors.viaTripsHint': + 'Họ có thể mở nhật ký này vì một chuyến đi liên kết nó. Thay đổi trong cài đặt của chuyến đi.', + 'journey.contributors.viaTrip': 'qua {trip}', 'journey.share.publicShare': 'Chia sẻ công khai', 'journey.share.createLink': 'Tạo liên kết chia sẻ', 'journey.share.linkCreated': 'Đã tạo liên kết chia sẻ', diff --git a/shared/src/i18n/zh-TW/journey.ts b/shared/src/i18n/zh-TW/journey.ts index a0882b74f..c6c8d6a77 100644 --- a/shared/src/i18n/zh-TW/journey.ts +++ b/shared/src/i18n/zh-TW/journey.ts @@ -253,6 +253,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': 'Remove {username} from this journey?', // en-fallback 'journey.contributors.removed': 'Contributor removed', // en-fallback 'journey.contributors.removeFailed': 'Failed to remove contributor', // en-fallback + 'journey.contributors.viaTrips': '透過旅行', + 'journey.contributors.viaTripsHint': '因為某個旅行連結了此日誌,他們可以開啟它。請在該旅行的設定中變更。', + 'journey.contributors.viaTrip': '透過 {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback diff --git a/shared/src/i18n/zh/journey.ts b/shared/src/i18n/zh/journey.ts index 5893a3443..1cdfbaf44 100644 --- a/shared/src/i18n/zh/journey.ts +++ b/shared/src/i18n/zh/journey.ts @@ -253,6 +253,9 @@ const journey: TranslationStrings = { 'journey.contributors.removeConfirm': '要将 {username} 从此旅程中移除吗?', 'journey.contributors.removed': '已移除贡献者', 'journey.contributors.removeFailed': '移除贡献者失败', + 'journey.contributors.viaTrips': '通过旅行', + 'journey.contributors.viaTripsHint': '因为某个旅行关联了此日志,他们可以打开它。请在该旅行的设置中更改。', + 'journey.contributors.viaTrip': '通过 {trip}', 'journey.editor.externalPhotos': 'External photos', // en-fallback 'journey.editor.externalPhotosFor': 'Photos for {date}', // en-fallback 'journey.editor.externalPhotosNearby': 'Nearby photos first', // en-fallback