diff --git a/frontend/src/lib/flights.ts b/frontend/src/lib/flights.ts new file mode 100644 index 00000000..d38c8682 --- /dev/null +++ b/frontend/src/lib/flights.ts @@ -0,0 +1,30 @@ +import type {i18n as I18nextType} from 'i18next'; + +/** + * Return a verbose translated name for the specified flight. + */ +export function flightName( + flight: { + id: number; + number?: number; + launchAt?: string; + landingAt?: string; + }, + i18n: I18nextType, +): string { + let name = + flight.number !== undefined + ? i18n.t('flight.snippet--flight-with-number', { + number: flight.number, + }) + : i18n.t('flight.snippet--flight-with-id', {id: flight.id}); + if (flight.launchAt !== undefined) { + name += ' '; + name += i18n.t('flight.snippet--from', {location: flight.launchAt}); + } + if (flight.landingAt !== undefined) { + name += ' '; + name += i18n.t('flight.snippet--to', {location: flight.landingAt}); + } + return name; +} diff --git a/frontend/src/routes/flights/+page.svelte b/frontend/src/routes/flights/+page.svelte index d6637a77..76d4daff 100644 --- a/frontend/src/routes/flights/+page.svelte +++ b/frontend/src/routes/flights/+page.svelte @@ -5,6 +5,7 @@ import Flashes from '$lib/components/Flashes.svelte'; import MessageModal from '$lib/components/MessageModal.svelte'; import XContestSummary from '$lib/components/XContestSummary.svelte'; + import {flightName} from '$lib/flights'; import {formatDate, formatDistance, formatDuration} from '$lib/formatters'; import {i18n} from '$lib/i18n'; import {addFlash} from '$lib/stores'; @@ -22,23 +23,15 @@ let deleting = false; let deleteError: {type: 'authentication'} | {type: 'api-error'; message: string} | undefined; - function flightName(flight: FlightListItem): string { - let name = `Flight ${ - flight.number !== undefined ? `${flight.number}` : `with ID ${flight.id}` - }`; - if (flight.launchAt !== undefined) { - const location = data.locations[flight.launchAt]; - if (location !== undefined) { - name += ` from ${location.name}`; - } - } - if (flight.landingAt !== undefined) { - const location = data.locations[flight.landingAt]; - if (location !== undefined) { - name += ` to ${location.name}`; - } - } - return name; + function flightListItemName(f: FlightListItem): string { + return flightName( + { + ...f, + launchAt: f.launchAt === undefined ? undefined : data.locations[f.launchAt]?.name, + landingAt: f.landingAt === undefined ? undefined : data.locations[f.landingAt]?.name, + }, + $i18n, + ); } async function deleteFlight(): Promise { @@ -51,7 +44,9 @@ case 204: // Success addFlash({ - message: `${flightName(flightToDelete)} successfully deleted`, + message: $i18n.t('flights.prose--delete-success', { + flight: flightListItemName(flightToDelete), + }), severity: 'success', icon: 'fa-trash-can', }); @@ -99,25 +94,23 @@ (deleteError = undefined)} /> {:else if flightToDelete !== undefined}
- - + +
{/if} @@ -131,30 +124,34 @@ -

Your Flights

+

{$i18n.t('flights.title--your-flights')}

- You've logged {data.flights.length} flight{data.flights.length === 1 ? '' : 's'} so far! + {$i18n.t('flights.prose--flight-log-count', {count: data.flights.length})}

- Add flight - Import from CSV + + {$i18n.t('flights.action--add-flight')} + + {$i18n.t('flights.action--import-csv')}

- - - - - - - - + + + + + + + + @@ -200,12 +197,16 @@ />
#DateGliderLaunchLandingDurationGPS DistanceXContestActions{$i18n.t('flights.column--date')}{$i18n.t('flights.column--glider')}{$i18n.t('flights.column--launch')}{$i18n.t('flights.column--landing')}{$i18n.t('flights.column--duration')}{$i18n.t('flights.column--track-distance')}{$i18n.t('flights.column--xcontest')}{$i18n.t('flights.column--actions')}
- + @@ -213,7 +214,7 @@