feat(client): add the Startup section to General settings

Desktop and mobile both get it, in the style of the file they live in -
the On/Off button pairs on desktop, segments and a picker sheet on mobile.
The tab picker only appears once "Active trip" is chosen, since there is
nothing for it to mean otherwise.

Labels come from the same keys the planner's tab bar uses, so the picker
can never name a tab differently from the tab itself.
This commit is contained in:
Maurice
2026-08-08 21:03:57 +02:00
committed by Maurice
parent 44eff7177e
commit 6bf2e0708d
27 changed files with 379 additions and 4 deletions
@@ -1,4 +1,4 @@
// FE-COMP-DISPLAY-001 to FE-COMP-DISPLAY-048
// FE-COMP-DISPLAY-001 to FE-COMP-DISPLAY-052
import { render, screen, within, fireEvent } from '../../../tests/helpers/render';
import userEvent from '@testing-library/user-event';
import { http, HttpResponse } from 'msw';
@@ -395,3 +395,52 @@ describe('DisplaySettingsTab – Map and privacy toggles', () => {
expect(screen.getAllByText('Nope').length).toBeGreaterThan(0);
});
});
describe('DisplaySettingsTab – startup destination', () => {
it('FE-COMP-DISPLAY-049: defaults to the dashboard and hides the tab picker', () => {
seedStore(useSettingsStore, { settings: buildSettings() });
render(<DisplaySettingsTab />);
const block = optionBlock(/^Start page$/);
expect(within(block).getByText('Dashboard').closest('button')!.style.border).toContain('var(--text-primary)');
// Nothing to pick a tab for while TREK opens on the dashboard.
expect(screen.queryByText('Start tab')).not.toBeInTheDocument();
});
it('FE-COMP-DISPLAY-050: choosing the active trip saves it and reveals the tab picker', async () => {
const user = userEvent.setup();
const updateSetting = vi.fn().mockResolvedValue(undefined);
seedStore(useSettingsStore, { settings: buildSettings(), updateSetting });
render(<DisplaySettingsTab />);
await user.click(within(optionBlock(/^Start page$/)).getByText('Active trip'));
expect(updateSetting).toHaveBeenCalledWith('start_page', 'active_trip');
});
it('FE-COMP-DISPLAY-051: with the active trip chosen, the tab picker stores the planner tab id', async () => {
const user = userEvent.setup();
const updateSetting = vi.fn().mockResolvedValue(undefined);
seedStore(useSettingsStore, {
settings: buildSettings({ start_page: 'active_trip', start_trip_tab: 'plan' }),
updateSetting,
});
render(<DisplaySettingsTab />);
await user.click(screen.getByRole('button', { name: 'Plan' }));
await user.click(await screen.findByText('Costs'));
// The German legacy id, not the English label the user sees.
expect(updateSetting).toHaveBeenCalledWith('start_trip_tab', 'finanzplan');
});
it('FE-COMP-DISPLAY-052: a rejected start-page change surfaces the error', async () => {
const user = userEvent.setup();
seedFailing('Start locked');
render(<><ToastContainer /><DisplaySettingsTab /></>);
await user.click(within(optionBlock(/^Start page$/)).getByText('Active trip'));
await screen.findByText('Start locked');
});
});
@@ -1,11 +1,13 @@
import React, { useState, useEffect, useRef } from 'react'
import { Languages, Map, ChevronDown, Check } from 'lucide-react'
import { Languages, Map, ChevronDown, Check, Rocket } from 'lucide-react'
import { SUPPORTED_LANGUAGES, useTranslation } from '../../i18n'
import { useSettingsStore, DEFAULT_SETTINGS } from '../../store/settingsStore'
import { useToast } from '../shared/Toast'
import CustomSelect from '../shared/CustomSelect'
import { SYMBOLS, currenciesWith } from '../Budget/BudgetPanel.constants'
import Section from './Section'
import { TRIP_TAB_IDS, TRIP_TAB_LABEL_KEYS } from '../../constants/tripTabs'
import { DEFAULT_START_PAGE, DEFAULT_START_TRIP_TAB } from '../../utils/startDestination'
import type { DistanceUnit } from '../../types'
export default function DisplaySettingsTab(): React.ReactElement {
@@ -34,8 +36,60 @@ export default function DisplaySettingsTab(): React.ReactElement {
setDistanceUnit(settings.distance_unit || DEFAULT_SETTINGS.distance_unit)
}, [settings.distance_unit])
const startPage = settings.start_page === 'active_trip' ? 'active_trip' : DEFAULT_START_PAGE
const startTripTab = settings.start_trip_tab || DEFAULT_START_TRIP_TAB
return (
<>
<Section title={t('settings.general.startup')} icon={Rocket}>
{/* Where opening TREK lands */}
<div>
<label className="block text-sm font-medium mb-2 text-content-secondary">{t('settings.startPage')}</label>
<div className="flex gap-3">
{([
{ value: 'dashboard', label: t('settings.startPageDashboard') },
{ value: 'active_trip', label: t('settings.startPageActiveTrip') },
] as const).map(opt => (
<button
key={opt.value}
onClick={async () => {
try { await updateSetting('start_page', opt.value) }
catch (e: unknown) { toast.error(e instanceof Error ? e.message : t('common.error')) }
}}
style={{
display: 'flex', alignItems: 'center', gap: 8,
padding: '10px 20px', borderRadius: 10, cursor: 'pointer',
fontFamily: 'inherit', fontSize: 'calc(14px * var(--fs-scale-body, 1))', fontWeight: 500,
border: startPage === opt.value ? '2px solid var(--text-primary)' : '2px solid var(--border-primary)',
background: startPage === opt.value ? 'var(--bg-hover)' : 'var(--bg-card)',
color: 'var(--text-primary)',
transition: 'all 0.15s',
}}
>
{opt.label}
</button>
))}
</div>
<p className="text-xs mt-1 text-content-faint">{t('settings.startPageHint')}</p>
</div>
{/* Which planner tab the trip opens on — only meaningful for 'active_trip' */}
{startPage === 'active_trip' && (
<div>
<label className="block text-sm font-medium mb-2 text-content-secondary">{t('settings.startTripTab')}</label>
<CustomSelect
value={startTripTab}
onChange={async v => {
try { await updateSetting('start_trip_tab', String(v)) }
catch (e: unknown) { toast.error(e instanceof Error ? e.message : t('common.error')) }
}}
options={TRIP_TAB_IDS.map(id => ({ value: id, label: t(TRIP_TAB_LABEL_KEYS[id]) }))}
/>
<p className="text-xs text-content-faint mt-2">{t('settings.startTripTabHint')}</p>
</div>
)}
</Section>
<Section title={t('settings.general.languageRegion')} icon={Languages}>
{/* Display currency */}
<div>
@@ -1,9 +1,11 @@
import { useState } from 'react'
import { ChevronDown, Languages, Map } from 'lucide-react'
import { ChevronDown, Languages, Map, Rocket } from 'lucide-react'
import { useTranslation, SUPPORTED_LANGUAGES } from '../../../i18n'
import { useSettingsStore } from '../../../store/settingsStore'
import { useToast } from '../../../components/shared/Toast'
import { SYMBOLS, currenciesWith } from '../../../components/Budget/BudgetPanel.constants'
import { TRIP_TAB_IDS, TRIP_TAB_LABEL_KEYS, isTripTabId } from '../../../constants/tripTabs'
import { DEFAULT_START_PAGE, DEFAULT_START_TRIP_TAB, type StartPage } from '../../../utils/startDestination'
import type { Settings, DistanceUnit } from '../../../types'
import { MSetCard, MSetEyebrow, MSetSelectRow, MSetSegments, MSetRow } from './MSettingsUi'
import MToggle from '../../components/MToggle'
@@ -19,6 +21,7 @@ export default function MSettingsGeneral() {
const { settings, updateSetting } = useSettingsStore()
const [currencyOpen, setCurrencyOpen] = useState(false)
const [langOpen, setLangOpen] = useState(false)
const [startTabOpen, setStartTabOpen] = useState(false)
const save = async (key: keyof Settings, value: Settings[keyof Settings]) => {
try {
@@ -28,6 +31,8 @@ export default function MSettingsGeneral() {
}
}
const startPage: StartPage = settings.start_page === 'active_trip' ? 'active_trip' : DEFAULT_START_PAGE
const startTripTab = isTripTabId(settings.start_trip_tab) ? settings.start_trip_tab : DEFAULT_START_TRIP_TAB
const currency = settings.default_currency || ''
const currencyLabel = currency ? `${currency} — ${SYMBOLS[currency] || currency}` : t('settings.currencyTrip')
const language = SUPPORTED_LANGUAGES.find((l) => l.value === settings.language) || SUPPORTED_LANGUAGES[0]
@@ -73,7 +78,29 @@ export default function MSettingsGeneral() {
return (
<>
<MSetCard title={t('settings.general.languageRegion')} icon={Languages}>
<MSetCard title={t('settings.general.startup')} icon={Rocket}>
<MSetEyebrow className="mb-[6px]">{t('settings.startPage')}</MSetEyebrow>
<MSetSegments<StartPage>
value={startPage}
onChange={(v) => save('start_page', v)}
options={[
{ value: 'dashboard', label: t('settings.startPageDashboard') },
{ value: 'active_trip', label: t('settings.startPageActiveTrip') },
]}
/>
{startPage === 'active_trip' && (
<>
<MSetEyebrow className="mb-[5px] mt-[14px]">{t('settings.startTripTab')}</MSetEyebrow>
<MSetSelectRow
label={t(TRIP_TAB_LABEL_KEYS[startTripTab])}
trailing={chevron}
onClick={() => setStartTabOpen(true)}
/>
</>
)}
</MSetCard>
<MSetCard title={t('settings.general.languageRegion')} icon={Languages} className="mt-3">
<MSetEyebrow className="mb-[5px]">{t('settings.currency')}</MSetEyebrow>
<MSetSelectRow label={currencyLabel} trailing={chevron} onClick={() => setCurrencyOpen(true)} />
@@ -150,6 +177,15 @@ export default function MSettingsGeneral() {
onSelect={(v) => save('language', v)}
options={SUPPORTED_LANGUAGES.map((l) => ({ value: l.value, label: l.label }))}
/>
<MSetPickerSheet
open={startTabOpen}
onClose={() => setStartTabOpen(false)}
title={t('settings.startTripTab')}
value={startTripTab}
onSelect={(v) => save('start_trip_tab', v)}
options={TRIP_TAB_IDS.map((id) => ({ value: id, label: t(TRIP_TAB_LABEL_KEYS[id]) }))}
/>
</>
)
}
@@ -156,4 +156,38 @@ describe('MSettingsGeneral', () => {
await user.click(screen.getByRole('button', { name: '°F Fahrenheit' }));
await screen.findByText('Error');
});
it('FE-MOB-SET-012: the startup card defaults to the dashboard and hides the tab row', () => {
render(<MSettingsGeneral />);
expect(screen.getByText('Startup')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Dashboard' })).toHaveAttribute('aria-pressed', 'true');
expect(screen.queryByText('Start tab')).not.toBeInTheDocument();
});
it('FE-MOB-SET-013: picking the active trip persists it and reveals the tab row', async () => {
const user = userEvent.setup();
const updateSetting = vi.fn().mockResolvedValue(undefined);
seedStore(useSettingsStore, { settings: buildSettings({ language: 'en' }), updateSetting });
render(<MSettingsGeneral />);
await user.click(screen.getByRole('button', { name: 'Active trip' }));
expect(updateSetting).toHaveBeenCalledWith('start_page', 'active_trip');
});
it('FE-MOB-SET-014: the start-tab sheet saves the planner tab id behind the label', async () => {
const user = userEvent.setup();
const updateSetting = vi.fn().mockResolvedValue(undefined);
seedStore(useSettingsStore, {
settings: buildSettings({ language: 'en', start_page: 'active_trip', start_trip_tab: 'plan' }),
updateSetting,
});
render(<MSettingsGeneral />);
expect(screen.getByText('Start tab')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Plan' }));
await user.click(await screen.findByText('Costs'));
expect(updateSetting).toHaveBeenCalledWith('start_trip_tab', 'finanzplan');
});
});
+9
View File
@@ -431,6 +431,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'مخفي',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'البدء',
'settings.startPage': 'صفحة البدء',
'settings.startPageDashboard': 'لوحة التحكم',
'settings.startPageActiveTrip': 'الرحلة النشطة',
'settings.startPageHint':
'يفتح TREK مباشرةً على الرحلة الجارية، وإن لم توجد فعلى الرحلة القادمة التالية. وهي نفس الرحلة التي تبرزها لوحة التحكم.',
'settings.startTripTab': 'علامة تبويب البدء',
'settings.startTripTabHint':
'علامة التبويب التي تفتح بها الرحلة. إذا كانت تابعة لإضافة أوقفت تشغيلها، تُفتح الخطة بدلاً منها.',
// ── Offline (#1135)
'settings.offline.cache.title': 'ذاكرة التخزين المؤقت دون اتصال',
+9
View File
@@ -446,6 +446,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Oculto',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Inicialização',
'settings.startPage': 'Página inicial',
'settings.startPageDashboard': 'Painel',
'settings.startPageActiveTrip': 'Viagem ativa',
'settings.startPageHint':
'O TREK abre direto na viagem que está acontecendo, ou na próxima que começa. É a mesma viagem que o painel destaca.',
'settings.startTripTab': 'Aba inicial',
'settings.startTripTabHint':
'A aba com que a viagem abre. Se ela pertencer a um complemento desativado, abre a visão de plano.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Cache offline',
+9
View File
@@ -429,6 +429,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Ocult',
'settings.general.languageRegion': 'Idioma i regió',
'settings.general.travelMap': 'Viatge i mapa',
'settings.general.startup': 'Inici',
'settings.startPage': "Pàgina d'inici",
'settings.startPageDashboard': 'Tauler',
'settings.startPageActiveTrip': 'Viatge actiu',
'settings.startPageHint':
'TREK obre directament el viatge que està en curs, o el següent que comença. És el mateix viatge que destaca el tauler.',
'settings.startTripTab': "Pestanya d'inici",
'settings.startTripTabHint':
"La pestanya amb què s'obre el viatge. Si pertany a un complement desactivat, s'obre la vista de planificació.",
'settings.offline.cache.title': 'Memòria cau fora de línia',
'settings.offline.mode.title': 'Mode fora de línia',
'settings.offline.mode.force': 'Forçar mode fora de línia',
+9
View File
@@ -439,6 +439,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Skryto',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Spuštění',
'settings.startPage': 'Úvodní stránka',
'settings.startPageDashboard': 'Přehled',
'settings.startPageActiveTrip': 'Aktivní cesta',
'settings.startPageHint':
'TREK se otevře rovnou na cestě, která právě probíhá, jinak na nejbližší nadcházející. Je to táž cesta, kterou zvýrazňuje přehled.',
'settings.startTripTab': 'Úvodní karta',
'settings.startTripTabHint':
'Karta, kterou se cesta otevře. Pokud patří k vypnutému doplňku, otevře se místo ní plán.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Offline mezipaměť',
+9
View File
@@ -448,6 +448,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Ausgeblendet',
'settings.general.languageRegion': 'Sprache & Region',
'settings.general.travelMap': 'Reise & Karte',
'settings.general.startup': 'Start',
'settings.startPage': 'Startseite',
'settings.startPageDashboard': 'Dashboard',
'settings.startPageActiveTrip': 'Aktive Reise',
'settings.startPageHint':
'TREK öffnet direkt die Reise, die gerade läuft, sonst die nächste anstehende. Also genau die Reise, die auch das Dashboard hervorhebt.',
'settings.startTripTab': 'Start-Tab',
'settings.startTripTabHint':
'Der Tab, mit dem die Reise öffnet. Gehört er zu einem ausgeschalteten Addon, öffnet stattdessen die Planung.',
// ── Offline (#1135) ────────────────────────────────────────────────────────
'settings.offline.cache.title': 'Offline-Cache',
+9
View File
@@ -447,6 +447,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Hidden',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Startup',
'settings.startPage': 'Start page',
'settings.startPageDashboard': 'Dashboard',
'settings.startPageActiveTrip': 'Active trip',
'settings.startPageHint':
'TREK opens straight in the trip running today, or the next one coming up. That is the same trip the dashboard features.',
'settings.startTripTab': 'Start tab',
'settings.startTripTabHint':
'The tab the trip opens on. If it belongs to an addon you switched off, the plan view opens instead.',
// ── Offline (#1135) ────────────────────────────────────────────────────────
'settings.offline.cache.title': 'Offline cache',
+9
View File
@@ -447,6 +447,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Oculto',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Inicio',
'settings.startPage': 'Página de inicio',
'settings.startPageDashboard': 'Panel',
'settings.startPageActiveTrip': 'Viaje activo',
'settings.startPageHint':
'TREK abre directamente el viaje que está en curso o el siguiente que empieza. Es el mismo viaje que destaca el panel.',
'settings.startTripTab': 'Pestaña de inicio',
'settings.startTripTabHint':
'La pestaña con la que se abre el viaje. Si pertenece a un complemento desactivado, se abre la vista de plan.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Caché offline',
+9
View File
@@ -453,6 +453,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Masqué',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Démarrage',
'settings.startPage': 'Page de démarrage',
'settings.startPageDashboard': 'Tableau de bord',
'settings.startPageActiveTrip': 'Voyage en cours',
'settings.startPageHint':
"TREK s'ouvre directement sur le voyage en cours, ou sur le prochain à venir. C'est le même voyage que celui mis en avant sur le tableau de bord.",
'settings.startTripTab': 'Onglet de démarrage',
'settings.startTripTabHint':
"L'onglet sur lequel le voyage s'ouvre. S'il appartient à un module désactivé, la vue Plan s'ouvre à la place.",
// ── Offline (#1135)
'settings.offline.cache.title': 'Cache hors ligne',
+9
View File
@@ -456,6 +456,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Κρυφό',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Εκκίνηση',
'settings.startPage': 'Αρχική σελίδα',
'settings.startPageDashboard': 'Πίνακας ελέγχου',
'settings.startPageActiveTrip': 'Ενεργό ταξίδι',
'settings.startPageHint':
'Το TREK ανοίγει απευθείας στο ταξίδι που είναι σε εξέλιξη ή στο επόμενο που ξεκινά. Είναι το ίδιο ταξίδι που προβάλλει ο πίνακας ελέγχου.',
'settings.startTripTab': 'Αρχική καρτέλα',
'settings.startTripTabHint':
'Η καρτέλα με την οποία ανοίγει το ταξίδι. Αν ανήκει σε απενεργοποιημένο πρόσθετο, ανοίγει το πλάνο.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Προσωρινή μνήμη εκτός σύνδεσης',
+9
View File
@@ -446,6 +446,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Rejtett',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Indítás',
'settings.startPage': 'Kezdőoldal',
'settings.startPageDashboard': 'Irányítópult',
'settings.startPageActiveTrip': 'Aktív utazás',
'settings.startPageHint':
'A TREK egyből a most zajló utazást nyitja meg, vagy a következőt, amelyik indul. Ugyanaz az utazás, amelyet az irányítópult is kiemel.',
'settings.startTripTab': 'Kezdő fül',
'settings.startTripTabHint':
'Az a fül, amellyel az utazás megnyílik. Ha kikapcsolt bővítményhez tartozik, helyette a terv nézet nyílik meg.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Offline gyorsítótár',
+9
View File
@@ -444,6 +444,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Tersembunyi',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Mulai',
'settings.startPage': 'Halaman awal',
'settings.startPageDashboard': 'Dasbor',
'settings.startPageActiveTrip': 'Perjalanan aktif',
'settings.startPageHint':
'TREK langsung membuka perjalanan yang sedang berlangsung, atau yang paling dekat akan dimulai. Perjalanan yang sama yang disorot dasbor.',
'settings.startTripTab': 'Tab awal',
'settings.startTripTabHint':
'Tab yang dibuka bersama perjalanan. Jika tab itu milik addon yang dimatikan, tampilan rencana yang dibuka.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Cache offline',
+9
View File
@@ -446,6 +446,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Nascosto',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Avvio',
'settings.startPage': 'Pagina iniziale',
'settings.startPageDashboard': 'Dashboard',
'settings.startPageActiveTrip': 'Viaggio attivo',
'settings.startPageHint':
'TREK si apre direttamente sul viaggio in corso, o sul prossimo in arrivo. È lo stesso viaggio che la dashboard mette in evidenza.',
'settings.startTripTab': 'Scheda iniziale',
'settings.startTripTabHint':
'La scheda con cui si apre il viaggio. Se appartiene a un componente aggiuntivo disattivato, si apre la vista Programma.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Cache offline',
+8
View File
@@ -419,6 +419,14 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': '非表示',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': '起動',
'settings.startPage': '起動時の画面',
'settings.startPageDashboard': 'ダッシュボード',
'settings.startPageActiveTrip': '進行中の旅行',
'settings.startPageHint':
'TREK を開くと、進行中の旅行、なければ次に始まる旅行が直接開きます。ダッシュボードで大きく表示される旅行と同じです。',
'settings.startTripTab': '起動時のタブ',
'settings.startTripTabHint': '旅行を開くタブです。無効にしたアドオンのタブの場合は、代わりに計画が開きます。',
// ── Offline (#1135)
'settings.offline.cache.title': 'オフラインキャッシュ',
+8
View File
@@ -433,6 +433,14 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': '숨김',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': '시작',
'settings.startPage': '시작 화면',
'settings.startPageDashboard': '대시보드',
'settings.startPageActiveTrip': '진행 중인 여행',
'settings.startPageHint':
'TREK을 열면 지금 진행 중인 여행, 없으면 다음에 시작하는 여행으로 바로 이동합니다. 대시보드가 강조하는 여행과 같습니다.',
'settings.startTripTab': '시작 탭',
'settings.startTripTabHint': '여행이 열릴 탭입니다. 꺼 둔 애드온의 탭이면 대신 계획이 열립니다.',
// ── Offline (#1135)
'settings.offline.cache.title': '오프라인 캐시',
+9
View File
@@ -447,6 +447,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Verborgen',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Opstarten',
'settings.startPage': 'Startpagina',
'settings.startPageDashboard': 'Dashboard',
'settings.startPageActiveTrip': 'Actieve reis',
'settings.startPageHint':
'TREK opent direct de reis die nu loopt, of anders de eerstvolgende. Dat is dezelfde reis die het dashboard uitlicht.',
'settings.startTripTab': 'Starttabblad',
'settings.startTripTabHint':
'Het tabblad waarmee de reis opent. Hoort het bij een uitgeschakelde add-on, dan opent het plan in plaats daarvan.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Offline cache',
+9
View File
@@ -446,6 +446,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Ukryte',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Uruchamianie',
'settings.startPage': 'Strona startowa',
'settings.startPageDashboard': 'Panel',
'settings.startPageActiveTrip': 'Aktywna podróż',
'settings.startPageHint':
'TREK otwiera się od razu na podróży, która właśnie trwa, albo na najbliższej nadchodzącej. To ta sama podróż, którą wyróżnia panel.',
'settings.startTripTab': 'Karta startowa',
'settings.startTripTabHint':
'Karta, na której otwiera się podróż. Jeśli należy do wyłączonego dodatku, otworzy się widok planu.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Pamięć podręczna offline',
+9
View File
@@ -447,6 +447,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Скрыто',
'settings.general.languageRegion': 'Язык и регион',
'settings.general.travelMap': 'Карта и путешествия',
'settings.general.startup': 'Запуск',
'settings.startPage': 'Стартовая страница',
'settings.startPageDashboard': 'Панель управления',
'settings.startPageActiveTrip': 'Активная поездка',
'settings.startPageHint':
'TREK сразу открывает поездку, которая идёт сейчас, иначе ближайшую предстоящую. Это та же поездка, которую выделяет панель управления.',
'settings.startTripTab': 'Стартовая вкладка',
'settings.startTripTabHint':
'Вкладка, с которой открывается поездка. Если она относится к отключённому дополнению, откроется план.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Офлайн-кэш',
+9
View File
@@ -445,6 +445,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Dold',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Start',
'settings.startPage': 'Startsida',
'settings.startPageDashboard': 'Översikt',
'settings.startPageActiveTrip': 'Aktiv resa',
'settings.startPageHint':
'TREK öppnar direkt i resan som pågår, annars i nästa som börjar. Det är samma resa som översikten lyfter fram.',
'settings.startTripTab': 'Startflik',
'settings.startTripTabHint':
'Fliken som resan öppnas med. Hör den till ett avstängt tillägg öppnas planvyn i stället.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Offline-cache',
+9
View File
@@ -443,6 +443,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Gizli',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Başlangıç',
'settings.startPage': 'Başlangıç sayfası',
'settings.startPageDashboard': 'Pano',
'settings.startPageActiveTrip': 'Aktif seyahat',
'settings.startPageHint':
'TREK doğrudan devam eden seyahati, yoksa sıradaki seyahati açar. Panonun öne çıkardığı seyahatin aynısı.',
'settings.startTripTab': 'Başlangıç sekmesi',
'settings.startTripTabHint':
'Seyahatin açılacağı sekme. Kapalı bir eklentiye aitse onun yerine plan görünümü açılır.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Çevrimdışı önbellek',
+9
View File
@@ -446,6 +446,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Приховано',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': 'Запуск',
'settings.startPage': 'Стартова сторінка',
'settings.startPageDashboard': 'Панель',
'settings.startPageActiveTrip': 'Активна поїздка',
'settings.startPageHint':
'TREK одразу відкриває поїздку, яка триває зараз, інакше найближчу майбутню. Це та сама поїздка, яку виділяє панель.',
'settings.startTripTab': 'Стартова вкладка',
'settings.startTripTabHint':
'Вкладка, з якою відкривається поїздка. Якщо вона належить до вимкненого доповнення, натомість відкриється план.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Офлайн-кеш',
+9
View File
@@ -448,6 +448,15 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': 'Đã ẩn',
'settings.general.languageRegion': 'Ngôn ngữ & khu vực',
'settings.general.travelMap': 'Du lịch & bản đồ',
'settings.general.startup': 'Khởi động',
'settings.startPage': 'Trang khởi động',
'settings.startPageDashboard': 'Bảng điều khiển',
'settings.startPageActiveTrip': 'Chuyến đi đang diễn ra',
'settings.startPageHint':
'TREK mở thẳng chuyến đi đang diễn ra, nếu không thì chuyến gần nhất sắp tới. Đó cũng là chuyến mà bảng điều khiển làm nổi bật.',
'settings.startTripTab': 'Tab khởi động',
'settings.startTripTabHint':
'Tab mà chuyến đi mở ra. Nếu tab đó thuộc tiện ích đã tắt, chế độ xem kế hoạch sẽ mở thay thế.',
// ── Offline (#1135)
'settings.offline.cache.title': 'Bộ nhớ đệm ngoại tuyến',
+7
View File
@@ -420,6 +420,13 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': '已隱藏',
'settings.general.languageRegion': 'Language & region',
'settings.general.travelMap': 'Travel & map',
'settings.general.startup': '啟動',
'settings.startPage': '啟動頁面',
'settings.startPageDashboard': '儀表板',
'settings.startPageActiveTrip': '進行中的旅行',
'settings.startPageHint': 'TREK 會直接開啟正在進行的旅行,沒有則開啟最近要開始的那次。與儀表板突顯的是同一次旅行。',
'settings.startTripTab': '啟動分頁',
'settings.startTripTabHint': '旅行開啟時所在的分頁。如果該分頁屬於已關閉的附加元件,則改為開啟計劃檢視。',
// ── Offline (#1135)
'settings.offline.cache.title': '離線快取',
+8
View File
@@ -416,6 +416,14 @@ const settings: TranslationStrings = {
'settings.appearance.dashOrder.hidden': '已隐藏',
'settings.general.languageRegion': '语言与地区',
'settings.general.travelMap': '旅行与地图',
'settings.general.startup': '启动',
'settings.startPage': '启动页面',
'settings.startPageDashboard': '仪表盘',
'settings.startPageActiveTrip': '进行中的旅行',
'settings.startPageHint':
'TREK 会直接打开正在进行的旅行,没有则打开最近要开始的那次。与仪表盘突出显示的是同一次旅行。',
'settings.startTripTab': '启动标签页',
'settings.startTripTabHint': '旅行打开时所在的标签页。如果该标签页属于已关闭的插件,则改为打开计划视图。',
// ── Offline (#1135)
'settings.offline.cache.title': '离线缓存',