From e63a7799fb3957ddca3c93177b38112ae8b31e56 Mon Sep 17 00:00:00 2001 From: Maurice Date: Sun, 31 May 2026 16:08:08 +0200 Subject: [PATCH] fix(i18n): guard locale key parity and finish the OAuth consent page strings Every non-en locale now exposes the exact same flat key set as en. Keys that had drifted out of sync are backfilled with the English source value (tagged en-fallback) so t() resolves a real string instead of relying on the silent runtime fallback; no existing translation was touched and no key was removed. Add a parity test that imports each aggregated locale bundle and asserts its key set matches en, with a diagnostic listing of any missing/extra keys. This complements the file-level check in shared/scripts by guarding the merged export the app actually serves. Finish internationalising OAuthAuthorizePage: the ~15 remaining hardcoded English chrome strings now go through oauth.authorize.* keys (English source in en, en-fallback placeholders elsewhere). Markup and behaviour are unchanged. --- client/src/pages/OAuthAuthorizePage.tsx | 39 ++--- client/tests/unit/i18n/parity.test.ts | 64 ++++++++ shared/src/i18n/ar/admin.ts | 26 ++++ shared/src/i18n/ar/backup.ts | 1 + shared/src/i18n/ar/collab.ts | 1 + shared/src/i18n/ar/common.ts | 3 + shared/src/i18n/ar/dayplan.ts | 8 + shared/src/i18n/ar/journey.ts | 188 ++++++++++++++++++++++++ shared/src/i18n/ar/login.ts | 1 + shared/src/i18n/ar/oauth.ts | 26 ++++ shared/src/i18n/ar/settings.ts | 18 +++ shared/src/i18n/ar/system_notice.ts | 3 + shared/src/i18n/br/dayplan.ts | 2 + shared/src/i18n/br/journey.ts | 5 + shared/src/i18n/br/oauth.ts | 24 +++ shared/src/i18n/cs/dayplan.ts | 2 + shared/src/i18n/cs/journey.ts | 5 + shared/src/i18n/cs/oauth.ts | 24 +++ shared/src/i18n/de/journey.ts | 1 + shared/src/i18n/de/oauth.ts | 24 +++ shared/src/i18n/en/oauth.ts | 24 +++ shared/src/i18n/es/dayplan.ts | 2 + shared/src/i18n/es/journey.ts | 5 + shared/src/i18n/es/oauth.ts | 24 +++ shared/src/i18n/fr/dayplan.ts | 2 + shared/src/i18n/fr/journey.ts | 5 + shared/src/i18n/fr/oauth.ts | 24 +++ shared/src/i18n/gr/dashboard.ts | 46 ++++++ shared/src/i18n/gr/oauth.ts | 24 +++ shared/src/i18n/hu/dayplan.ts | 2 + shared/src/i18n/hu/journey.ts | 5 + shared/src/i18n/hu/oauth.ts | 24 +++ shared/src/i18n/id/dayplan.ts | 2 + shared/src/i18n/id/journey.ts | 5 + shared/src/i18n/id/oauth.ts | 24 +++ shared/src/i18n/it/dayplan.ts | 2 + shared/src/i18n/it/journey.ts | 5 + shared/src/i18n/it/oauth.ts | 24 +++ shared/src/i18n/ja/oauth.ts | 24 +++ shared/src/i18n/ko/oauth.ts | 24 +++ shared/src/i18n/nl/dayplan.ts | 2 + shared/src/i18n/nl/journey.ts | 5 + shared/src/i18n/nl/oauth.ts | 24 +++ shared/src/i18n/pl/dayplan.ts | 2 + shared/src/i18n/pl/journey.ts | 5 + shared/src/i18n/pl/oauth.ts | 24 +++ shared/src/i18n/ru/dayplan.ts | 2 + shared/src/i18n/ru/journey.ts | 5 + shared/src/i18n/ru/oauth.ts | 24 +++ shared/src/i18n/tr/oauth.ts | 24 +++ shared/src/i18n/uk/oauth.ts | 24 +++ shared/src/i18n/zh-TW/dayplan.ts | 2 + shared/src/i18n/zh-TW/journey.ts | 5 + shared/src/i18n/zh-TW/oauth.ts | 24 +++ shared/src/i18n/zh/dayplan.ts | 2 + shared/src/i18n/zh/journey.ts | 5 + shared/src/i18n/zh/oauth.ts | 24 +++ 57 files changed, 948 insertions(+), 17 deletions(-) create mode 100644 client/tests/unit/i18n/parity.test.ts diff --git a/client/src/pages/OAuthAuthorizePage.tsx b/client/src/pages/OAuthAuthorizePage.tsx index 72bc8b61..9f4e7a13 100644 --- a/client/src/pages/OAuthAuthorizePage.tsx +++ b/client/src/pages/OAuthAuthorizePage.tsx @@ -20,7 +20,7 @@ export default function OAuthAuthorizePage(): React.ReactElement {

- {pageState === 'auto_approving' ? 'Authorizing…' : 'Loading…'} + {pageState === 'auto_approving' ? t('oauth.authorize.authorizing') : t('oauth.authorize.loading')}

@@ -32,7 +32,7 @@ export default function OAuthAuthorizePage(): React.ReactElement {
-

Authorization Error

+

{t('oauth.authorize.errorTitle')}

{errorMsg}

@@ -45,9 +45,9 @@ export default function OAuthAuthorizePage(): React.ReactElement {
-

Sign in to continue

+

{t('oauth.authorize.loginTitle')}

- {validation?.client?.name || clientId} wants access to your TREK account. Please sign in first. + {t('oauth.authorize.loginDescription', { client: validation?.client?.name || clientId })}

@@ -74,19 +74,19 @@ export default function OAuthAuthorizePage(): React.ReactElement {
-

Authorization Request

+

{t('oauth.authorize.requestLabel')}

{validation?.client?.name || clientId}

- This application is requesting access to your TREK account. + {t('oauth.authorize.requestDescription')}

- Only grant access to applications you trust. Your data stays on your server. + {t('oauth.authorize.trustNote')}

@@ -117,7 +122,7 @@ export default function OAuthAuthorizePage(): React.ReactElement { {Object.keys(scopesByGroup).length > 0 && (

- {validation?.scopeSelectable ? 'Choose which permissions to grant' : 'Permissions requested'} + {validation?.scopeSelectable ? t('oauth.authorize.choosePermissions') : t('oauth.authorize.permissionsRequested')}

{validation?.scopeSelectable ? ( @@ -201,12 +206,12 @@ export default function OAuthAuthorizePage(): React.ReactElement { {/* Always-available tools — granted regardless of scopes */}

- Always included + {t('oauth.authorize.alwaysIncluded')}

{[ - { name: 'list_trips', desc: 'List your trips so the AI can discover trip IDs' }, - { name: 'get_trip_summary', desc: 'Read a trip overview needed to use any other tool' }, + { name: 'list_trips', desc: t('oauth.authorize.alwaysTool.listTrips') }, + { name: 'get_trip_summary', desc: t('oauth.authorize.alwaysTool.getTripSummary') }, ].map(({ name, desc }) => (
👁️ diff --git a/client/tests/unit/i18n/parity.test.ts b/client/tests/unit/i18n/parity.test.ts new file mode 100644 index 00000000..ec60b2ee --- /dev/null +++ b/client/tests/unit/i18n/parity.test.ts @@ -0,0 +1,64 @@ +import { describe, it, expect } from 'vitest' +import type { TranslationStrings } from '@trek/shared/i18n' +import en from '@trek/shared/i18n/en' +import de from '@trek/shared/i18n/de' +import es from '@trek/shared/i18n/es' +import fr from '@trek/shared/i18n/fr' +import hu from '@trek/shared/i18n/hu' +import itIT from '@trek/shared/i18n/it' +import tr from '@trek/shared/i18n/tr' +import ru from '@trek/shared/i18n/ru' +import zh from '@trek/shared/i18n/zh' +import zhTW from '@trek/shared/i18n/zh-TW' +import nl from '@trek/shared/i18n/nl' +import idID from '@trek/shared/i18n/id' +import ar from '@trek/shared/i18n/ar' +import br from '@trek/shared/i18n/br' +import cs from '@trek/shared/i18n/cs' +import pl from '@trek/shared/i18n/pl' +import ja from '@trek/shared/i18n/ja' +import ko from '@trek/shared/i18n/ko' +import uk from '@trek/shared/i18n/uk' +import gr from '@trek/shared/i18n/gr' + +// Runtime guard for the aggregated i18n bundles. `t()` resolves keys against the +// active locale's flat dot-key map (see TranslationContext), so a key that is +// present in en but missing in another locale silently falls back to English at +// runtime — easy to ship, hard to notice. This test fails loudly when any locale +// drifts away from the en key set so translators get an explicit, diagnostic list. +// +// The shared package also runs a file-level parity check (shared/scripts), but +// that one only inspects per-domain source files; this one asserts the *merged* +// export each locale actually serves to the app. + +const NON_EN_LOCALES: Record = { + de, es, fr, hu, it: itIT, tr, ru, zh, 'zh-TW': zhTW, nl, id: idID, + ar, br, cs, pl, ja, ko, uk, gr, +} + +const enKeys = new Set(Object.keys(en)) + +describe('i18n locale key parity', () => { + it('covers every non-en locale', () => { + // Keep the assertion set in lockstep with the supported language list minus en. + expect(Object.keys(NON_EN_LOCALES)).toHaveLength(19) + }) + + for (const [locale, strings] of Object.entries(NON_EN_LOCALES)) { + it(`${locale} has the exact same key set as en`, () => { + const localeKeys = new Set(Object.keys(strings)) + const missing = [...enKeys].filter((k) => !localeKeys.has(k)) + const extra = [...localeKeys].filter((k) => !enKeys.has(k)) + + const diagnostic = + `Locale "${locale}" key drift vs en — ` + + `missing ${missing.length}` + + (missing.length ? ` (${missing.slice(0, 10).join(', ')}${missing.length > 10 ? ', …' : ''})` : '') + + `; extra ${extra.length}` + + (extra.length ? ` (${extra.slice(0, 10).join(', ')}${extra.length > 10 ? ', …' : ''})` : '') + + expect(missing, diagnostic).toEqual([]) + expect(extra, diagnostic).toEqual([]) + }) + } +}) diff --git a/shared/src/i18n/ar/admin.ts b/shared/src/i18n/ar/admin.ts index 7fd39133..7e8f30d2 100644 --- a/shared/src/i18n/ar/admin.ts +++ b/shared/src/i18n/ar/admin.ts @@ -315,5 +315,31 @@ const admin: TranslationStrings = { 'يعمل TREK الخاص بك في Docker. للتحديث إلى {version}، نفّذ الأوامر التالية على الخادم:', 'admin.update.reloadHint': 'يرجى إعادة تحميل الصفحة بعد بضع ثوانٍ.', 'admin.tabs.permissions': 'الصلاحيات', + 'admin.notifications.webhook': 'Webhook', // en-fallback + 'admin.notifications.ntfy': 'Ntfy', // en-fallback + 'admin.notifications.emailPanel.title': 'Email (SMTP)', // en-fallback + 'admin.notifications.webhookPanel.title': 'Webhook', // en-fallback + 'admin.notifications.inappPanel.title': 'In-App', // en-fallback + 'admin.notifications.adminNtfyPanel.serverPlaceholder': 'https://ntfy.sh', // en-fallback + 'admin.notifications.adminNtfyPanel.topicPlaceholder': 'trek-admin-alerts', // en-fallback + 'admin.authMethods': 'Authentication Methods', // en-fallback + 'admin.passwordLogin': 'Password Login', // en-fallback + 'admin.passwordLoginHint': 'Allow users to sign in with email and password', // en-fallback + 'admin.passwordRegistration': 'Password Registration', // en-fallback + 'admin.passwordRegistrationHint': + 'Allow new users to register with email and password', // en-fallback + 'admin.oidcLogin': 'SSO Login', // en-fallback + 'admin.oidcLoginHint': 'Allow users to sign in with SSO', // en-fallback + 'admin.oidcRegistration': 'SSO Auto-Provisioning', // en-fallback + 'admin.oidcRegistrationHint': + 'Automatically create accounts for new SSO users', // en-fallback + 'admin.envOverrideHint': + 'Password login settings are controlled by the OIDC_ONLY environment variable and cannot be changed here.', // en-fallback + 'admin.lockoutWarning': 'At least one login method must remain enabled', // en-fallback + 'admin.addons.catalog.mcp.name': 'MCP', // en-fallback + 'admin.tabs.github': 'GitHub', // en-fallback + 'admin.addons.catalog.journey.name': 'Journey', // en-fallback + 'admin.addons.catalog.journey.description': + 'Trip tracking & travel journal with check-ins, photos, and daily stories', // en-fallback }; export default admin; diff --git a/shared/src/i18n/ar/backup.ts b/shared/src/i18n/ar/backup.ts index 24ea0d10..c42dddfc 100644 --- a/shared/src/i18n/ar/backup.ts +++ b/shared/src/i18n/ar/backup.ts @@ -71,5 +71,6 @@ const backup: TranslationStrings = { 'backup.restoreTip': 'نصيحة: أنشئ نسخة احتياطية للحالة الحالية قبل الاستعادة.', 'backup.restoreConfirm': 'نعم، استعادة', + 'backup.auto.envLocked': 'Docker', // en-fallback }; export default backup; diff --git a/shared/src/i18n/ar/collab.ts b/shared/src/i18n/ar/collab.ts index ddfc600d..55177539 100644 --- a/shared/src/i18n/ar/collab.ts +++ b/shared/src/i18n/ar/collab.ts @@ -68,5 +68,6 @@ const collab: TranslationStrings = { 'collab.polls.options': 'الخيارات', 'collab.polls.delete': 'حذف', 'collab.polls.closedSection': 'مغلق', + 'collab.notes.websitePlaceholder': 'https://...', // en-fallback }; export default collab; diff --git a/shared/src/i18n/ar/common.ts b/shared/src/i18n/ar/common.ts index 0f665c12..3c0181bd 100644 --- a/shared/src/i18n/ar/common.ts +++ b/shared/src/i18n/ar/common.ts @@ -47,5 +47,8 @@ const common: TranslationStrings = { 'common.collapse': 'طي', 'common.copy': 'نسخ', 'common.copied': 'تم النسخ', + 'common.justNow': 'just now', // en-fallback + 'common.hoursAgo': '{count}h ago', // en-fallback + 'common.daysAgo': '{count}d ago', // en-fallback }; export default common; diff --git a/shared/src/i18n/ar/dayplan.ts b/shared/src/i18n/ar/dayplan.ts index 42df2f5a..ccb83dd2 100644 --- a/shared/src/i18n/ar/dayplan.ts +++ b/shared/src/i18n/ar/dayplan.ts @@ -34,5 +34,13 @@ const dayplan: TranslationStrings = { 'dayplan.pendingRes': 'قيد الانتظار', 'dayplan.pdfTooltip': 'تصدير خطة اليوم بصيغة PDF', 'dayplan.pdfError': 'فشل تصدير PDF', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback + 'dayplan.pdf': 'PDF', // en-fallback + 'dayplan.mobile.addPlace': 'Add Place', // en-fallback + 'dayplan.mobile.searchPlaces': 'Search places...', // en-fallback + 'dayplan.mobile.allAssigned': 'All places assigned', // en-fallback + 'dayplan.mobile.noMatch': 'No match', // en-fallback + 'dayplan.mobile.createNew': 'Create new place', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/ar/journey.ts b/shared/src/i18n/ar/journey.ts index 1ed12a24..5e1a762e 100644 --- a/shared/src/i18n/ar/journey.ts +++ b/shared/src/i18n/ar/journey.ts @@ -52,5 +52,193 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'لم يتم العثور على ألبومات', 'journey.picker.selectDate': 'اختر تاريخ', 'journey.picker.search': 'بحث', + 'journey.title': 'Journey', // en-fallback + 'journey.subtitle': 'Track your travels as they happen', // en-fallback + 'journey.new': 'New Journey', // en-fallback + 'journey.create': 'Create', // en-fallback + 'journey.titlePlaceholder': 'Where are you going?', // en-fallback + 'journey.empty': 'No journeys yet', // en-fallback + 'journey.emptyHint': 'Start documenting your next trip', // en-fallback + 'journey.deleted': 'Journey deleted', // en-fallback + 'journey.createError': 'Could not create journey', // en-fallback + 'journey.deleteError': 'Could not delete journey', // en-fallback + 'journey.deleteConfirmTitle': 'Delete', // en-fallback + 'journey.deleteConfirmMessage': 'Delete "{title}"? This cannot be undone.', // en-fallback + 'journey.deleteConfirmGeneric': 'Are you sure you want to delete this?', // en-fallback + 'journey.notFound': 'Journey not found', // en-fallback + 'journey.photos': 'Photos', // en-fallback + 'journey.timelineEmpty': 'No stops yet', // en-fallback + 'journey.timelineEmptyHint': + 'Add a check-in or write a journal entry to get started', // en-fallback + 'journey.status.draft': 'Draft', // en-fallback + 'journey.status.active': 'Active', // en-fallback + 'journey.status.completed': 'Completed', // en-fallback + 'journey.status.upcoming': 'Upcoming', // en-fallback + 'journey.checkin.add': 'Check in', // en-fallback + 'journey.checkin.namePlaceholder': 'Location name', // en-fallback + 'journey.checkin.notesPlaceholder': 'Notes (optional)', // en-fallback + 'journey.checkin.save': 'Save', // en-fallback + 'journey.checkin.error': 'Could not save check-in', // en-fallback + 'journey.entry.add': 'Journal', // en-fallback + 'journey.entry.edit': 'Edit entry', // en-fallback + 'journey.entry.titlePlaceholder': 'Title (optional)', // en-fallback + 'journey.entry.bodyPlaceholder': 'What happened today?', // en-fallback + 'journey.entry.save': 'Save', // en-fallback + 'journey.entry.error': 'Could not save entry', // en-fallback + 'journey.photo.add': 'Photo', // en-fallback + 'journey.photo.uploadError': 'Upload failed', // en-fallback + 'journey.share.share': 'Share', // en-fallback + 'journey.share.public': 'Public', // en-fallback + 'journey.share.linkCopied': 'Public link copied', // en-fallback + 'journey.share.disabled': 'Public sharing disabled', // en-fallback + 'journey.editor.titlePlaceholder': 'Give this moment a name...', // en-fallback + 'journey.editor.bodyPlaceholder': 'Tell the story of this day...', // en-fallback + 'journey.editor.placePlaceholder': 'Location (optional)', // en-fallback + 'journey.editor.tagsPlaceholder': + 'Tags: hidden gem, best meal, must revisit...', // en-fallback + 'journey.visibility.private': 'Private', // en-fallback + 'journey.visibility.shared': 'Shared', // en-fallback + 'journey.visibility.public': 'Public', // en-fallback + 'journey.emptyState.title': 'Your story starts here', // en-fallback + 'journey.emptyState.subtitle': + 'Check in at a place or write your first journal entry', // en-fallback + 'journey.frontpage.subtitle': + "Turn your trips into stories you'll never forget", // en-fallback + 'journey.frontpage.createJourney': 'Create Journey', // en-fallback + 'journey.frontpage.activeJourney': 'Active Journey', // en-fallback + 'journey.frontpage.allJourneys': 'All Journeys', // en-fallback + 'journey.frontpage.journeys': 'journeys', // en-fallback + 'journey.frontpage.createNew': 'Create a new Journey', // en-fallback + 'journey.frontpage.createNewSub': + 'Pick trips, write stories, share your adventures', // en-fallback + 'journey.frontpage.live': 'Live', // en-fallback + 'journey.frontpage.synced': 'Synced', // en-fallback + 'journey.frontpage.continueWriting': 'Continue writing', // en-fallback + 'journey.frontpage.updated': 'Updated {time}', // en-fallback + 'journey.frontpage.suggestionLabel': 'Trip just ended', // en-fallback + 'journey.frontpage.suggestionText': + 'Turn {title} into a Journey', // en-fallback + 'journey.frontpage.dismiss': 'Dismiss', // en-fallback + 'journey.frontpage.journeyName': 'Journey Name', // en-fallback + 'journey.frontpage.namePlaceholder': 'e.g. Southeast Asia 2026', // en-fallback + 'journey.frontpage.selectTrips': 'Select Trips', // en-fallback + 'journey.frontpage.tripsSelected': 'trips selected', // en-fallback + 'journey.frontpage.trips': 'trips', // en-fallback + 'journey.frontpage.placesImported': 'places will be imported', // en-fallback + 'journey.frontpage.places': 'places', // en-fallback + 'journey.detail.syncedWithTrips': 'Synced with Trips', // en-fallback + 'journey.detail.addEntry': 'Add Entry', // en-fallback + 'journey.detail.newEntry': 'New Entry', // en-fallback + 'journey.detail.editEntry': 'Edit Entry', // en-fallback + 'journey.detail.noEntries': 'No entries yet', // en-fallback + 'journey.detail.noEntriesHint': + 'Add a trip to get started with skeleton entries', // en-fallback + 'journey.detail.noPhotos': 'No photos yet', // en-fallback + 'journey.detail.noPhotosHint': + 'Upload photos to entries or browse your Immich/Synology library', // en-fallback + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.detail.journeyStats': 'Journey Stats', // en-fallback + 'journey.detail.syncedTrips': 'Synced Trips', // en-fallback + 'journey.detail.noTripsLinked': 'No trips linked yet', // en-fallback + 'journey.detail.contributors': 'Contributors', // en-fallback + 'journey.detail.readMore': 'Read more', // en-fallback + 'journey.detail.prosCons': 'Pros & Cons', // en-fallback + 'journey.stats.days': 'Days', // en-fallback + 'journey.stats.cities': 'Cities', // en-fallback + 'journey.stats.entries': 'Entries', // en-fallback + 'journey.stats.photos': 'Photos', // en-fallback + 'journey.stats.places': 'Places', // en-fallback + 'journey.verdict.lovedIt': 'Loved it', // en-fallback + 'journey.verdict.couldBeBetter': 'Could be better', // en-fallback + 'journey.synced.places': 'places', // en-fallback + 'journey.synced.synced': 'synced', // en-fallback + 'journey.editor.allPhotosAdded': 'All photos already added', // en-fallback + 'journey.editor.writeStory': 'Write your story...', // en-fallback + 'journey.editor.prosCons': 'Pros & Cons', // en-fallback + 'journey.editor.pros': 'Pros', // en-fallback + 'journey.editor.cons': 'Cons', // en-fallback + 'journey.editor.proPlaceholder': 'Something great...', // en-fallback + 'journey.editor.conPlaceholder': 'Not so great...', // en-fallback + 'journey.editor.date': 'Date', // en-fallback + 'journey.editor.location': 'Location', // en-fallback + 'journey.editor.searchLocation': 'Search location...', // en-fallback + 'journey.editor.mood': 'Mood', // en-fallback + 'journey.editor.weather': 'Weather', // en-fallback + 'journey.editor.photoFirst': '1st', // en-fallback + 'journey.mood.amazing': 'Amazing', // en-fallback + 'journey.mood.good': 'Good', // en-fallback + 'journey.mood.neutral': 'Neutral', // en-fallback + 'journey.mood.rough': 'Rough', // en-fallback + 'journey.weather.sunny': 'Sunny', // en-fallback + 'journey.weather.partly': 'Partly cloudy', // en-fallback + 'journey.weather.cloudy': 'Cloudy', // en-fallback + 'journey.weather.rainy': 'Rainy', // en-fallback + 'journey.weather.stormy': 'Stormy', // en-fallback + 'journey.weather.cold': 'Snowy', // en-fallback + 'journey.trips.linkTrip': 'Link Trip', // en-fallback + 'journey.trips.searchTrip': 'Search Trip', // en-fallback + 'journey.trips.searchPlaceholder': 'Trip name or destination...', // en-fallback + 'journey.trips.noTripsAvailable': 'No trips available', // en-fallback + 'journey.trips.link': 'Link', // en-fallback + 'journey.trips.tripLinked': 'Trip linked', // en-fallback + 'journey.trips.linkFailed': 'Failed to link trip', // en-fallback + 'journey.trips.addTrip': 'Add Trip', // en-fallback + 'journey.trips.unlinkTrip': 'Unlink Trip', // en-fallback + 'journey.trips.unlinkMessage': + 'Unlink "{title}"? All synced entries and photos from this trip will be permanently deleted. This cannot be undone.', // en-fallback + 'journey.trips.unlink': 'Unlink', // en-fallback + 'journey.trips.tripUnlinked': 'Trip unlinked', // en-fallback + 'journey.trips.unlinkFailed': 'Failed to unlink trip', // en-fallback + 'journey.trips.noTripsLinkedSettings': 'No trips linked', // en-fallback + 'journey.contributors.invite': 'Invite Contributor', // en-fallback + 'journey.contributors.searchUser': 'Search User', // en-fallback + 'journey.contributors.searchPlaceholder': 'Username or email...', // en-fallback + 'journey.contributors.noUsers': 'No users found', // en-fallback + 'journey.contributors.role': 'Role', // en-fallback + 'journey.contributors.added': 'Contributor added', // en-fallback + 'journey.contributors.addFailed': 'Failed to add contributor', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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.share.publicShare': 'Public Share', // en-fallback + 'journey.share.createLink': 'Create share link', // en-fallback + 'journey.share.linkCreated': 'Share link created', // en-fallback + 'journey.share.createFailed': 'Failed to create link', // en-fallback + 'journey.share.timeline': 'Timeline', // en-fallback + 'journey.share.gallery': 'Gallery', // en-fallback + 'journey.share.map': 'Map', // en-fallback + 'journey.share.removeLink': 'Remove share link', // en-fallback + 'journey.share.linkDeleted': 'Share link deleted', // en-fallback + 'journey.share.deleteFailed': 'Failed to delete', // en-fallback + 'journey.share.updateFailed': 'Failed to update', // en-fallback + 'journey.settings.title': 'Journey Settings', // en-fallback + 'journey.settings.coverImage': 'Cover Image', // en-fallback + 'journey.settings.changeCover': 'Change cover', // en-fallback + 'journey.settings.addCover': 'Add cover image', // en-fallback + 'journey.settings.name': 'Name', // en-fallback + 'journey.settings.subtitle': 'Subtitle', // en-fallback + 'journey.settings.subtitlePlaceholder': 'e.g. Thailand, Vietnam & Cambodia', // en-fallback + '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 + 'journey.settings.saved': 'Settings saved', // en-fallback + 'journey.settings.saveFailed': 'Failed to save', // en-fallback + 'journey.settings.coverUpdated': 'Cover updated', // en-fallback + 'journey.settings.coverFailed': 'Upload failed', // en-fallback + 'journey.public.notFound': 'Not Found', // en-fallback + 'journey.public.notFoundMessage': + "This journey doesn't exist or the link has expired.", // en-fallback + 'journey.public.readOnly': 'Read-only · Public Journey', // en-fallback + 'journey.public.tagline': 'Travel Resource & Exploration Kit', // en-fallback + 'journey.public.sharedVia': 'Shared via', // en-fallback + 'journey.public.madeWith': 'Made with', // en-fallback + 'journey.pdf.journeyBook': 'Journey Book', // en-fallback + 'journey.pdf.madeWith': 'Made with TREK', // en-fallback + 'journey.pdf.day': 'Day', // en-fallback + 'journey.pdf.theEnd': 'The End', // en-fallback + 'journey.pdf.saveAsPdf': 'Save as PDF', // en-fallback + 'journey.pdf.pages': 'pages', // en-fallback }; export default journey; diff --git a/shared/src/i18n/ar/login.ts b/shared/src/i18n/ar/login.ts index 3463d293..603d9600 100644 --- a/shared/src/i18n/ar/login.ts +++ b/shared/src/i18n/ar/login.ts @@ -87,5 +87,6 @@ const login: TranslationStrings = { 'login.resetPasswordInvalidLinkBody': 'هذا الرابط مفقود أو تالف. اطلب رابطًا جديدًا للمتابعة.', 'login.resetPasswordFailed': 'فشلت إعادة التعيين. ربما انتهت صلاحية الرابط.', + 'login.emailPlaceholder': 'your@email.com', // en-fallback }; export default login; diff --git a/shared/src/i18n/ar/oauth.ts b/shared/src/i18n/ar/oauth.ts index ea117dae..6b50b518 100644 --- a/shared/src/i18n/ar/oauth.ts +++ b/shared/src/i18n/ar/oauth.ts @@ -89,5 +89,31 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'إدارة روابط مذكرات السفر', 'oauth.scope.journey:share.description': 'إنشاء روابط مشاركة عامة لمذكرات السفر وتحديثها وإلغاؤها', + 'oauth.scope.group.atlas': 'Atlas', // en-fallback + 'oauth.scope.group.geo': 'Geo', // en-fallback + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/ar/settings.ts b/shared/src/i18n/ar/settings.ts index fafaa676..2f5b9409 100644 --- a/shared/src/i18n/ar/settings.ts +++ b/shared/src/i18n/ar/settings.ts @@ -270,5 +270,23 @@ const settings: TranslationStrings = { 'settings.mfa.toastEnabled': 'تم تفعيل المصادقة الثنائية', 'settings.mfa.toastDisabled': 'تم تعطيل المصادقة الثنائية', 'settings.mfa.demoBlocked': 'غير متاح في الوضع التجريبي', + 'settings.tabs.offline': 'Offline', // en-fallback + 'settings.mapTemplatePlaceholder': + 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', // en-fallback + 'settings.notificationPreferences.email': 'Email', // en-fallback + 'settings.notificationPreferences.webhook': 'Webhook', // en-fallback + 'settings.notificationPreferences.inapp': 'In-App', // en-fallback + 'settings.notificationPreferences.ntfy': 'Ntfy', // en-fallback + 'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...', // en-fallback + 'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts', // en-fallback + 'settings.ntfyUrl.serverPlaceholder': 'https://ntfy.sh', // en-fallback + 'settings.oauth.modal.redirectUrisPlaceholder': + 'https://your-app.com/callback\nhttps://your-app.com/auth', // en-fallback + 'settings.about.supporter.tier.noReturnTicket': 'No Return Ticket', // en-fallback + 'settings.about.supporter.tier.lostLuggageVip': 'Lost Luggage VIP', // en-fallback + 'settings.about.supporter.tier.businessClassDreamer': + 'Business Class Dreamer', // en-fallback + 'settings.about.supporter.tier.budgetTraveller': 'Budget Traveller', // en-fallback + 'settings.about.supporter.tier.hostelBunkmate': 'Hostel Bunkmate', // en-fallback }; export default settings; diff --git a/shared/src/i18n/ar/system_notice.ts b/shared/src/i18n/ar/system_notice.ts index 65867b08..01865b24 100644 --- a/shared/src/i18n/ar/system_notice.ts +++ b/shared/src/i18n/ar/system_notice.ts @@ -47,5 +47,8 @@ const system_notice: TranslationStrings = { 'system_notice.pager.next': 'الإشعار التالي', 'system_notice.pager.goto': 'الانتقال إلى الإشعار {n}', 'system_notice.pager.position': 'الإشعار {current} من {total}', + 'system_notice.dev_test_modal.title': '[Dev] Test notice', // en-fallback + 'system_notice.dev_test_modal.body': 'This is a dev-only test notice.', // en-fallback + 'system_notice.pager.counter': '{current} / {total}', // en-fallback }; export default system_notice; diff --git a/shared/src/i18n/br/dayplan.ts b/shared/src/i18n/br/dayplan.ts index 5627e2ae..a1b1c7c3 100644 --- a/shared/src/i18n/br/dayplan.ts +++ b/shared/src/i18n/br/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Todos os lugares atribuídos', 'dayplan.mobile.noMatch': 'Sem correspondência', 'dayplan.mobile.createNew': 'Criar novo lugar', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/br/journey.ts b/shared/src/i18n/br/journey.ts index be7f8994..40d81c91 100644 --- a/shared/src/i18n/br/journey.ts +++ b/shared/src/i18n/br/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Nenhum álbum encontrado', 'journey.picker.selectDate': 'Selecionar data', 'journey.picker.search': 'Pesquisar', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/br/oauth.ts b/shared/src/i18n/br/oauth.ts index 72aa5cb7..b7180bbd 100644 --- a/shared/src/i18n/br/oauth.ts +++ b/shared/src/i18n/br/oauth.ts @@ -94,5 +94,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Gerenciar links de jornadas', 'oauth.scope.journey:share.description': 'Criar, atualizar e revogar links de compartilhamento públicos para jornadas', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/cs/dayplan.ts b/shared/src/i18n/cs/dayplan.ts index 7330e0ac..9b72421d 100644 --- a/shared/src/i18n/cs/dayplan.ts +++ b/shared/src/i18n/cs/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Všechna místa přiřazena', 'dayplan.mobile.noMatch': 'Žádná shoda', 'dayplan.mobile.createNew': 'Vytvořit nové místo', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/cs/journey.ts b/shared/src/i18n/cs/journey.ts index 93d2a96e..5918d793 100644 --- a/shared/src/i18n/cs/journey.ts +++ b/shared/src/i18n/cs/journey.ts @@ -235,5 +235,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Žádná alba nenalezena', 'journey.picker.selectDate': 'Vyberte datum', 'journey.picker.search': 'Hledat', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/cs/oauth.ts b/shared/src/i18n/cs/oauth.ts index 5ff46d29..5c978fd3 100644 --- a/shared/src/i18n/cs/oauth.ts +++ b/shared/src/i18n/cs/oauth.ts @@ -94,5 +94,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Spravovat odkazy na cestovní deníky', 'oauth.scope.journey:share.description': 'Vytvářet, aktualizovat a rušit veřejné sdílené odkazy na cestovní deníky', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/de/journey.ts b/shared/src/i18n/de/journey.ts index f2161f37..ba18546a 100644 --- a/shared/src/i18n/de/journey.ts +++ b/shared/src/i18n/de/journey.ts @@ -242,5 +242,6 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Keine Alben gefunden', 'journey.picker.selectDate': 'Datum wählen', 'journey.picker.search': 'Suchen', + 'journey.detail.journeyTab': 'Journey', // en-fallback }; export default journey; diff --git a/shared/src/i18n/de/oauth.ts b/shared/src/i18n/de/oauth.ts index 43a21e76..18dfdff9 100644 --- a/shared/src/i18n/de/oauth.ts +++ b/shared/src/i18n/de/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Journey-Links verwalten', 'oauth.scope.journey:share.description': 'Öffentliche Freigabelinks für Journeys erstellen, aktualisieren und widerrufen', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/en/oauth.ts b/shared/src/i18n/en/oauth.ts index ef4f8f5c..4ec7ffc1 100644 --- a/shared/src/i18n/en/oauth.ts +++ b/shared/src/i18n/en/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Manage journey links', 'oauth.scope.journey:share.description': 'Create, update, and revoke public share links for journeys', + 'oauth.authorize.authorizing': 'Authorizing…', + 'oauth.authorize.loading': 'Loading…', + 'oauth.authorize.errorTitle': 'Authorization Error', + 'oauth.authorize.loginTitle': 'Sign in to continue', + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', + 'oauth.authorize.loginButton': 'Sign in to TREK', + 'oauth.authorize.requestLabel': 'Authorization Request', + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', + 'oauth.authorize.selectScope': 'Select at least one scope', + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', + 'oauth.authorize.approveAccess': 'Approve Access', + 'oauth.authorize.deny': 'Deny', + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', + 'oauth.authorize.permissionsRequested': 'Permissions requested', + 'oauth.authorize.alwaysIncluded': 'Always included', + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', }; export default oauth; diff --git a/shared/src/i18n/es/dayplan.ts b/shared/src/i18n/es/dayplan.ts index 309cdd9b..25281557 100644 --- a/shared/src/i18n/es/dayplan.ts +++ b/shared/src/i18n/es/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Todos los lugares asignados', 'dayplan.mobile.noMatch': 'Sin coincidencias', 'dayplan.mobile.createNew': 'Crear nuevo lugar', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/es/journey.ts b/shared/src/i18n/es/journey.ts index f551161d..00b3f547 100644 --- a/shared/src/i18n/es/journey.ts +++ b/shared/src/i18n/es/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'No se encontraron álbumes', 'journey.picker.selectDate': 'Seleccionar fecha', 'journey.picker.search': 'Buscar', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/es/oauth.ts b/shared/src/i18n/es/oauth.ts index 3ae7d027..1a01050e 100644 --- a/shared/src/i18n/es/oauth.ts +++ b/shared/src/i18n/es/oauth.ts @@ -94,5 +94,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Gestionar enlaces de travesías', 'oauth.scope.journey:share.description': 'Crear, actualizar y revocar enlaces públicos de compartir para travesías', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/fr/dayplan.ts b/shared/src/i18n/fr/dayplan.ts index 1a671207..2066e978 100644 --- a/shared/src/i18n/fr/dayplan.ts +++ b/shared/src/i18n/fr/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Tous les lieux attribués', 'dayplan.mobile.noMatch': 'Aucun résultat', 'dayplan.mobile.createNew': 'Créer un nouveau lieu', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/fr/journey.ts b/shared/src/i18n/fr/journey.ts index 1074e77f..897fdf30 100644 --- a/shared/src/i18n/fr/journey.ts +++ b/shared/src/i18n/fr/journey.ts @@ -237,5 +237,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Aucun album trouvé', 'journey.picker.selectDate': 'Sélectionner une date', 'journey.picker.search': 'Rechercher', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/fr/oauth.ts b/shared/src/i18n/fr/oauth.ts index 1c81d941..6cf851e8 100644 --- a/shared/src/i18n/fr/oauth.ts +++ b/shared/src/i18n/fr/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Gérer les liens de journaux de voyage', 'oauth.scope.journey:share.description': 'Créer, modifier et révoquer des liens de partage publics pour les journaux de voyage', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/gr/dashboard.ts b/shared/src/i18n/gr/dashboard.ts index 7f0f080f..ed7a018c 100644 --- a/shared/src/i18n/gr/dashboard.ts +++ b/shared/src/i18n/gr/dashboard.ts @@ -120,5 +120,51 @@ const dashboard: TranslationStrings = { 'dashboard.mobile.inMonths': 'Σε {count} μήνες', 'dashboard.mobile.completed': 'Ολοκληρώθηκε', 'dashboard.mobile.currencyConverter': 'Μετατροπέας Νομισμάτων', + 'dashboard.newTripSub': 'Plan a new trip from scratch', // en-fallback + 'dashboard.filter.planned': 'Planned', // en-fallback + 'dashboard.hero.badgeLive': 'LIVE NOW', // en-fallback + 'dashboard.hero.badgeToday': 'STARTS TODAY', // en-fallback + 'dashboard.hero.badgeTomorrow': 'TOMORROW', // en-fallback + 'dashboard.hero.badgeNext': 'UP NEXT', // en-fallback + 'dashboard.hero.badgeRecent': 'RECENT', // en-fallback + 'dashboard.hero.tripDates': 'Trip dates', // en-fallback + 'dashboard.hero.noDates': 'No dates set', // en-fallback + 'dashboard.hero.travelerOne': '{count} traveler', // en-fallback + 'dashboard.hero.travelerMany': '{count} travelers', // en-fallback + 'dashboard.hero.destinationOne': '{count} destination', // en-fallback + 'dashboard.hero.destinationMany': '{count} destinations', // en-fallback + 'dashboard.hero.dayUnitOne': 'day', // en-fallback + 'dashboard.hero.dayUnitMany': 'days', // en-fallback + 'dashboard.hero.dayLeft': 'Day left', // en-fallback + 'dashboard.hero.daysLeft': 'Days left', // en-fallback + 'dashboard.hero.lastDay': 'Last day', // en-fallback + 'dashboard.hero.untilStart': 'Until start', // en-fallback + 'dashboard.hero.startsIn': 'Trip starts in', // en-fallback + 'dashboard.atlas.countriesVisited': 'Atlas · Countries visited', // en-fallback + 'dashboard.atlas.ofTotal': 'of {total}', // en-fallback + 'dashboard.atlas.tripsTotal': 'Trips total', // en-fallback + 'dashboard.atlas.placesMapped': '{count} places mapped', // en-fallback + 'dashboard.atlas.daysTraveled': 'Days traveled', // en-fallback + 'dashboard.atlas.daysUnit': 'days', // en-fallback + 'dashboard.atlas.acrossAllTrips': 'across all trips', // en-fallback + 'dashboard.atlas.distanceFlown': 'Distance flown', // en-fallback + 'dashboard.atlas.kmUnit': 'km', // en-fallback + 'dashboard.atlas.aroundEquator': '≈ {count}× around the equator', // en-fallback + 'dashboard.card.idea': 'Idea', // en-fallback + 'dashboard.card.buddyOne': 'Buddy', // en-fallback + 'dashboard.fx.from': 'From', // en-fallback + 'dashboard.fx.to': 'To', // en-fallback + 'dashboard.fx.unavailable': 'Rate unavailable', // en-fallback + 'dashboard.tz.searchPlaceholder': 'Search timezone…', // en-fallback + 'dashboard.tz.empty': 'No other timezones yet — add one with +', // en-fallback + 'dashboard.upcoming.title': 'Upcoming reservations', // en-fallback + 'dashboard.upcoming.empty': 'Nothing booked yet.', // en-fallback + 'dashboard.aria.toggleView': 'Toggle view', // en-fallback + 'dashboard.aria.filter': 'Filter', // en-fallback + 'dashboard.aria.duplicate': 'Duplicate', // en-fallback + 'dashboard.aria.refreshRates': 'Refresh rates', // en-fallback + 'dashboard.aria.swapCurrencies': 'Swap currencies', // en-fallback + 'dashboard.aria.addTimezone': 'Add timezone', // en-fallback + 'dashboard.aria.removeTimezone': 'Remove {city}', // en-fallback }; export default dashboard; diff --git a/shared/src/i18n/gr/oauth.ts b/shared/src/i18n/gr/oauth.ts index 08f9f953..4b6ed2c4 100644 --- a/shared/src/i18n/gr/oauth.ts +++ b/shared/src/i18n/gr/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Διαχείριση συνδέσμων ταξιδιών', 'oauth.scope.journey:share.description': 'Δημιουργία, ενημέρωση και ανάκληση δημόσιων συνδέσμων κοινής χρήσης για ταξίδια', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/hu/dayplan.ts b/shared/src/i18n/hu/dayplan.ts index 3d9d54da..5742779d 100644 --- a/shared/src/i18n/hu/dayplan.ts +++ b/shared/src/i18n/hu/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Minden helyszín kiosztva', 'dayplan.mobile.noMatch': 'Nincs találat', 'dayplan.mobile.createNew': 'Új helyszín létrehozása', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/hu/journey.ts b/shared/src/i18n/hu/journey.ts index 01bf659c..76829423 100644 --- a/shared/src/i18n/hu/journey.ts +++ b/shared/src/i18n/hu/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Nem található album', 'journey.picker.selectDate': 'Dátum választása', 'journey.picker.search': 'Keresés', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/hu/oauth.ts b/shared/src/i18n/hu/oauth.ts index 0ae46942..9218f1f7 100644 --- a/shared/src/i18n/hu/oauth.ts +++ b/shared/src/i18n/hu/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Útinapló-linkek kezelése', 'oauth.scope.journey:share.description': 'Nyilvános megosztási linkek létrehozása, frissítése és visszavonása útinaplókhoz', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/id/dayplan.ts b/shared/src/i18n/id/dayplan.ts index 03d3bc75..3e6e6897 100644 --- a/shared/src/i18n/id/dayplan.ts +++ b/shared/src/i18n/id/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Semua tempat sudah ditugaskan', 'dayplan.mobile.noMatch': 'Tidak ditemukan', 'dayplan.mobile.createNew': 'Buat tempat baru', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/id/journey.ts b/shared/src/i18n/id/journey.ts index b4d3c941..2a262d5c 100644 --- a/shared/src/i18n/id/journey.ts +++ b/shared/src/i18n/id/journey.ts @@ -237,5 +237,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Tidak ada album ditemukan', 'journey.picker.selectDate': 'Pilih tanggal', 'journey.picker.search': 'Cari', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/id/oauth.ts b/shared/src/i18n/id/oauth.ts index b3e74f33..b73af708 100644 --- a/shared/src/i18n/id/oauth.ts +++ b/shared/src/i18n/id/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Kelola tautan Journey', 'oauth.scope.journey:share.description': 'Buat, perbarui, dan cabut tautan berbagi publik untuk Journey', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/it/dayplan.ts b/shared/src/i18n/it/dayplan.ts index bcaab98e..312f52ef 100644 --- a/shared/src/i18n/it/dayplan.ts +++ b/shared/src/i18n/it/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Tutti i luoghi assegnati', 'dayplan.mobile.noMatch': 'Nessun risultato', 'dayplan.mobile.createNew': 'Crea nuovo luogo', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/it/journey.ts b/shared/src/i18n/it/journey.ts index fbdb3744..94921c4e 100644 --- a/shared/src/i18n/it/journey.ts +++ b/shared/src/i18n/it/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Nessun album trovato', 'journey.picker.selectDate': 'Seleziona data', 'journey.picker.search': 'Cerca', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/it/oauth.ts b/shared/src/i18n/it/oauth.ts index c3910b40..c6736a46 100644 --- a/shared/src/i18n/it/oauth.ts +++ b/shared/src/i18n/it/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Gestisci link diari di viaggio', 'oauth.scope.journey:share.description': 'Crea, aggiorna e revoca link di condivisione pubblici per i diari di viaggio', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/ja/oauth.ts b/shared/src/i18n/ja/oauth.ts index ce4bf8e7..afcb6ad9 100644 --- a/shared/src/i18n/ja/oauth.ts +++ b/shared/src/i18n/ja/oauth.ts @@ -79,5 +79,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:write.description': '日記やエントリーの作成・編集・削除', 'oauth.scope.journey:share.label': '日記共有を管理', 'oauth.scope.journey:share.description': '公開共有リンクの作成・更新・無効化', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/ko/oauth.ts b/shared/src/i18n/ko/oauth.ts index e04c287e..94e33a26 100644 --- a/shared/src/i18n/ko/oauth.ts +++ b/shared/src/i18n/ko/oauth.ts @@ -83,5 +83,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Journey 링크 관리', 'oauth.scope.journey:share.description': 'Journey의 공개 공유 링크 만들기, 업데이트, 취소', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/nl/dayplan.ts b/shared/src/i18n/nl/dayplan.ts index e21bfcd2..d721adf9 100644 --- a/shared/src/i18n/nl/dayplan.ts +++ b/shared/src/i18n/nl/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Alle plaatsen toegewezen', 'dayplan.mobile.noMatch': 'Geen resultaat', 'dayplan.mobile.createNew': 'Nieuwe plaats aanmaken', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/nl/journey.ts b/shared/src/i18n/nl/journey.ts index 82151595..2d83b077 100644 --- a/shared/src/i18n/nl/journey.ts +++ b/shared/src/i18n/nl/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Geen albums gevonden', 'journey.picker.selectDate': 'Selecteer datum', 'journey.picker.search': 'Zoeken', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/nl/oauth.ts b/shared/src/i18n/nl/oauth.ts index 8b898223..caf8112a 100644 --- a/shared/src/i18n/nl/oauth.ts +++ b/shared/src/i18n/nl/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Reisverslag-links beheren', 'oauth.scope.journey:share.description': 'Publieke deellinks voor reisverslagen aanmaken, bijwerken en intrekken', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/pl/dayplan.ts b/shared/src/i18n/pl/dayplan.ts index 3c0845b9..23fe1a49 100644 --- a/shared/src/i18n/pl/dayplan.ts +++ b/shared/src/i18n/pl/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Wszystkie miejsca przypisane', 'dayplan.mobile.noMatch': 'Brak wyników', 'dayplan.mobile.createNew': 'Utwórz nowe miejsce', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/pl/journey.ts b/shared/src/i18n/pl/journey.ts index 83a70308..e6b7a8a8 100644 --- a/shared/src/i18n/pl/journey.ts +++ b/shared/src/i18n/pl/journey.ts @@ -235,5 +235,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Nie znaleziono albumów', 'journey.picker.selectDate': 'Wybierz datę', 'journey.picker.search': 'Szukaj', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/pl/oauth.ts b/shared/src/i18n/pl/oauth.ts index c53998f6..42b06018 100644 --- a/shared/src/i18n/pl/oauth.ts +++ b/shared/src/i18n/pl/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Zarządzaj linkami dzienników podróży', 'oauth.scope.journey:share.description': 'Twórz, aktualizuj i unieważniaj publiczne linki udostępniania dzienników podróży', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/ru/dayplan.ts b/shared/src/i18n/ru/dayplan.ts index 5ffb7fb6..1a7c2644 100644 --- a/shared/src/i18n/ru/dayplan.ts +++ b/shared/src/i18n/ru/dayplan.ts @@ -42,5 +42,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': 'Все места распределены', 'dayplan.mobile.noMatch': 'Нет совпадений', 'dayplan.mobile.createNew': 'Создать новое место', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/ru/journey.ts b/shared/src/i18n/ru/journey.ts index f8ef154e..97f8f376 100644 --- a/shared/src/i18n/ru/journey.ts +++ b/shared/src/i18n/ru/journey.ts @@ -236,5 +236,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': 'Альбомы не найдены', 'journey.picker.selectDate': 'Выберите дату', 'journey.picker.search': 'Поиск', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/ru/oauth.ts b/shared/src/i18n/ru/oauth.ts index 8454d68c..af2860ec 100644 --- a/shared/src/i18n/ru/oauth.ts +++ b/shared/src/i18n/ru/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Управление ссылками на путешествия', 'oauth.scope.journey:share.description': 'Создание, обновление и отзыв публичных ссылок для путешествий', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/tr/oauth.ts b/shared/src/i18n/tr/oauth.ts index fd216f59..70936b1a 100644 --- a/shared/src/i18n/tr/oauth.ts +++ b/shared/src/i18n/tr/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Journey bağlantılarını yönet', 'oauth.scope.journey:share.description': "Journey'ler için herkese açık paylaşım bağlantıları oluştur, güncelle ve iptal et", + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/uk/oauth.ts b/shared/src/i18n/uk/oauth.ts index 18a51534..b1462112 100644 --- a/shared/src/i18n/uk/oauth.ts +++ b/shared/src/i18n/uk/oauth.ts @@ -95,5 +95,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:share.label': 'Керування посиланнями на подорожі', 'oauth.scope.journey:share.description': 'Створення, оновлення і відкликання публічних посилань на подорожі', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/zh-TW/dayplan.ts b/shared/src/i18n/zh-TW/dayplan.ts index dbc99146..7cfd4a47 100644 --- a/shared/src/i18n/zh-TW/dayplan.ts +++ b/shared/src/i18n/zh-TW/dayplan.ts @@ -37,5 +37,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': '所有地點已分配', 'dayplan.mobile.noMatch': '無匹配', 'dayplan.mobile.createNew': '建立新地點', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/zh-TW/journey.ts b/shared/src/i18n/zh-TW/journey.ts index 40063142..c78ff829 100644 --- a/shared/src/i18n/zh-TW/journey.ts +++ b/shared/src/i18n/zh-TW/journey.ts @@ -225,5 +225,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': '未找到相簿', 'journey.picker.selectDate': '選擇日期', 'journey.picker.search': '搜尋', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/zh-TW/oauth.ts b/shared/src/i18n/zh-TW/oauth.ts index f96c4cd7..c70c2d73 100644 --- a/shared/src/i18n/zh-TW/oauth.ts +++ b/shared/src/i18n/zh-TW/oauth.ts @@ -73,5 +73,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:write.description': '建立、更新及刪除旅程及其條目', 'oauth.scope.journey:share.label': '管理旅程連結', 'oauth.scope.journey:share.description': '建立、更新及撤銷旅程的公開分享連結', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth; diff --git a/shared/src/i18n/zh/dayplan.ts b/shared/src/i18n/zh/dayplan.ts index ebd90f37..6a6a64f3 100644 --- a/shared/src/i18n/zh/dayplan.ts +++ b/shared/src/i18n/zh/dayplan.ts @@ -37,5 +37,7 @@ const dayplan: TranslationStrings = { 'dayplan.mobile.allAssigned': '所有地点已分配', 'dayplan.mobile.noMatch': '无匹配', 'dayplan.mobile.createNew': '创建新地点', + 'dayplan.expandAll': 'Expand all days', // en-fallback + 'dayplan.collapseAll': 'Collapse all days', // en-fallback }; export default dayplan; diff --git a/shared/src/i18n/zh/journey.ts b/shared/src/i18n/zh/journey.ts index b73defde..d3510b70 100644 --- a/shared/src/i18n/zh/journey.ts +++ b/shared/src/i18n/zh/journey.ts @@ -225,5 +225,10 @@ const journey: TranslationStrings = { 'journey.picker.noAlbums': '未找到相册', 'journey.picker.selectDate': '选择日期', 'journey.picker.search': '搜索', + 'journey.detail.journeyTab': 'Journey', // en-fallback + 'journey.contributors.remove': 'Remove contributor', // en-fallback + '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 }; export default journey; diff --git a/shared/src/i18n/zh/oauth.ts b/shared/src/i18n/zh/oauth.ts index 87300b17..2fc581a5 100644 --- a/shared/src/i18n/zh/oauth.ts +++ b/shared/src/i18n/zh/oauth.ts @@ -73,5 +73,29 @@ const oauth: TranslationStrings = { 'oauth.scope.journey:write.description': '创建、更新和删除旅程及其条目', 'oauth.scope.journey:share.label': '管理旅程链接', 'oauth.scope.journey:share.description': '创建、更新和撤销旅程的公开分享链接', + 'oauth.authorize.authorizing': 'Authorizing…', // en-fallback + 'oauth.authorize.loading': 'Loading…', // en-fallback + 'oauth.authorize.errorTitle': 'Authorization Error', // en-fallback + 'oauth.authorize.loginTitle': 'Sign in to continue', // en-fallback + 'oauth.authorize.loginDescription': + '{client} wants access to your TREK account. Please sign in first.', // en-fallback + 'oauth.authorize.loginButton': 'Sign in to TREK', // en-fallback + 'oauth.authorize.requestLabel': 'Authorization Request', // en-fallback + 'oauth.authorize.requestDescription': + 'This application is requesting access to your TREK account.', // en-fallback + 'oauth.authorize.trustNote': + 'Only grant access to applications you trust. Your data stays on your server.', // en-fallback + 'oauth.authorize.selectScope': 'Select at least one scope', // en-fallback + 'oauth.authorize.approveOneScope': 'Approve ({count} scope)', // en-fallback + 'oauth.authorize.approveManyScopes': 'Approve ({count} scopes)', // en-fallback + 'oauth.authorize.approveAccess': 'Approve Access', // en-fallback + 'oauth.authorize.deny': 'Deny', // en-fallback + 'oauth.authorize.choosePermissions': 'Choose which permissions to grant', // en-fallback + 'oauth.authorize.permissionsRequested': 'Permissions requested', // en-fallback + 'oauth.authorize.alwaysIncluded': 'Always included', // en-fallback + 'oauth.authorize.alwaysTool.listTrips': + 'List your trips so the AI can discover trip IDs', // en-fallback + 'oauth.authorize.alwaysTool.getTripSummary': + 'Read a trip overview needed to use any other tool', // en-fallback }; export default oauth;