diff --git a/client/src/components/Admin/DefaultUserSettingsTab.test.tsx b/client/src/components/Admin/DefaultUserSettingsTab.test.tsx index 2ed73a677..95a5e8d3c 100644 --- a/client/src/components/Admin/DefaultUserSettingsTab.test.tsx +++ b/client/src/components/Admin/DefaultUserSettingsTab.test.tsx @@ -1,4 +1,4 @@ -// FE-ADMIN-DUS-001 to FE-ADMIN-DUS-027 +// FE-ADMIN-DUS-001 to FE-ADMIN-DUS-028 import { render, screen, waitFor, within, fireEvent } from '../../../tests/helpers/render'; import userEvent from '@testing-library/user-event'; import { http, HttpResponse } from 'msw'; @@ -453,3 +453,18 @@ describe('DefaultUserSettingsTab', () => { expect(screen.queryByText('Shared CARTO key')).not.toBeInTheDocument(); }); }); + +describe('DefaultUserSettingsTab week start (#2029)', () => { + it('FE-ADMIN-DUS-028: the week-start default saves its own key and can be reset', async () => { + const user = userEvent.setup(); + const { puts } = stubDefaults(); + render(); + await screen.findByText('Default User Settings'); + + await user.click(screen.getByRole('button', { name: 'Sunday' })); + await waitFor(() => expect(resetLink('Week starts on')).toBeInTheDocument()); + await user.click(resetLink('Week starts on')); + + await waitFor(() => expect(puts).toEqual([{ week_start: 'sunday' }, { week_start: null }])); + }); +}); diff --git a/client/src/components/Admin/DefaultUserSettingsTab.tsx b/client/src/components/Admin/DefaultUserSettingsTab.tsx index b789f2d1a..e235ab767 100644 --- a/client/src/components/Admin/DefaultUserSettingsTab.tsx +++ b/client/src/components/Admin/DefaultUserSettingsTab.tsx @@ -7,7 +7,8 @@ import Section from '../Settings/Section' import CustomSelect from '../shared/CustomSelect' import { MapView } from '../Map/MapView' import { SYMBOLS, currenciesWith } from '../Budget/BudgetPanel.constants' -import type { DistanceUnit, Place } from '../../types' +import type { DistanceUnit, Place, WeekStart } from '../../types' +import { weekStartOptions } from '../../utils/calendarWeek' import { normalizeTileUrl, withTileApiKey } from '../../utils/tileUrl' import { MAPBOX_DEFAULT_STYLE, @@ -40,6 +41,7 @@ type Defaults = RoutingDefaults & { distance_unit?: DistanceUnit dark_mode?: string | boolean time_format?: string + week_start?: WeekStart default_currency?: string blur_booking_codes?: boolean map_tile_url?: string @@ -112,7 +114,7 @@ function OptionButton({ } export default function DefaultUserSettingsTab(): React.ReactElement { - const { t } = useTranslation() + const { t, locale } = useTranslation() const toast = useToast() const [defaults, setDefaults] = useState({}) const [loaded, setLoaded] = useState(false) @@ -302,6 +304,15 @@ export default function DefaultUserSettingsTab(): React.ReactElement { ))} + {/* Week start: the first column of every date picker (#2029) */} + {t('settings.weekStart')} }> + {weekStartOptions(locale).map(opt => ( + save({ week_start: opt.value })}> + {opt.label} + + ))} + + {/* Default Currency */}
+ + {/* Week start: the first column of every date picker (#2029) */} +
+ + { + try { await updateSetting('week_start', String(v)) } + catch (e: unknown) { toast.error(e instanceof Error ? e.message : t('common.error')) } + }} + options={weekStartOptions(locale)} + /> +

{t('settings.weekStartHint')}

+
diff --git a/client/src/components/shared/CustomDateTimePicker.test.tsx b/client/src/components/shared/CustomDateTimePicker.test.tsx index 4e152b2bc..7b258a6d5 100644 --- a/client/src/components/shared/CustomDateTimePicker.test.tsx +++ b/client/src/components/shared/CustomDateTimePicker.test.tsx @@ -787,3 +787,35 @@ describe('CustomDateTimePicker branches', () => { expect(onChange).toHaveBeenCalledWith('2026-03-15'); }); }); + +// ─── Week start (#2029) ─────────────────────────────────────────────────────── + +describe('CustomDatePicker week start (#2029)', () => { + const onChange = vi.fn(); + const original = useSettingsStore.getState().settings; + afterEach(() => useSettingsStore.setState({ settings: original })); + + /** The weekday header row and how many blanks precede the 1st, read off the open calendar. */ + async function openMarch2026(weekStart?: 'monday' | 'sunday' | 'saturday') { + useSettingsStore.setState({ settings: { ...original, week_start: weekStart } }); + const user = userEvent.setup(); + render(); + await user.click(screen.getAllByRole('button')[0]); + const day1 = screen.getAllByRole('button').find((b) => b.textContent?.trim() === '1')!; + const grid = day1.parentElement!; + return { header: grid.previousElementSibling!.textContent, blanks: Array.from(grid.children).indexOf(day1) }; + } + + it('FE-COMP-DATEPICKER-033: rows start on Monday when nothing is set', async () => { + // 1 March 2026 is a Sunday: the last column of a Monday-first row. + expect(await openMarch2026(undefined)).toEqual({ header: 'MTWTFSS', blanks: 6 }); + }); + + it('FE-COMP-DATEPICKER-034: rows start on the day the user picked', async () => { + expect(await openMarch2026('sunday')).toEqual({ header: 'SMTWTFS', blanks: 0 }); + }); + + it('FE-COMP-DATEPICKER-035: a Saturday start puts the Sunday 1st in the second column', async () => { + expect(await openMarch2026('saturday')).toEqual({ header: 'SSMTWTF', blanks: 1 }); + }); +}); diff --git a/client/src/components/shared/CustomDateTimePicker.tsx b/client/src/components/shared/CustomDateTimePicker.tsx index 69c09ef07..03997564b 100644 --- a/client/src/components/shared/CustomDateTimePicker.tsx +++ b/client/src/components/shared/CustomDateTimePicker.tsx @@ -4,13 +4,12 @@ import React, { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from '../../i18n'; import { useRemeasureSignal } from '../../hooks/useAnchoredPosition'; +import { useWeekStartDay } from '../../hooks/useWeekStartDay'; +import { leadingBlanks, weekdayLabels } from '../../utils/calendarWeek'; function daysInMonth(year: number, month: number): number { return new Date(year, month + 1, 0).getDate(); } -function getWeekday(year: number, month: number, day: number): number { - return new Date(year, month, day).getDay(); -} const YEAR_PAGE_SIZE = 12; type CalendarView = 'days' | 'months' | 'years'; @@ -41,6 +40,7 @@ export function CustomDatePicker({ max, }: CustomDatePickerProps) { const { locale, t } = useTranslation(); + const weekStart = useWeekStartDay(); const [open, setOpen] = useState(false); const [view, setView] = useState('days'); const [yearPageStart, setYearPageStart] = useState(0); @@ -140,10 +140,8 @@ export function CustomDatePicker({ }; const days = daysInMonth(viewYear, viewMonth); - const startDay = (getWeekday(viewYear, viewMonth, 1) + 6) % 7; - const weekdays = Array.from({ length: 7 }, (_, i) => - new Date(2024, 0, i + 1).toLocaleDateString(locale, { weekday: 'narrow' }) - ); + const startDay = leadingBlanks(viewYear, viewMonth, weekStart); + const weekdays = weekdayLabels(locale, weekStart); const monthNames = Array.from({ length: 12 }, (_, i) => new Date(viewYear, i).toLocaleDateString(locale, { month: 'short' }) diff --git a/client/src/hooks/useWeekStartDay.ts b/client/src/hooks/useWeekStartDay.ts new file mode 100644 index 000000000..546b2d082 --- /dev/null +++ b/client/src/hooks/useWeekStartDay.ts @@ -0,0 +1,7 @@ +import { useSettingsStore } from '../store/settingsStore' +import { weekStartDay } from '../utils/calendarWeek' + +/** The current user's first weekday as a Date#getDay() number (#2029). */ +export function useWeekStartDay(): number { + return weekStartDay(useSettingsStore(s => s.settings.week_start)) +} diff --git a/client/src/mobile/screens/admin/MAdminDefaultUserSettings.tsx b/client/src/mobile/screens/admin/MAdminDefaultUserSettings.tsx index 193865f6b..5ecc71bde 100644 --- a/client/src/mobile/screens/admin/MAdminDefaultUserSettings.tsx +++ b/client/src/mobile/screens/admin/MAdminDefaultUserSettings.tsx @@ -5,7 +5,8 @@ import { useTranslation } from '../../../i18n' import { useToast } from '../../../components/shared/Toast' import { MapView } from '../../../components/Map/MapView' import { SYMBOLS, currenciesWith } from '../../../components/Budget/BudgetPanel.constants' -import { getApiErrorMessage, type DistanceUnit, type Place } from '../../../types' +import { getApiErrorMessage, type DistanceUnit, type Place, type WeekStart } from '../../../types' +import { weekStartOptions } from '../../../utils/calendarWeek' import { normalizeTileUrl, withTileApiKey } from '../../../utils/tileUrl' import { MAPBOX_DEFAULT_STYLE, @@ -43,6 +44,7 @@ type Defaults = RoutingDefaults & { distance_unit?: DistanceUnit dark_mode?: string | boolean time_format?: string + week_start?: WeekStart default_currency?: string blur_booking_codes?: boolean map_tile_url?: string @@ -71,7 +73,7 @@ function styleForProvider(provider: MapProvider, style?: string | null): string // layer (adminApi defaults, per-change auto-save, reset-to-built-in) — only the // presentation is relaid on the admin mobile design system. export default function MAdminDefaultUserSettings(): React.ReactElement { - const { t } = useTranslation() + const { t, locale } = useTranslation() const toast = useToast() const [defaults, setDefaults] = useState({}) const [loaded, setLoaded] = useState(false) @@ -253,6 +255,11 @@ export default function MAdminDefaultUserSettings(): React.ReactElement { save({ time_format: v })} options={timeOptions} /> + {/* Week start (#2029) */} + {t('settings.weekStart')} }> + save({ week_start: v as WeekStart })} options={weekStartOptions(locale)} /> + + {/* Default Currency */} {t('settings.currency')} } diff --git a/client/src/mobile/screens/settings/MSettingsGeneral.tsx b/client/src/mobile/screens/settings/MSettingsGeneral.tsx index 1d4fd9880..f9cf51510 100644 --- a/client/src/mobile/screens/settings/MSettingsGeneral.tsx +++ b/client/src/mobile/screens/settings/MSettingsGeneral.tsx @@ -6,7 +6,9 @@ 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 type { Settings, DistanceUnit, WeekStart } from '../../../types' +import { DEFAULT_WEEK_START } from '@trek/shared' +import { weekStartOptions } from '../../../utils/calendarWeek' import { MSetCard, MSetEyebrow, MSetSelectRow, MSetSegments, MSetRow } from './MSettingsUi' import MToggle from '../../components/MToggle' import MSetPickerSheet from './MSetPickerSheet' @@ -16,7 +18,7 @@ import MSetPickerSheet from './MSetPickerSheet' * cards, wired to the real user preferences (DisplaySettingsTab parity). */ export default function MSettingsGeneral() { - const { t } = useTranslation() + const { t, locale } = useTranslation() const toast = useToast() const { settings, updateSetting } = useSettingsStore() const [currencyOpen, setCurrencyOpen] = useState(false) @@ -143,6 +145,13 @@ export default function MSettingsGeneral() { { value: '12h', label: '12h' }, ]} /> + + {t('settings.weekStart')} + + value={settings.week_start || DEFAULT_WEEK_START} + onChange={(v) => save('week_start', v)} + options={weekStartOptions(locale)} + /> diff --git a/client/src/pages/JourneyDetailPage.test.tsx b/client/src/pages/JourneyDetailPage.test.tsx index 1d2942123..311343dc6 100644 --- a/client/src/pages/JourneyDetailPage.test.tsx +++ b/client/src/pages/JourneyDetailPage.test.tsx @@ -2284,13 +2284,13 @@ describe('JourneyDetailPage', () => { // Calendar dropdown should show weekday headers await waitFor(() => { - expect(screen.getByText('Su')).toBeInTheDocument(); - expect(screen.getByText('Mo')).toBeInTheDocument(); - expect(screen.getByText('Tu')).toBeInTheDocument(); - expect(screen.getByText('We')).toBeInTheDocument(); - expect(screen.getByText('Th')).toBeInTheDocument(); - expect(screen.getByText('Fr')).toBeInTheDocument(); - expect(screen.getByText('Sa')).toBeInTheDocument(); + expect(screen.getByText('Sun')).toBeInTheDocument(); + expect(screen.getByText('Mon')).toBeInTheDocument(); + expect(screen.getByText('Tue')).toBeInTheDocument(); + expect(screen.getByText('Wed')).toBeInTheDocument(); + expect(screen.getByText('Thu')).toBeInTheDocument(); + expect(screen.getByText('Fri')).toBeInTheDocument(); + expect(screen.getByText('Sat')).toBeInTheDocument(); }); }); }); @@ -2309,12 +2309,12 @@ describe('JourneyDetailPage', () => { // The calendar should have the month name and two navigation buttons await waitFor(() => { - expect(screen.getByText('Su')).toBeInTheDocument(); + expect(screen.getByText('Sun')).toBeInTheDocument(); }); // The calendar header has prev/next buttons. They are type="button" within the calendar dropdown. // There should be navigation buttons around the month name - const calendarDropdown = screen.getByText('Su').closest('[class*="rounded-xl"]')!; + const calendarDropdown = screen.getByText('Sun').closest('[class*="rounded-xl"]')!; const navButtons = calendarDropdown.querySelectorAll('button[type="button"]'); // At minimum: 2 nav buttons + day cells expect(navButtons.length).toBeGreaterThanOrEqual(2); @@ -2823,7 +2823,7 @@ describe('JourneyDetailPage', () => { // Wait for calendar to open await waitFor(() => { - expect(screen.getByText('Su')).toBeInTheDocument(); + expect(screen.getByText('Sun')).toBeInTheDocument(); }); // Click day 15 (should be a button in the grid) @@ -2835,7 +2835,7 @@ describe('JourneyDetailPage', () => { // Calendar should close after selection await waitFor(() => { - expect(screen.queryByText('Su')).not.toBeInTheDocument(); + expect(screen.queryByText('Sun')).not.toBeInTheDocument(); }); }); }); @@ -2853,11 +2853,11 @@ describe('JourneyDetailPage', () => { await user.click(dateBtn as HTMLElement); await waitFor(() => { - expect(screen.getByText('Su')).toBeInTheDocument(); + expect(screen.getByText('Sun')).toBeInTheDocument(); }); // Get current month name - const calendarDropdown = screen.getByText('Su').closest('[class*="rounded-xl"]')!; + const calendarDropdown = screen.getByText('Sun').closest('[class*="rounded-xl"]')!; const monthText = calendarDropdown.querySelector('[class*="font-semibold"][class*="text-\\[13px\\]"]'); const currentMonth = monthText?.textContent || ''; diff --git a/client/src/store/settingsStore.ts b/client/src/store/settingsStore.ts index 4df5ea76e..06a2d9c6f 100644 --- a/client/src/store/settingsStore.ts +++ b/client/src/store/settingsStore.ts @@ -1,7 +1,7 @@ import { create } from 'zustand' import { settingsApi } from '../api/client' import type { Settings } from '../types' -import { DEFAULT_APPEARANCE } from '@trek/shared' +import { DEFAULT_APPEARANCE, DEFAULT_WEEK_START } from '@trek/shared' import { getApiErrorMessage } from '../types' import { SUPPORTED_LANGUAGE_CODES } from '../i18n/supportedLanguages' import { normalizeTileUrl, stripTileApiKey } from '../utils/tileUrl' @@ -84,6 +84,7 @@ export const DEFAULT_SETTINGS: Settings = { temperature_unit: 'celsius', distance_unit: 'metric', time_format: '24h', + week_start: DEFAULT_WEEK_START, show_place_description: false, optimize_from_accommodation: true, map_provider: 'leaflet', diff --git a/client/src/types.ts b/client/src/types.ts index efbec7712..0e0407470 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -29,6 +29,7 @@ import type { Tag, Category, AppearanceConfig, + WeekStart, } from '@trek/shared' export type { @@ -53,6 +54,7 @@ export type { Tag, Category, AppearanceConfig, + WeekStart, } export interface User { @@ -128,6 +130,8 @@ export interface Settings { temperature_unit: string distance_unit?: DistanceUnit time_format: string + /** First column of every date picker (#2029); missing means Monday. */ + week_start?: WeekStart show_place_description: boolean blur_booking_codes?: boolean map_booking_labels?: boolean diff --git a/client/src/utils/calendarWeek.test.ts b/client/src/utils/calendarWeek.test.ts new file mode 100644 index 000000000..cb2b9c95e --- /dev/null +++ b/client/src/utils/calendarWeek.test.ts @@ -0,0 +1,47 @@ +// FE-UTIL-CALWEEK-001 to FE-UTIL-CALWEEK-005 +import { describe, it, expect } from 'vitest' +import { leadingBlanks, weekdayLabels, weekStartDay, weekStartOptions } from './calendarWeek' + +describe('calendarWeek (#2029)', () => { + it('FE-UTIL-CALWEEK-001: maps the setting to getDay() and falls back to Monday', () => { + expect(weekStartDay('monday')).toBe(1) + expect(weekStartDay('sunday')).toBe(0) + expect(weekStartDay('saturday')).toBe(6) + // Missing, unknown and the Vacay-style number all read as Monday, what every picker showed before. + expect(weekStartDay(undefined)).toBe(1) + expect(weekStartDay('friday')).toBe(1) + expect(weekStartDay(0)).toBe(1) + }) + + it('FE-UTIL-CALWEEK-002: counts the blanks before the 1st for each first weekday', () => { + // 1 March 2026 is a Sunday. + expect(leadingBlanks(2026, 2, 1)).toBe(6) + expect(leadingBlanks(2026, 2, 0)).toBe(0) + expect(leadingBlanks(2026, 2, 6)).toBe(1) + // 1 January 2024 is a Monday. + expect(leadingBlanks(2024, 0, 1)).toBe(0) + expect(leadingBlanks(2024, 0, 0)).toBe(1) + expect(leadingBlanks(2024, 0, 6)).toBe(2) + }) + + it('FE-UTIL-CALWEEK-003: rotates the header row to the first weekday', () => { + expect(weekdayLabels('en-US', 1, 'short')).toEqual(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']) + expect(weekdayLabels('en-US', 0, 'short')).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']) + expect(weekdayLabels('en-US', 6, 'short')).toEqual(['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri']) + expect(weekdayLabels('en-US', 0).join('')).toBe('SMTWTFS') + }) + + it('FE-UTIL-CALWEEK-004: speaks the app locale, not the browser one', () => { + expect(weekdayLabels('de-DE', 1, 'short')[0]).toBe('Mo') + }) + + it('FE-UTIL-CALWEEK-005: labels the choices with capitalised day names in the app language', () => { + expect(weekStartOptions('en-US')).toEqual([ + { value: 'monday', label: 'Monday' }, + { value: 'sunday', label: 'Sunday' }, + { value: 'saturday', label: 'Saturday' }, + ]) + // French writes weekday names lower-case; standing alone on a button they start upper-case. + expect(weekStartOptions('fr-FR').map(o => o.label)).toEqual(['Lundi', 'Dimanche', 'Samedi']) + }) +}) diff --git a/client/src/utils/calendarWeek.ts b/client/src/utils/calendarWeek.ts new file mode 100644 index 000000000..81af40e0a --- /dev/null +++ b/client/src/utils/calendarWeek.ts @@ -0,0 +1,42 @@ +import { DEFAULT_WEEK_START, WEEK_START_DAY, WEEK_START_VALUES, type WeekStart } from '@trek/shared' + +/** + * The calendar-grid half of the week_start setting (#2029): the one place a + * date picker asks which weekday opens a row, how many blanks go before the + * 1st, and what the header row says. Both pickers (CustomDatePicker and the + * journey DatePicker) read it, so they cannot drift apart again. + */ + +/** Date#getDay() of the first weekday; a missing or unknown value is Monday, what every picker did before the setting. */ +export function weekStartDay(value: unknown): number { + const known = (WEEK_START_VALUES as readonly unknown[]).includes(value) + return WEEK_START_DAY[known ? value as WeekStart : DEFAULT_WEEK_START] +} + +/** Blank cells before the 1st of the month when rows begin on `weekStart`. */ +export function leadingBlanks(year: number, month: number, weekStart: number): number { + return (new Date(year, month, 1).getDay() - weekStart + 7) % 7 +} + +// 7 January 2024 is a Sunday, so the 7th plus a getDay() number is that weekday. +function sampleDay(day: number): Date { + return new Date(2024, 0, 7 + day) +} + +/** The header row of a month grid, starting on `weekStart`, in the app's locale. */ +export function weekdayLabels(locale: string, weekStart: number, weekday: 'narrow' | 'short' = 'narrow'): string[] { + return Array.from({ length: 7 }, (_, i) => sampleDay((weekStart + i) % 7).toLocaleDateString(locale, { weekday })) +} + +/** + * The choices for the setting, labelled with the day's own name in the app's + * language, so no locale file has to spell out seven weekdays. Capitalised + * because several languages write weekday names lower-case and these stand + * alone on a button. + */ +export function weekStartOptions(locale: string): { value: WeekStart; label: string }[] { + return WEEK_START_VALUES.map(value => { + const name = sampleDay(WEEK_START_DAY[value]).toLocaleDateString(locale, { weekday: 'long' }) + return { value, label: name.charAt(0).toLocaleUpperCase(locale) + name.slice(1) } + }) +} diff --git a/client/tests/unit/mobile/admin/MAdminDefaultUserSettings.test.tsx b/client/tests/unit/mobile/admin/MAdminDefaultUserSettings.test.tsx index 773fd7fb4..eb3fd7c4e 100644 --- a/client/tests/unit/mobile/admin/MAdminDefaultUserSettings.test.tsx +++ b/client/tests/unit/mobile/admin/MAdminDefaultUserSettings.test.tsx @@ -1,4 +1,4 @@ -// FE-MOB-MDUS-001 to FE-MOB-MDUS-027 +// FE-MOB-MDUS-001 to FE-MOB-MDUS-028 import { describe, it, expect, beforeEach, vi } from 'vitest'; import { render, screen, waitFor, within, fireEvent } from '../../../helpers/render'; import userEvent from '@testing-library/user-event'; @@ -452,3 +452,16 @@ describe('MAdminDefaultUserSettings', () => { expect(screen.queryByText('Shared Mapbox token')).not.toBeInTheDocument(); }); }); + +describe('MAdminDefaultUserSettings week start (#2029)', () => { + it('FE-MOB-MDUS-028: the week-start segment saves its own key', async () => { + const user = userEvent.setup(); + const { puts } = stubDefaults(); + render(); + await screen.findByText('Default User Settings'); + + await user.click(screen.getByRole('tab', { name: 'Saturday' })); + await waitFor(() => expect(screen.getByRole('tab', { name: 'Saturday' })).toHaveAttribute('aria-selected', 'true')); + expect(puts).toEqual([{ week_start: 'saturday' }]); + }); +}); diff --git a/client/tests/unit/mobile/settings/MSettingsGeneral.test.tsx b/client/tests/unit/mobile/settings/MSettingsGeneral.test.tsx index e7aa9421d..b1ae3c5af 100644 --- a/client/tests/unit/mobile/settings/MSettingsGeneral.test.tsx +++ b/client/tests/unit/mobile/settings/MSettingsGeneral.test.tsx @@ -218,3 +218,16 @@ describe('MSettingsGeneral', () => { expect(updateSetting).toHaveBeenCalledWith('map_always_show_routes', false); }); }); + +describe('MSettingsGeneral week start (#2029)', () => { + it('FE-MOB-SET-017: the week-start segments show Monday when unset and save the day tapped', async () => { + const user = userEvent.setup(); + const updateSetting = vi.fn().mockResolvedValue(undefined); + seedStore(useSettingsStore, { settings: buildSettings({ language: 'en', week_start: undefined }), updateSetting }); + render(); + + expect(screen.getByRole('button', { name: 'Monday' })).toHaveAttribute('aria-pressed', 'true'); + await user.click(screen.getByRole('button', { name: 'Saturday' })); + expect(updateSetting).toHaveBeenCalledWith('week_start', 'saturday'); + }); +}); diff --git a/server/src/nest/common/managed.ts b/server/src/nest/common/managed.ts index 813ecfe08..536e84aa5 100644 --- a/server/src/nest/common/managed.ts +++ b/server/src/nest/common/managed.ts @@ -153,6 +153,7 @@ export const MANAGED_CUSTOMER_KEYS = [ 'require_mfa', 'temperature_unit', 'time_format', + 'week_start', ] as const; const LOCKED = new Set(MANAGED_LOCKED_SETTING_KEYS); diff --git a/server/src/nest/settings/settings.mcp.ts b/server/src/nest/settings/settings.mcp.ts index fd3aa1656..902f95756 100644 --- a/server/src/nest/settings/settings.mcp.ts +++ b/server/src/nest/settings/settings.mcp.ts @@ -4,7 +4,7 @@ import { demoDenied, errorResult, ok, } from '../../nest-mcp'; import { z } from 'zod'; -import { MASKED_SETTING_VALUE, SUPPORTED_LANGUAGE_CODES, settingsBulkRequestSchema } from '@trek/shared'; +import { MASKED_SETTING_VALUE, SUPPORTED_LANGUAGE_CODES, settingsBulkRequestSchema, weekStartSchema } from '@trek/shared'; import { AuthService } from '../auth/auth.service'; import { SettingsService } from './settings.service'; @@ -47,6 +47,7 @@ const DISPLAY_PREFERENCES = { temperature_unit: z.enum(['celsius', 'fahrenheit']), distance_unit: z.enum(['metric', 'imperial']), time_format: z.enum(['12h', '24h']), + week_start: weekStartSchema, // Booleans are the pre-'auto' form and still sit in older rows, so they stay // writable: this is exactly the VALID_VALUES.dark_mode set the admin-defaults // path accepts, and refusing them here would make a value TREK itself wrote @@ -112,7 +113,7 @@ export class SettingsMcp { @Tool({ name: 'get_display_settings', - description: `Read the current user's display preferences: ${KEY_LIST}. Call this before rendering a temperature, a distance, a time of day or an amount, so the answer matches what the person sees inside TREK instead of being guessed, and call it before update_display_settings whenever the request is relative ("switch me back", "use the other unit"). Only keys that are actually set are returned; TREK's own fallbacks for the rest are celsius, metric, 24h, language en, start_page dashboard, start_trip_tab plan, and no personal default currency, which means amounts fall back to the currency of the trip they belong to. Stored credentials (map tokens, LLM API keys, webhook URLs, SMTP) are deliberately not part of this surface and never appear in the result.`, + description: `Read the current user's display preferences: ${KEY_LIST}. Call this before rendering a temperature, a distance, a time of day or an amount, so the answer matches what the person sees inside TREK instead of being guessed, and call it before update_display_settings whenever the request is relative ("switch me back", "use the other unit"). Only keys that are actually set are returned; TREK's own fallbacks for the rest are celsius, metric, 24h, week_start monday, language en, start_page dashboard, start_trip_tab plan, and no personal default currency, which means amounts fall back to the currency of the trip they belong to. Stored credentials (map tokens, LLM API keys, webhook URLs, SMTP) are deliberately not part of this surface and never appear in the result.`, inputSchema: {}, annotations: TOOL_ANNOTATIONS_READONLY, access: { group: 'settings', mode: 'read' }, @@ -123,7 +124,7 @@ export class SettingsMcp { @Tool({ name: 'update_display_settings', - description: `Change one or more of the current user's display preferences. Pass a settings object holding only the keys to change; anything left out keeps its current value. Writable keys: ${KEY_LIST}. start_page is dashboard or active_trip, start_trip_tab is one of plan, transports, buchungen, listen, finanzplan, dateien, collab (the ids are the planner's internal German ones) or plugin: for a plugin tab, default_currency is a three-letter ISO code or "" to fall back to each trip's own currency, dark_mode is light, dark or auto. Every other key is refused, including API keys, map tokens, LLM endpoint settings and SMTP: those belong to the account owner or to whoever operates the instance and are set in TREK itself, not here. Prefer get_display_settings when you only need to read a value.`, + description: `Change one or more of the current user's display preferences. Pass a settings object holding only the keys to change; anything left out keeps its current value. Writable keys: ${KEY_LIST}. start_page is dashboard or active_trip, start_trip_tab is one of plan, transports, buchungen, listen, finanzplan, dateien, collab (the ids are the planner's internal German ones) or plugin: for a plugin tab, default_currency is a three-letter ISO code or "" to fall back to each trip's own currency, dark_mode is light, dark or auto, week_start is monday, sunday or saturday and sets the first column of every date picker in TREK. Every other key is refused, including API keys, map tokens, LLM endpoint settings and SMTP: those belong to the account owner or to whoever operates the instance and are set in TREK itself, not here. Prefer get_display_settings when you only need to read a value.`, inputSchema: { settings: settingsBulkRequestSchema.shape.settings .describe(`Object of preference key to new value, e.g. {"temperature_unit": "fahrenheit", "distance_unit": "imperial"}. At least one key, and every key must be one of: ${KEY_LIST}.`), diff --git a/server/src/nest/settings/settings.service.ts b/server/src/nest/settings/settings.service.ts index 46df58797..07c852c20 100644 --- a/server/src/nest/settings/settings.service.ts +++ b/server/src/nest/settings/settings.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { DatabaseService } from '../database/database.service'; import { decrypt_api_key, maybe_encrypt_api_key } from '../common/crypto/apiKeyCrypto'; -import { MASKED_SETTING_VALUE, normalizeAppearance } from '@trek/shared'; +import { MASKED_SETTING_VALUE, WEEK_START_VALUES, normalizeAppearance } from '@trek/shared'; import { readEnv } from '../../app-config'; /** @@ -25,6 +25,8 @@ export const DEFAULTABLE_USER_SETTING_KEYS = [ 'distance_unit', 'dark_mode', 'time_format', + // First day of the week in every date picker (#2029). + 'week_start', // Instance-wide default currency for Costs (new users inherit it until they // pick their own). Free-form ISO code, validated on the client. 'default_currency', @@ -83,6 +85,7 @@ const VALID_VALUES: Partial> = { temperature_unit: ['fahrenheit', 'celsius'], distance_unit: ['metric', 'imperial'], time_format: ['12h', '24h'], + week_start: [...WEEK_START_VALUES], dark_mode: [true, false, 'light', 'dark', 'auto'], map_provider: ['leaflet', 'mapbox-gl', 'maplibre-gl'], llm_provider: ['local', 'openai', 'anthropic'], diff --git a/server/tests/e2e/settings.e2e.test.ts b/server/tests/e2e/settings.e2e.test.ts index 866b4a8d5..88d21aafb 100644 --- a/server/tests/e2e/settings.e2e.test.ts +++ b/server/tests/e2e/settings.e2e.test.ts @@ -232,4 +232,22 @@ describe('Settings e2e (real auth guard + temp SQLite)', () => { .toEqual({ value: 'openai' }); }); }); + + describe('week_start (#2029)', () => { + it('an admin default reaches a user who never picked a first weekday', async () => { + const put = await request(server).put('/api/admin/default-user-settings').set('Cookie', sessionCookie(2)) + .send({ week_start: 'sunday' }); + expect(put.status).toBe(200); + const res = await request(server).get('/api/settings').set('Cookie', sessionCookie(1)); + expect(res.status).toBe(200); + expect(res.body.settings.week_start).toBe('sunday'); + }); + + it('PUT /api/admin/default-user-settings 400 for a weekday the pickers do not offer', async () => { + const res = await request(server).put('/api/admin/default-user-settings').set('Cookie', sessionCookie(2)) + .send({ week_start: 'friday' }); + expect(res.status).toBe(400); + expect(db.prepare("SELECT value FROM app_settings WHERE key = 'default_user_setting_week_start'").get()).toBeUndefined(); + }); + }); }); diff --git a/server/tests/unit/mcp/tools-settings.test.ts b/server/tests/unit/mcp/tools-settings.test.ts index 850a844d6..fecb115d4 100644 --- a/server/tests/unit/mcp/tools-settings.test.ts +++ b/server/tests/unit/mcp/tools-settings.test.ts @@ -259,6 +259,17 @@ describe('Tool: update_display_settings', () => { }); }); + it('writes week_start and refuses a day outside the three the app offers (#2029)', async () => { + const { user } = createUser(testDb); + await withHarness(user.id, async (h) => { + const ok = parseToolResult(await update(h, { week_start: 'sunday' })) as any; + expect(ok.settings.week_start).toBe('sunday'); + const refused = await update(h, { week_start: 'friday' }); + expect(refused.isError).toBe(true); + expect(readSetting(user.id, 'week_start')).toBe('sunday'); + }); + }); + it('accepts every boolean display preference', async () => { const { user } = createUser(testDb); await withHarness(user.id, async (h) => { diff --git a/server/tests/unit/nest/settings.service.test.ts b/server/tests/unit/nest/settings.service.test.ts index 8df6e68ed..c85378c3d 100644 --- a/server/tests/unit/nest/settings.service.test.ts +++ b/server/tests/unit/nest/settings.service.test.ts @@ -353,6 +353,22 @@ describe('legacy quirk fixes', () => { expect(svc.getDecryptedUserSetting(user.id, 'llm_api_key')).toBeNull(); }); + it('SET-SVC-035 — a week_start default reaches users without their own, and theirs wins (#2029)', () => { + const { user: plain } = createUser(testDb); + const { user: own } = createUser(testDb); + svc.setAdminUserDefaults({ week_start: 'sunday' }); + svc.upsertSetting(own.id, 'week_start', 'saturday'); + expect(svc.getUserSettings(plain.id).week_start).toBe('sunday'); + expect(svc.getUserSettings(own.id).week_start).toBe('saturday'); + }); + + it('SET-SVC-036 — a week_start default outside monday/sunday/saturday is refused and not stored', () => { + expect(() => svc.setAdminUserDefaults({ week_start: 'friday' })).toThrow(/Invalid value for week_start/); + // Vacay's 0/1 numbers are not this setting's values either. + expect(() => svc.setAdminUserDefaults({ week_start: 0 })).toThrow(/Invalid value for week_start/); + expect(svc.getAdminUserDefaults().week_start).toBeUndefined(); + }); + it('SET-SVC-028 — a nulled defaultable key falls through to the admin default', () => { const { user } = createUser(testDb); svc.setAdminUserDefaults({ mapbox_style: 'admin-style' }); diff --git a/shared/src/i18n/ar/help.ts b/shared/src/i18n/ar/help.ts index ff4150fd4..ea780917e 100644 --- a/shared/src/i18n/ar/help.ts +++ b/shared/src/i18n/ar/help.ts @@ -936,7 +936,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'اللغة والوحدات والعملة، وكيف تتصرف الخريطة والحجوزات، وما يفتح به TREK. كل تغيير هنا يسري فورًا.', 'help.ctx.settings-display.bullet.1': - '«Language & region»: لغة الواجهة وتنسيق الوقت وعملة العرض ووحدتا المسافة والحرارة.', + '«Language & region»: لغة الواجهة وتنسيق الوقت وأول أيام الأسبوع وعملة العرض ووحدتا المسافة والحرارة.', 'help.ctx.settings-display.bullet.2': '«Travel & map»: مسارات الحجوزات دائمًا على الخريطة، وزر استكشاف الأماكن، وتحسين المسار انطلاقًا من مكان إقامتك، وإخفاء رموز الحجز، ومسارات الحجوزات المسمّاة.', 'help.ctx.settings-display.bullet.3': @@ -1001,7 +1001,8 @@ const help: TranslationStrings = { 'help.guide.language-region.goal': 'اجعل TREK يتحدث لغتك ويحسب كما تحسب.', 'help.guide.language-region.step.1': 'اختر لغة الواجهة في «Language & region». يتبدّل TREK فورًا، على كل جهاز تسجّل الدخول منه.', - 'help.guide.language-region.step.2': 'تحته، اختر تنسيق الوقت وعملة العرض ووحدتي المسافة والحرارة.', + 'help.guide.language-region.step.2': + 'تحته، اختر تنسيق الوقت واليوم الذي يبدأ به الأسبوع في جميع منتقيات التاريخ وعملة العرض ووحدتي المسافة والحرارة.', 'help.guide.language-region.result': 'تُقرأ التواريخ والمسافات والمبالغ كما تتوقع؛ وتبقى عملة الرحلة نفسها ظاهرة بجانب المبالغ المحوّلة.', 'help.guide.language-region.tip.1': 'عملة العرض للمجاميع عبر الرحلات؛ وتحتفظ كل رحلة بالعملة التي أعطيتها إياها.', diff --git a/shared/src/i18n/ar/settings.ts b/shared/src/i18n/ar/settings.ts index 9c011e01e..7aef2103c 100644 --- a/shared/src/i18n/ar/settings.ts +++ b/shared/src/i18n/ar/settings.ts @@ -74,6 +74,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'وحدة الحرارة', 'settings.distance': 'وحدة المسافة', 'settings.timeFormat': 'تنسيق الوقت', + 'settings.weekStart': 'يبدأ الأسبوع في', + 'settings.weekStartHint': 'أول أيام الأسبوع في جميع منتقيات التاريخ. لدى Vacay إعداد خاص به.', 'settings.bookingLabels': 'تسميات مسارات الحجوزات', 'settings.bookingLabelsHint': 'عرض أسماء المحطات/المطارات على الخريطة. عند الإيقاف، يتم عرض الرمز فقط.', 'settings.blurBookingCodes': 'إخفاء رموز الحجز', diff --git a/shared/src/i18n/az/help.ts b/shared/src/i18n/az/help.ts index c8ccd0c96..be26a48e8 100644 --- a/shared/src/i18n/az/help.ts +++ b/shared/src/i18n/az/help.ts @@ -1059,7 +1059,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Dil, vahidlər və valyuta, xəritə və rezervasiyaların davranışı və TREK-in nə ilə açılması. Buradakı hər dəyişiklik dərhal tətbiq olunur.', 'help.ctx.settings-display.bullet.1': - 'Dil və region: interfeys dili, vaxt formatı, göstərilən valyuta, məsafə və temperatur vahidləri.', + 'Dil və region: interfeys dili, vaxt formatı, həftənin ilk günü, göstərilən valyuta, məsafə və temperatur vahidləri.', 'help.ctx.settings-display.bullet.2': 'Səyahət və xəritə: xəritədə həmişə görünən rezervasiya marşrutları, məkanları kəşf etmə düyməsi, yaşayış yerindən marşrut optimallaşdırması, bulanıqlaşdırılmış rezervasiya kodları və etiketli rezervasiya marşrutları.', 'help.ctx.settings-display.bullet.3': @@ -1128,7 +1128,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Dil və region bölməsində interfeys dilini seçin. TREK daxil olduğunuz bütün cihazlarda dərhal dəyişir.', 'help.guide.language-region.step.2': - 'Onun altında vaxt formatını, göstərilən valyutanı, məsafə və temperatur vahidlərini seçin.', + 'Onun altında vaxt formatını, bütün tarix seçicilərində həftənin hansı gündən başladığını, göstərilən valyutanı, məsafə və temperatur vahidlərini seçin.', 'help.guide.language-region.result': 'Tarixlər, məsafələr və pul gözlədiyiniz kimi göstərilir; səyahətin öz valyutası çevrilmiş məbləğlərin yanında yenə də görünür.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/az/settings.ts b/shared/src/i18n/az/settings.ts index 64db7bda0..2abb32d60 100644 --- a/shared/src/i18n/az/settings.ts +++ b/shared/src/i18n/az/settings.ts @@ -111,6 +111,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperatur vahidi', 'settings.distance': 'Məsafə vahidi', 'settings.timeFormat': 'Vaxt formatı', + 'settings.weekStart': 'Həftənin başlanğıcı', + 'settings.weekStartHint': 'Bütün tarix seçicilərində həftənin ilk günü. Vacay-ın öz ayarı var.', 'settings.bookingLabels': 'Rezervasiya marşrutu etiketləri', 'settings.bookingLabelsHint': diff --git a/shared/src/i18n/br/help.ts b/shared/src/i18n/br/help.ts index d8bc89ac3..3a4cb6e2d 100644 --- a/shared/src/i18n/br/help.ts +++ b/shared/src/i18n/br/help.ts @@ -1025,7 +1025,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Idioma, unidades e moeda, como o mapa e as reservas se comportam, e com o que o TREK abre. Cada mudança aqui vale na hora.', 'help.ctx.settings-display.bullet.1': - 'Language & region: o idioma da interface, o formato de hora, a moeda de exibição, e as unidades de distância e temperatura.', + 'Language & region: o idioma da interface, o formato de hora, o primeiro dia da semana, a moeda de exibição, e as unidades de distância e temperatura.', 'help.ctx.settings-display.bullet.2': 'Travel & map: rotas de reserva sempre no mapa, a pílula Explorar lugares, otimização de rota a partir da sua hospedagem, códigos de reserva ocultos e rotas de reserva com rótulo.', 'help.ctx.settings-display.bullet.3': @@ -1094,7 +1094,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Escolha o idioma da interface em Language & region. O TREK muda na hora, em cada dispositivo em que você entra.', 'help.guide.language-region.step.2': - 'Abaixo, escolha o formato de hora, a moeda de exibição, e as unidades de distância e temperatura.', + 'Abaixo, escolha o formato de hora, o dia em que a semana começa em todos os seletores de data, a moeda de exibição, e as unidades de distância e temperatura.', 'help.guide.language-region.result': 'Datas, distâncias e dinheiro aparecem do jeito que você espera; a moeda própria de uma viagem continua ao lado dos valores convertidos.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/br/settings.ts b/shared/src/i18n/br/settings.ts index e0fc726d0..fca026fa9 100644 --- a/shared/src/i18n/br/settings.ts +++ b/shared/src/i18n/br/settings.ts @@ -78,6 +78,9 @@ const settings: TranslationStrings = { 'settings.temperature': 'Unidade de temperatura', 'settings.distance': 'Unidade de distância', 'settings.timeFormat': 'Formato de hora', + 'settings.weekStart': 'Semana começa em', + 'settings.weekStartHint': + 'Primeiro dia da semana em todos os seletores de data. O Vacay tem sua própria configuração.', 'settings.blurBookingCodes': 'Ocultar códigos de reserva', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/ca/help.ts b/shared/src/i18n/ca/help.ts index dec7eec46..8c3a571d3 100644 --- a/shared/src/i18n/ca/help.ts +++ b/shared/src/i18n/ca/help.ts @@ -1042,7 +1042,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Idioma, unitats i divisa, com es comporten el mapa i les reserves, i amb què s’obre TREK. Cada canvi aquí s’aplica a l’instant.', 'help.ctx.settings-display.bullet.1': - 'Idioma i regió: l’idioma de la interfície, el format d’hora, la divisa de visualització, i les unitats de distància i temperatura.', + 'Idioma i regió: l’idioma de la interfície, el format d’hora, el primer dia de la setmana, la divisa de visualització, i les unitats de distància i temperatura.', 'help.ctx.settings-display.bullet.2': 'Viatge i mapa: rutes de reserva sempre al mapa, la píndola Explora llocs, optimització de la ruta des del teu allotjament, codis de reserva difuminats i rutes de reserva etiquetades.', 'help.ctx.settings-display.bullet.3': @@ -1112,7 +1112,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Tria l’idioma de la interfície a Idioma i regió. TREK canvia a l’instant, a cada dispositiu on inicies sessió.', 'help.guide.language-region.step.2': - 'A sota, tria el format d’hora, la divisa de visualització, i les unitats de distància i temperatura.', + 'A sota, tria el format d’hora, el dia en què comença la setmana a tots els selectors de data, la divisa de visualització, i les unitats de distància i temperatura.', 'help.guide.language-region.result': 'Dates, distàncies i diners es llegeixen com esperes; la divisa pròpia d’un viatge continua apareixent al costat dels imports convertits.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/ca/settings.ts b/shared/src/i18n/ca/settings.ts index 54fe6dc0b..6d5d3be5f 100644 --- a/shared/src/i18n/ca/settings.ts +++ b/shared/src/i18n/ca/settings.ts @@ -63,6 +63,8 @@ const settings: TranslationStrings = { 'settings.language': 'Idioma', 'settings.temperature': 'Unitat de temperatura', 'settings.timeFormat': "Format d'hora", + 'settings.weekStart': 'La setmana comença el', + 'settings.weekStartHint': 'Primer dia de la setmana a tots els selectors de data. Vacay té la seva pròpia opció.', 'settings.blurBookingCodes': 'Difumina els codis de reserva', 'settings.optimizeFromAccommodation': "Optimitza la ruta des de l'allotjament", 'settings.optimizeFromAccommodationHint': diff --git a/shared/src/i18n/cs/help.ts b/shared/src/i18n/cs/help.ts index 79fecb3ec..31882ad60 100644 --- a/shared/src/i18n/cs/help.ts +++ b/shared/src/i18n/cs/help.ts @@ -996,7 +996,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Jazyk, jednotky a měna, jak se chová mapa a rezervace a s čím se TREK otevře. Každá změna tady se projeví hned.', 'help.ctx.settings-display.bullet.1': - 'Language & region: jazyk rozhraní, formát času, zobrazovaná měna a jednotky vzdálenosti a teploty.', + 'Language & region: jazyk rozhraní, formát času, první den týdne, zobrazovaná měna a jednotky vzdálenosti a teploty.', 'help.ctx.settings-display.bullet.2': 'Travel & map: trasy rezervací vždy na mapě, pilulka Objevovat místa, optimalizace trasy od ubytování, skryté rezervační kódy a popisky tras rezervací.', 'help.ctx.settings-display.bullet.3': @@ -1064,7 +1064,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Vyberte jazyk rozhraní v Language & region. TREK se přepne hned, na každém zařízení, kde se přihlásíte.', 'help.guide.language-region.step.2': - 'Pod ním zvolte formát času, zobrazovanou měnu a jednotky vzdálenosti a teploty.', + 'Pod ním zvolte formát času, den, kterým začíná týden ve všech výběrech data, zobrazovanou měnu a jednotky vzdálenosti a teploty.', 'help.guide.language-region.result': 'Data, vzdálenosti a peníze se čtou tak, jak čekáte; vlastní měna cesty se dál ukazuje vedle přepočtených částek.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/cs/settings.ts b/shared/src/i18n/cs/settings.ts index 1f415a8b3..12f40ad54 100644 --- a/shared/src/i18n/cs/settings.ts +++ b/shared/src/i18n/cs/settings.ts @@ -75,6 +75,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Jednotky teploty', 'settings.distance': 'Jednotky vzdálenosti', 'settings.timeFormat': 'Formát času', + 'settings.weekStart': 'Týden začíná', + 'settings.weekStartHint': 'První den týdne ve všech výběrech data. Vacay má vlastní nastavení.', 'settings.blurBookingCodes': 'Skrýt rezervační kódy', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/de/help.ts b/shared/src/i18n/de/help.ts index 6fe1ef48a..de639e8d6 100644 --- a/shared/src/i18n/de/help.ts +++ b/shared/src/i18n/de/help.ts @@ -1049,7 +1049,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Sprache, Einheiten und Währung, wie sich Karte und Buchungen verhalten, und womit TREK öffnet. Jede Änderung hier greift sofort.', 'help.ctx.settings-display.bullet.1': - 'Sprache & Region: die Sprache der Oberfläche, das Zeitformat, die Anzeigewährung sowie Entfernungs- und Temperatureinheit.', + 'Sprache & Region: die Sprache der Oberfläche, das Zeitformat, der erste Tag der Woche, die Anzeigewährung sowie Entfernungs- und Temperatureinheit.', 'help.ctx.settings-display.bullet.2': 'Reise & Karte: Buchungsrouten immer auf der Karte, die Pille zum Entdecken von Orten, Routenoptimierung ab deiner Unterkunft, verborgene Buchungscodes und beschriftete Buchungsrouten.', 'help.ctx.settings-display.bullet.3': @@ -1119,7 +1119,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Wähl die Sprache der Oberfläche unter Sprache & Region. TREK wechselt sofort, auf jedem Gerät, auf dem du dich anmeldest.', 'help.guide.language-region.step.2': - 'Darunter wählst du das Zeitformat, die Anzeigewährung sowie Entfernungs- und Temperatureinheit.', + 'Darunter wählst du das Zeitformat, den Tag, mit dem jeder Datumswähler die Woche beginnt, die Anzeigewährung sowie Entfernungs- und Temperatureinheit.', 'help.guide.language-region.result': 'Daten, Entfernungen und Geld lesen sich so, wie du es erwartest; die eigene Währung einer Reise steht weiterhin neben umgerechneten Beträgen.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/de/settings.ts b/shared/src/i18n/de/settings.ts index d56ca1829..446da5f05 100644 --- a/shared/src/i18n/de/settings.ts +++ b/shared/src/i18n/de/settings.ts @@ -77,6 +77,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperatureinheit', 'settings.distance': 'Entfernungseinheit', 'settings.timeFormat': 'Zeitformat', + 'settings.weekStart': 'Woche beginnt am', + 'settings.weekStartHint': 'Erster Tag der Woche in jedem Datumswähler. Vacay hat eine eigene Einstellung.', 'settings.bookingLabels': 'Orts-Labels auf Buchungsrouten', 'settings.bookingLabelsHint': 'Zeigt Bahnhofs-/Flughafennamen auf der Karte. Wenn aus, wird nur das Icon angezeigt.', 'settings.blurBookingCodes': 'Buchungscodes verbergen', diff --git a/shared/src/i18n/en/help.ts b/shared/src/i18n/en/help.ts index 4224bda4d..aff8a5c54 100644 --- a/shared/src/i18n/en/help.ts +++ b/shared/src/i18n/en/help.ts @@ -1009,7 +1009,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Language, units and currency, how the map and bookings behave, and what TREK opens with. Every change here applies at once.', 'help.ctx.settings-display.bullet.1': - 'Language & region: the interface language, the time format, the display currency, and distance and temperature units.', + 'Language & region: the interface language, the time format, the first day of the week, the display currency, and distance and temperature units.', 'help.ctx.settings-display.bullet.2': 'Travel & map: booking routes always on the map, the Explore places pill, route optimisation from your accommodation, blurred booking codes and labelled booking routes.', 'help.ctx.settings-display.bullet.3': @@ -1076,7 +1076,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Pick the interface language in Language & region. TREK switches at once, on every device you sign in on.', 'help.guide.language-region.step.2': - 'Below it, choose the time format, the display currency, and the distance and temperature units.', + 'Below it, choose the time format, the day every date picker starts its week on, the display currency, and the distance and temperature units.', 'help.guide.language-region.result': "Dates, distances and money read the way you expect; a trip's own currency still shows next to converted amounts.", 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/en/settings.ts b/shared/src/i18n/en/settings.ts index 27427f816..533e912d6 100644 --- a/shared/src/i18n/en/settings.ts +++ b/shared/src/i18n/en/settings.ts @@ -84,6 +84,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperature Unit', 'settings.distance': 'Distance Unit', 'settings.timeFormat': 'Time Format', + 'settings.weekStart': 'Week starts on', + 'settings.weekStartHint': 'First day of the week in every date picker. Vacay has its own setting.', 'settings.bookingLabels': 'Booking route labels', 'settings.bookingLabelsHint': 'Show station / airport names on the map. When off, only the icon is shown.', 'settings.mapPoiPill': 'Explore places on the map', diff --git a/shared/src/i18n/es/help.ts b/shared/src/i18n/es/help.ts index e404cc623..7352b9b9c 100644 --- a/shared/src/i18n/es/help.ts +++ b/shared/src/i18n/es/help.ts @@ -1044,7 +1044,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Idioma, unidades y moneda, cómo se comportan el mapa y las reservas, y con qué se abre TREK. Cada cambio aquí se aplica al momento.', 'help.ctx.settings-display.bullet.1': - 'Language & region: el idioma de la interfaz, el formato de hora, la moneda de visualización, y las unidades de distancia y temperatura.', + 'Language & region: el idioma de la interfaz, el formato de hora, el primer día de la semana, la moneda de visualización, y las unidades de distancia y temperatura.', 'help.ctx.settings-display.bullet.2': 'Travel & map: rutas de reserva siempre en el mapa, la píldora Explorar lugares, optimización de la ruta desde tu alojamiento, códigos de reserva difuminados y rutas de reserva etiquetadas.', 'help.ctx.settings-display.bullet.3': @@ -1114,7 +1114,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Elige el idioma de la interfaz en Language & region. TREK cambia al momento, en cada dispositivo en el que inicies sesión.', 'help.guide.language-region.step.2': - 'Debajo, elige el formato de hora, la moneda de visualización, y las unidades de distancia y temperatura.', + 'Debajo, elige el formato de hora, el día en que comienza la semana en todos los selectores de fecha, la moneda de visualización, y las unidades de distancia y temperatura.', 'help.guide.language-region.result': 'Fechas, distancias y dinero se leen como esperas; la moneda propia de un viaje sigue apareciendo junto a los importes convertidos.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/es/settings.ts b/shared/src/i18n/es/settings.ts index 74f0546cd..08a8e31b6 100644 --- a/shared/src/i18n/es/settings.ts +++ b/shared/src/i18n/es/settings.ts @@ -78,6 +78,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Unidad de temperatura', 'settings.distance': 'Unidad de distancia', 'settings.timeFormat': 'Formato de hora', + 'settings.weekStart': 'La semana comienza el', + 'settings.weekStartHint': 'Primer día de la semana en todos los selectores de fecha. Vacay tiene su propio ajuste.', 'settings.blurBookingCodes': 'Difuminar códigos de reserva', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/et/help.ts b/shared/src/i18n/et/help.ts index 01e4e8617..5dd9ca1a2 100644 --- a/shared/src/i18n/et/help.ts +++ b/shared/src/i18n/et/help.ts @@ -1024,7 +1024,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Keel, ühikud ja valuuta, kaardi ja broneeringute käitumine ning see, millega TREK avaneb. Iga muudatus rakendub kohe.', 'help.ctx.settings-display.bullet.1': - 'Keel ja piirkond: liidese keel, ajavorming, kuvamisvaluuta ning vahemaa- ja temperatuuriühikud.', + 'Keel ja piirkond: liidese keel, ajavorming, nädala esimene päev, kuvamisvaluuta ning vahemaa- ja temperatuuriühikud.', 'help.ctx.settings-display.bullet.2': 'Reisimine ja kaart: broneeringute marsruudid alati kaardil, kohtade avastamise nupp, marsruudi optimeerimine majutuskohast, hägustatud broneerimiskoodid ja siltidega broneeringute marsruudid.', 'help.ctx.settings-display.bullet.3': @@ -1093,7 +1093,8 @@ const help: TranslationStrings = { 'help.guide.language-region.goal': 'Pane TREK rääkima sinu keelt ja arvestama nii, nagu sina harjunud oled.', 'help.guide.language-region.step.1': 'Vali liidese keel jaotises Keel ja piirkond. TREK vahetab keele kohe igas seadmes, kuhu sisse logid.', - 'help.guide.language-region.step.2': 'Selle all vali ajavorming, kuvamisvaluuta ning vahemaa- ja temperatuuriühikud.', + 'help.guide.language-region.step.2': + 'Selle all vali ajavorming, nädala alguspäev kõigis kuupäevavalijates, kuvamisvaluuta ning vahemaa- ja temperatuuriühikud.', 'help.guide.language-region.result': 'Kuupäevad, vahemaad ja rahasummad kuvatakse nii, nagu ootad; reisi enda valuuta on endiselt näha teisendatud summade kõrval.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/et/settings.ts b/shared/src/i18n/et/settings.ts index 1b74849b5..52554ca5c 100644 --- a/shared/src/i18n/et/settings.ts +++ b/shared/src/i18n/et/settings.ts @@ -88,6 +88,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperatuuriühik', 'settings.distance': 'Vahemaaühik', 'settings.timeFormat': 'Ajavorming', + 'settings.weekStart': 'Nädala alguspäev', + 'settings.weekStartHint': 'Nädala esimene päev kõigis kuupäevavalijates. Vacayl on oma seade.', 'settings.bookingLabels': 'Broneeringute marsruutide sildid', 'settings.bookingLabelsHint': 'Näita kaardil jaamade ja lennujaamade nimesid. Väljalülitatuna näidatakse ainult ikooni.', diff --git a/shared/src/i18n/fr/help.ts b/shared/src/i18n/fr/help.ts index 153b384b7..9204b8dde 100644 --- a/shared/src/i18n/fr/help.ts +++ b/shared/src/i18n/fr/help.ts @@ -1061,7 +1061,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Langue, unités et devise, le comportement de la carte et des réservations, et ce sur quoi TREK s’ouvre. Chaque changement ici s’applique aussitôt.', 'help.ctx.settings-display.bullet.1': - 'Language & region : la langue de l’interface, le format de l’heure, la devise d’affichage, et les unités de distance et de température.', + 'Language & region : la langue de l’interface, le format de l’heure, le premier jour de la semaine, la devise d’affichage, et les unités de distance et de température.', 'help.ctx.settings-display.bullet.2': 'Travel & map : les itinéraires de réservation toujours sur la carte, la pastille Explorer les lieux, l’optimisation de l’itinéraire depuis votre hébergement, les codes de réservation masqués et les itinéraires de réservation étiquetés.', 'help.ctx.settings-display.bullet.3': @@ -1132,7 +1132,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Choisissez la langue de l’interface dans Language & region. TREK change aussitôt, sur chaque appareil où vous vous connectez.', 'help.guide.language-region.step.2': - 'En dessous, choisissez le format de l’heure, la devise d’affichage, et les unités de distance et de température.', + 'En dessous, choisissez le format de l’heure, le jour par lequel commence la semaine dans tous les sélecteurs de date, la devise d’affichage, et les unités de distance et de température.', 'help.guide.language-region.result': 'Dates, distances et montants se lisent comme vous l’attendez ; la devise propre à un voyage reste affichée à côté des montants convertis.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/fr/settings.ts b/shared/src/i18n/fr/settings.ts index eb1364481..1ecf1574f 100644 --- a/shared/src/i18n/fr/settings.ts +++ b/shared/src/i18n/fr/settings.ts @@ -80,6 +80,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Unité de température', 'settings.distance': 'Unité de distance', 'settings.timeFormat': "Format de l'heure", + 'settings.weekStart': 'La semaine commence le', + 'settings.weekStartHint': 'Premier jour de la semaine dans tous les sélecteurs de date. Vacay a son propre réglage.', 'settings.blurBookingCodes': 'Masquer les codes de réservation', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/gr/help.ts b/shared/src/i18n/gr/help.ts index d16c380aa..c74a98ad6 100644 --- a/shared/src/i18n/gr/help.ts +++ b/shared/src/i18n/gr/help.ts @@ -1068,7 +1068,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Γλώσσα, μονάδες και νόμισμα, πώς συμπεριφέρονται ο χάρτης και οι κρατήσεις, και με τι ανοίγει το TREK. Κάθε αλλαγή εδώ εφαρμόζεται αμέσως.', 'help.ctx.settings-display.bullet.1': - 'Language & region: η γλώσσα της διεπαφής, η μορφή ώρας, το νόμισμα εμφάνισης και οι μονάδες απόστασης και θερμοκρασίας.', + 'Language & region: η γλώσσα της διεπαφής, η μορφή ώρας, η πρώτη ημέρα της εβδομάδας, το νόμισμα εμφάνισης και οι μονάδες απόστασης και θερμοκρασίας.', 'help.ctx.settings-display.bullet.2': 'Travel & map: διαδρομές κρατήσεων πάντα στον χάρτη, το κουμπί Εξερεύνηση μερών, βελτιστοποίηση διαδρομής από το κατάλυμά σας, θολωμένοι κωδικοί κρατήσεων και διαδρομές κρατήσεων με ετικέτες.', 'help.ctx.settings-display.bullet.3': @@ -1137,7 +1137,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Επιλέξτε τη γλώσσα της διεπαφής στο Language & region. Το TREK αλλάζει αμέσως, σε κάθε συσκευή όπου συνδέεστε.', 'help.guide.language-region.step.2': - 'Από κάτω, επιλέξτε τη μορφή ώρας, το νόμισμα εμφάνισης και τις μονάδες απόστασης και θερμοκρασίας.', + 'Από κάτω, επιλέξτε τη μορφή ώρας, την ημέρα με την οποία ξεκινά η εβδομάδα σε κάθε επιλογέα ημερομηνίας, το νόμισμα εμφάνισης και τις μονάδες απόστασης και θερμοκρασίας.', 'help.guide.language-region.result': 'Ημερομηνίες, αποστάσεις και χρήματα διαβάζονται όπως περιμένετε· το δικό του νόμισμα ενός ταξιδιού εξακολουθεί να εμφανίζεται δίπλα στα μετατρεπόμενα ποσά.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/gr/settings.ts b/shared/src/i18n/gr/settings.ts index 084492ee7..867c56868 100644 --- a/shared/src/i18n/gr/settings.ts +++ b/shared/src/i18n/gr/settings.ts @@ -82,6 +82,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Μονάδα Θερμοκρασίας', 'settings.distance': 'Μονάδα Απόστασης', 'settings.timeFormat': 'Μορφή Ώρας', + 'settings.weekStart': 'Η εβδομάδα ξεκινά την', + 'settings.weekStartHint': 'Πρώτη ημέρα της εβδομάδας σε κάθε επιλογέα ημερομηνίας. Το Vacay έχει δική του ρύθμιση.', 'settings.bookingLabels': 'Ετικέτες διαδρομής κρατήσεων', 'settings.bookingLabelsHint': 'Εμφάνιση ονομάτων σταθμών / αεροδρομίων στον χάρτη. Όταν είναι απενεργοποιημένο, εμφανίζεται μόνο το εικονίδιο.', diff --git a/shared/src/i18n/hu/help.ts b/shared/src/i18n/hu/help.ts index fcccd7762..8bfa0e713 100644 --- a/shared/src/i18n/hu/help.ts +++ b/shared/src/i18n/hu/help.ts @@ -1040,7 +1040,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Nyelv, mértékegységek és pénznem, hogyan viselkedik a térkép és a foglalások, és mivel nyílik meg a TREK. Itt minden változás azonnal érvényes.', 'help.ctx.settings-display.bullet.1': - 'Language & region: a felület nyelve, az időformátum, a megjelenítési pénznem, valamint a távolság- és hőmérséklet-egységek.', + 'Language & region: a felület nyelve, az időformátum, a hét első napja, a megjelenítési pénznem, valamint a távolság- és hőmérséklet-egységek.', 'help.ctx.settings-display.bullet.2': 'Travel & map: foglalási útvonalak mindig a térképen, a Helyek felfedezése pirula, útvonal-optimalizálás a szállástól, elrejtett foglalási kódok és címkézett foglalási útvonalak.', 'help.ctx.settings-display.bullet.3': @@ -1107,7 +1107,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Válaszd ki a felület nyelvét a Language & region alatt. A TREK azonnal vált, minden eszközön, ahol bejelentkezel.', 'help.guide.language-region.step.2': - 'Alatta válaszd ki az időformátumot, a megjelenítési pénznemet, valamint a távolság- és hőmérséklet-egységeket.', + 'Alatta válaszd ki az időformátumot, a hét kezdőnapját minden dátumválasztóban, a megjelenítési pénznemet, valamint a távolság- és hőmérséklet-egységeket.', 'help.guide.language-region.result': 'A dátumok, távolságok és pénzösszegek úgy olvashatók, ahogy várod; az utazás saját pénzneme továbbra is ott áll az átváltott összegek mellett.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/hu/settings.ts b/shared/src/i18n/hu/settings.ts index 7e0b24cfb..defc6bf5d 100644 --- a/shared/src/i18n/hu/settings.ts +++ b/shared/src/i18n/hu/settings.ts @@ -78,6 +78,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Hőmérséklet egység', 'settings.distance': 'Távolság egység', 'settings.timeFormat': 'Időformátum', + 'settings.weekStart': 'A hét kezdőnapja', + 'settings.weekStartHint': 'A hét első napja minden dátumválasztóban. A Vacay saját beállítást használ.', 'settings.blurBookingCodes': 'Foglalási kódok elrejtése', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/id/help.ts b/shared/src/i18n/id/help.ts index 2e744e973..dc2d2fef8 100644 --- a/shared/src/i18n/id/help.ts +++ b/shared/src/i18n/id/help.ts @@ -1037,7 +1037,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Bahasa, satuan, dan mata uang, cara peta dan pemesanan berperilaku, serta apa yang dibuka TREK saat mulai. Setiap perubahan di sini langsung berlaku.', 'help.ctx.settings-display.bullet.1': - '“Language & region”: bahasa antarmuka, format waktu, mata uang tampilan, serta satuan jarak dan suhu.', + '“Language & region”: bahasa antarmuka, format waktu, hari pertama dalam seminggu, mata uang tampilan, serta satuan jarak dan suhu.', 'help.ctx.settings-display.bullet.2': '“Travel & map”: rute pemesanan selalu di peta, pil Jelajahi tempat, optimalisasi rute dari akomodasi Anda, kode pemesanan yang disamarkan, dan rute pemesanan berlabel.', 'help.ctx.settings-display.bullet.3': @@ -1108,7 +1108,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Pilih bahasa antarmuka di “Language & region”. TREK langsung beralih, di setiap perangkat tempat Anda masuk.', 'help.guide.language-region.step.2': - 'Di bawahnya, pilih format waktu, mata uang tampilan, serta satuan jarak dan suhu.', + 'Di bawahnya, pilih format waktu, hari yang mengawali minggu di setiap pemilih tanggal, mata uang tampilan, serta satuan jarak dan suhu.', 'help.guide.language-region.result': 'Tanggal, jarak, dan uang terbaca seperti yang Anda harapkan; mata uang perjalanan itu sendiri tetap tampil di samping jumlah yang dikonversi.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/id/settings.ts b/shared/src/i18n/id/settings.ts index 22b29cf44..77430dc6d 100644 --- a/shared/src/i18n/id/settings.ts +++ b/shared/src/i18n/id/settings.ts @@ -76,6 +76,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Satuan Suhu', 'settings.distance': 'Satuan Jarak', 'settings.timeFormat': 'Format Waktu', + 'settings.weekStart': 'Awal minggu', + 'settings.weekStartHint': 'Hari pertama dalam seminggu di setiap pemilih tanggal. Vacay punya pengaturannya sendiri.', 'settings.blurBookingCodes': 'Sembunyikan Kode Pemesanan', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/it/help.ts b/shared/src/i18n/it/help.ts index bd6e757b2..28c24c9e9 100644 --- a/shared/src/i18n/it/help.ts +++ b/shared/src/i18n/it/help.ts @@ -1037,7 +1037,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Lingua, unità e valuta, come si comportano mappa e prenotazioni, e con cosa si apre TREK. Ogni modifica qui si applica subito.', 'help.ctx.settings-display.bullet.1': - 'Language & region: la lingua dell’interfaccia, il formato dell’ora, la valuta di visualizzazione, e le unità di distanza e temperatura.', + 'Language & region: la lingua dell’interfaccia, il formato dell’ora, il primo giorno della settimana, la valuta di visualizzazione, e le unità di distanza e temperatura.', 'help.ctx.settings-display.bullet.2': 'Travel & map: i percorsi delle prenotazioni sempre sulla mappa, la pillola Esplora luoghi, l’ottimizzazione del percorso dal tuo alloggio, i codici di prenotazione nascosti e i percorsi delle prenotazioni etichettati.', 'help.ctx.settings-display.bullet.3': @@ -1107,7 +1107,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Scegli la lingua dell’interfaccia in Language & region. TREK cambia subito, su ogni dispositivo in cui accedi.', 'help.guide.language-region.step.2': - 'Sotto, scegli il formato dell’ora, la valuta di visualizzazione, e le unità di distanza e temperatura.', + 'Sotto, scegli il formato dell’ora, il giorno con cui inizia la settimana in ogni selettore di date, la valuta di visualizzazione, e le unità di distanza e temperatura.', 'help.guide.language-region.result': 'Date, distanze e soldi si leggono come ti aspetti; la valuta propria di un viaggio resta accanto agli importi convertiti.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/it/settings.ts b/shared/src/i18n/it/settings.ts index 09d76c7f4..e537fd1a2 100644 --- a/shared/src/i18n/it/settings.ts +++ b/shared/src/i18n/it/settings.ts @@ -79,6 +79,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Unità di Temperatura', 'settings.distance': 'Unità di Distanza', 'settings.timeFormat': 'Formato Ora', + 'settings.weekStart': 'La settimana inizia il', + 'settings.weekStartHint': 'Primo giorno della settimana in ogni selettore di date. Vacay ha una sua impostazione.', 'settings.blurBookingCodes': 'Nascondi codici di prenotazione', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/ja/help.ts b/shared/src/i18n/ja/help.ts index 5cb7db7d7..fbc7df869 100644 --- a/shared/src/i18n/ja/help.ts +++ b/shared/src/i18n/ja/help.ts @@ -976,7 +976,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': '言語、単位、通貨、地図と予約の振る舞い、そしてTREKが最初に開く画面。ここでの変更はすべて即座に反映されます。', 'help.ctx.settings-display.bullet.1': - '「Language & region」:インターフェースの言語、時刻形式、表示通貨、距離と温度の単位。', + '「Language & region」:インターフェースの言語、時刻形式、週の最初の曜日、表示通貨、距離と温度の単位。', 'help.ctx.settings-display.bullet.2': '「Travel & map」:予約ルートを常に地図に表示、スポットを探すピル、宿泊先を起点にしたルート最適化、予約コードのぼかし、予約ルートのラベル表示。', 'help.ctx.settings-display.bullet.3': @@ -1046,7 +1046,8 @@ const help: TranslationStrings = { 'help.guide.language-region.goal': 'TREKをあなたの言語で話させ、あなたの流儀で数えさせます。', 'help.guide.language-region.step.1': '「Language & region」でインターフェースの言語を選びます。TREKは即座に切り替わり、サインインしているどの端末にも及びます。', - 'help.guide.language-region.step.2': 'その下で、時刻形式、表示通貨、距離と温度の単位を選びます。', + 'help.guide.language-region.step.2': + 'その下で、時刻形式、すべての日付選択で週を何曜日から始めるか、表示通貨、距離と温度の単位を選びます。', 'help.guide.language-region.result': '日付、距離、金額が期待どおりに読めます。旅行ごとの通貨は、換算後の金額の隣に引き続き表示されます。', 'help.guide.language-region.tip.1': '表示通貨は旅行をまたいだ合計のためのものです。各旅行は設定した通貨を保ちます。', diff --git a/shared/src/i18n/ja/settings.ts b/shared/src/i18n/ja/settings.ts index cf3abec2b..bc44b2401 100644 --- a/shared/src/i18n/ja/settings.ts +++ b/shared/src/i18n/ja/settings.ts @@ -75,6 +75,8 @@ const settings: TranslationStrings = { 'settings.temperature': '温度単位', 'settings.distance': '距離単位', 'settings.timeFormat': '時刻形式', + 'settings.weekStart': '週の開始', + 'settings.weekStartHint': 'すべての日付選択で週の最初の曜日になります。Vacay には専用の設定があります。', 'settings.bookingLabels': '予約ルートのラベル', 'settings.bookingLabelsHint': '地図に駅・空港名を表示。オフ時はアイコンのみ。', 'settings.blurBookingCodes': '予約コードをぼかす', diff --git a/shared/src/i18n/ko/help.ts b/shared/src/i18n/ko/help.ts index c4e673393..cb5981240 100644 --- a/shared/src/i18n/ko/help.ts +++ b/shared/src/i18n/ko/help.ts @@ -956,7 +956,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': '언어, 단위, 통화, 지도와 예약이 동작하는 방식, 그리고 TREK이 처음 여는 화면. 여기서의 모든 변경은 즉시 적용됩니다.', 'help.ctx.settings-display.bullet.1': - '“Language & region”: 인터페이스 언어, 시간 형식, 표시 통화, 거리 및 온도 단위.', + '“Language & region”: 인터페이스 언어, 시간 형식, 한 주의 첫 요일, 표시 통화, 거리 및 온도 단위.', 'help.ctx.settings-display.bullet.2': '“Travel & map”: 예약 경로를 항상 지도에 표시, 장소 탐색 알약 버튼, 숙소 기준 경로 최적화, 예약 코드 흐리게, 예약 경로에 이름 표시.', 'help.ctx.settings-display.bullet.3': @@ -1020,7 +1020,8 @@ const help: TranslationStrings = { 'help.guide.language-region.goal': 'TREK이 내 언어로 말하고 내 방식으로 세게 합니다.', 'help.guide.language-region.step.1': '“Language & region”에서 인터페이스 언어를 고릅니다. TREK은 즉시 바뀌며 로그인한 모든 기기에 반영됩니다.', - 'help.guide.language-region.step.2': '그 아래에서 시간 형식, 표시 통화, 거리 및 온도 단위를 고릅니다.', + 'help.guide.language-region.step.2': + '그 아래에서 시간 형식, 모든 날짜 선택기에서 한 주가 시작되는 요일, 표시 통화, 거리 및 온도 단위를 고릅니다.', 'help.guide.language-region.result': '날짜, 거리, 금액이 기대한 대로 읽힙니다. 여행 자체의 통화는 환산된 금액 옆에 계속 표시됩니다.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/ko/settings.ts b/shared/src/i18n/ko/settings.ts index 1357cb049..3c920c3b9 100644 --- a/shared/src/i18n/ko/settings.ts +++ b/shared/src/i18n/ko/settings.ts @@ -76,6 +76,8 @@ const settings: TranslationStrings = { 'settings.temperature': '온도 단위', 'settings.distance': '거리 단위', 'settings.timeFormat': '시간 형식', + 'settings.weekStart': '주 시작 요일', + 'settings.weekStartHint': '모든 날짜 선택기에서 한 주의 첫 요일입니다. Vacay에는 별도의 설정이 있습니다.', 'settings.bookingLabels': '예약 경로 레이블', 'settings.bookingLabelsHint': '지도에 역 / 공항 이름을 표시합니다. 끄면 아이콘만 표시됩니다.', 'settings.blurBookingCodes': '예약 코드 흐리게', diff --git a/shared/src/i18n/nl/help.ts b/shared/src/i18n/nl/help.ts index 0fd00fc28..35a2e59ed 100644 --- a/shared/src/i18n/nl/help.ts +++ b/shared/src/i18n/nl/help.ts @@ -1042,7 +1042,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Taal, eenheden en valuta, hoe kaart en boekingen zich gedragen, en waarmee TREK opent. Elke wijziging hier geldt meteen.', 'help.ctx.settings-display.bullet.1': - 'Language & region: de taal van de interface, de tijdnotatie, de weergavevaluta, en de eenheden voor afstand en temperatuur.', + 'Language & region: de taal van de interface, de tijdnotatie, de eerste dag van de week, de weergavevaluta, en de eenheden voor afstand en temperatuur.', 'help.ctx.settings-display.bullet.2': 'Travel & map: boekingsroutes altijd op de kaart, de pil Plaatsen ontdekken, routeoptimalisatie vanaf je accommodatie, vervaagde boekingscodes en boekingsroutes met label.', 'help.ctx.settings-display.bullet.3': @@ -1111,7 +1111,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Kies de taal van de interface in Language & region. TREK schakelt meteen om, op elk apparaat waarop je inlogt.', 'help.guide.language-region.step.2': - 'Daaronder kies je de tijdnotatie, de weergavevaluta, en de eenheden voor afstand en temperatuur.', + 'Daaronder kies je de tijdnotatie, de dag waarop de week in elke datumkiezer begint, de weergavevaluta, en de eenheden voor afstand en temperatuur.', 'help.guide.language-region.result': 'Datums, afstanden en geld lezen zoals je verwacht; de eigen valuta van een reis staat nog steeds naast omgerekende bedragen.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/nl/settings.ts b/shared/src/i18n/nl/settings.ts index 39b929794..e0149db8e 100644 --- a/shared/src/i18n/nl/settings.ts +++ b/shared/src/i18n/nl/settings.ts @@ -77,6 +77,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperatuureenheid', 'settings.distance': 'Afstandseenheid', 'settings.timeFormat': 'Tijdnotatie', + 'settings.weekStart': 'Week begint op', + 'settings.weekStartHint': 'Eerste dag van de week in elke datumkiezer. Vacay heeft een eigen instelling.', 'settings.blurBookingCodes': 'Boekingscodes vervagen', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/pl/help.ts b/shared/src/i18n/pl/help.ts index e5efa1af5..0eb3e1f59 100644 --- a/shared/src/i18n/pl/help.ts +++ b/shared/src/i18n/pl/help.ts @@ -1014,7 +1014,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Język, jednostki i waluta, jak zachowują się mapa i rezerwacje oraz z czym TREK się otwiera. Każda zmiana tutaj działa od razu.', 'help.ctx.settings-display.bullet.1': - 'Language & region: język interfejsu, format czasu, waluta wyświetlania oraz jednostki odległości i temperatury.', + 'Language & region: język interfejsu, format czasu, pierwszy dzień tygodnia, waluta wyświetlania oraz jednostki odległości i temperatury.', 'help.ctx.settings-display.bullet.2': 'Travel & map: trasy rezerwacji zawsze na mapie, pigułka Odkrywaj miejsca, optymalizacja trasy od zakwaterowania, rozmyte kody rezerwacji i etykiety tras rezerwacji.', 'help.ctx.settings-display.bullet.3': @@ -1084,7 +1084,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Wybierz język interfejsu w Language & region. TREK przełącza się od razu, na każdym urządzeniu, na którym się logujesz.', 'help.guide.language-region.step.2': - 'Poniżej wybierz format czasu, walutę wyświetlania oraz jednostki odległości i temperatury.', + 'Poniżej wybierz format czasu, dzień, od którego zaczyna się tydzień we wszystkich wyborach daty, walutę wyświetlania oraz jednostki odległości i temperatury.', 'help.guide.language-region.result': 'Daty, odległości i pieniądze czyta się tak, jak oczekujesz; własna waluta podróży nadal pokazuje się obok przeliczonych kwot.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/pl/settings.ts b/shared/src/i18n/pl/settings.ts index a5a95615d..55e8e09a4 100644 --- a/shared/src/i18n/pl/settings.ts +++ b/shared/src/i18n/pl/settings.ts @@ -76,6 +76,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Jednostka temperatury', 'settings.distance': 'Jednostka odległości', 'settings.timeFormat': 'Format czasu', + 'settings.weekStart': 'Tydzień zaczyna się w', + 'settings.weekStartHint': 'Pierwszy dzień tygodnia we wszystkich wyborach daty. Vacay ma własne ustawienie.', 'settings.blurBookingCodes': 'Rozmyj kody rezerwacji', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/ru/help.ts b/shared/src/i18n/ru/help.ts index 321520ffe..168089b23 100644 --- a/shared/src/i18n/ru/help.ts +++ b/shared/src/i18n/ru/help.ts @@ -1014,7 +1014,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Язык, единицы и валюта, как ведут себя карта и бронирования и с чего открывается TREK. Каждое изменение здесь применяется сразу.', 'help.ctx.settings-display.bullet.1': - 'Язык и регион: язык интерфейса, формат времени, валюта отображения, единицы расстояния и температуры.', + 'Язык и регион: язык интерфейса, формат времени, первый день недели, валюта отображения, единицы расстояния и температуры.', 'help.ctx.settings-display.bullet.2': 'Карта и путешествия: маршруты бронирований всегда на карте, кнопка Поиск мест, оптимизация маршрута от места проживания, скрытые коды бронирования и подписи маршрутов бронирований.', 'help.ctx.settings-display.bullet.3': @@ -1085,7 +1085,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Выберите язык интерфейса в разделе Язык и регион. TREK переключается сразу, на каждом устройстве, где вы входите.', 'help.guide.language-region.step.2': - 'Ниже выберите формат времени, валюту отображения, единицы расстояния и температуры.', + 'Ниже выберите формат времени, день, с которого начинается неделя во всех полях выбора даты, валюту отображения, единицы расстояния и температуры.', 'help.guide.language-region.result': 'Даты, расстояния и деньги читаются так, как вы ожидаете; собственная валюта поездки по-прежнему показывается рядом с пересчитанными суммами.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/ru/settings.ts b/shared/src/i18n/ru/settings.ts index 6af106b62..a9e87b587 100644 --- a/shared/src/i18n/ru/settings.ts +++ b/shared/src/i18n/ru/settings.ts @@ -76,6 +76,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Единица температуры', 'settings.distance': 'Единица расстояния', 'settings.timeFormat': 'Формат времени', + 'settings.weekStart': 'Неделя начинается с', + 'settings.weekStartHint': 'Первый день недели во всех выборах даты. У Vacay своя настройка.', 'settings.blurBookingCodes': 'Скрыть коды бронирования', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/sk/help.ts b/shared/src/i18n/sk/help.ts index 75b126d50..f02107f5e 100644 --- a/shared/src/i18n/sk/help.ts +++ b/shared/src/i18n/sk/help.ts @@ -1033,7 +1033,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Jazyk, jednotky a mena, správanie mapy a rezervácií a to, čím sa TREK otvorí. Každá zmena tu platí okamžite.', 'help.ctx.settings-display.bullet.1': - 'Jazyk a región: jazyk rozhrania, formát času, zobrazovaná mena a jednotky vzdialenosti a teploty.', + 'Jazyk a región: jazyk rozhrania, formát času, prvý deň týždňa, zobrazovaná mena a jednotky vzdialenosti a teploty.', 'help.ctx.settings-display.bullet.2': 'Cestovanie a mapa: trasy rezervácií vždy na mape, tlačidlo Objavovať miesta, optimalizácia trasy od ubytovania, skryté rezervačné kódy a popisky trás rezervácií.', 'help.ctx.settings-display.bullet.3': @@ -1103,7 +1103,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'V časti Jazyk a región vyberte jazyk rozhrania. TREK sa prepne okamžite na každom zariadení, na ktorom sa prihlásite.', 'help.guide.language-region.step.2': - 'Pod ním vyberte formát času, zobrazovanú menu a jednotky vzdialenosti a teploty.', + 'Pod ním vyberte formát času, deň, ktorým začína týždeň vo všetkých výberoch dátumu, zobrazovanú menu a jednotky vzdialenosti a teploty.', 'help.guide.language-region.result': 'Dátumy, vzdialenosti a peniaze sa zobrazujú tak, ako očakávate; vlastná mena cesty sa stále zobrazuje vedľa prepočítaných súm.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/sk/settings.ts b/shared/src/i18n/sk/settings.ts index 443b9c5e1..1da11824f 100644 --- a/shared/src/i18n/sk/settings.ts +++ b/shared/src/i18n/sk/settings.ts @@ -85,6 +85,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Jednotky teploty', 'settings.distance': 'Jednotky vzdialenosti', 'settings.timeFormat': 'Formát času', + 'settings.weekStart': 'Týždeň začína', + 'settings.weekStartHint': 'Prvý deň týždňa vo všetkých výberoch dátumu. Vacay má vlastné nastavenie.', 'settings.bookingLabels': 'Popisky trás rezervácií', 'settings.bookingLabelsHint': 'Zobrazuje názvy staníc / letísk na mape. Ak je vypnuté, zobrazí sa iba ikona.', 'settings.mapPoiPill': 'Objavovať miesta na mape', diff --git a/shared/src/i18n/sv/help.ts b/shared/src/i18n/sv/help.ts index be8a7352d..c5614401b 100644 --- a/shared/src/i18n/sv/help.ts +++ b/shared/src/i18n/sv/help.ts @@ -1003,7 +1003,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Språk, enheter och valuta, hur kartan och bokningarna beter sig, och vad TREK öppnar med. Varje ändring här slår igenom direkt.', 'help.ctx.settings-display.bullet.1': - 'Language & region: gränssnittets språk, tidsformatet, visningsvalutan samt avstånds- och temperaturenheter.', + 'Language & region: gränssnittets språk, tidsformatet, veckans första dag, visningsvalutan samt avstånds- och temperaturenheter.', 'help.ctx.settings-display.bullet.2': 'Travel & map: bokningsrutter alltid på kartan, Utforska platser-pillret, ruttoptimering från ditt boende, blurrade bokningskoder och etiketter på bokningsrutter.', 'help.ctx.settings-display.bullet.3': @@ -1071,7 +1071,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Välj gränssnittets språk under Language & region. TREK växlar direkt, på varje enhet du loggar in på.', 'help.guide.language-region.step.2': - 'Under det väljer du tidsformatet, visningsvalutan samt avstånds- och temperaturenheterna.', + 'Under det väljer du tidsformatet, vilken dag veckan börjar på i alla datumväljare, visningsvalutan samt avstånds- och temperaturenheterna.', 'help.guide.language-region.result': 'Datum, avstånd och pengar läses som du väntar dig; en resas egen valuta visas fortfarande bredvid omräknade belopp.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/sv/settings.ts b/shared/src/i18n/sv/settings.ts index 0bb6b9e78..d14873469 100644 --- a/shared/src/i18n/sv/settings.ts +++ b/shared/src/i18n/sv/settings.ts @@ -77,6 +77,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Temperaturenhet', 'settings.distance': 'Avståndsenhet', 'settings.timeFormat': 'Tidsformat', + 'settings.weekStart': 'Vecka börjar på', + 'settings.weekStartHint': 'Veckans första dag i alla datumväljare. Vacay har en egen inställning.', 'settings.bookingLabels': 'Etiketter för bokningsrutter', 'settings.bookingLabelsHint': 'Visa stations- och flygplatsnamn på kartan. När funktionen är avstängd visas endast ikonen.', diff --git a/shared/src/i18n/th/help.ts b/shared/src/i18n/th/help.ts index 549b91c18..7dc32ba98 100644 --- a/shared/src/i18n/th/help.ts +++ b/shared/src/i18n/th/help.ts @@ -873,7 +873,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.title': 'ทั่วไป', 'help.ctx.settings-display.summary': 'ภาษา หน่วย และสกุลเงิน การทำงานของแผนที่และการจอง และหน้าที่ TREK เปิดขึ้นมา การเปลี่ยนแปลงทุกอย่างที่นี่มีผลทันที', - 'help.ctx.settings-display.bullet.1': 'ภาษาและภูมิภาค: ภาษาของอินเทอร์เฟซ รูปแบบเวลา สกุลเงินที่แสดง และหน่วยระยะทางและอุณหภูมิ', + 'help.ctx.settings-display.bullet.1': 'ภาษาและภูมิภาค: ภาษาของอินเทอร์เฟซ รูปแบบเวลา วันแรกของสัปดาห์ สกุลเงินที่แสดง และหน่วยระยะทางและอุณหภูมิ', 'help.ctx.settings-display.bullet.2': 'การเดินทางและแผนที่: แสดงเส้นทางการจองบนแผนที่เสมอ ปุ่มสำรวจสถานที่ การเพิ่มประสิทธิภาพเส้นทางจากที่พัก รหัสการจองแบบเบลอ และป้ายกำกับเส้นทางการจอง', 'help.ctx.settings-display.bullet.3': @@ -931,7 +931,7 @@ const help: TranslationStrings = { 'help.guide.language-region.title': 'ตั้งค่าภาษา หน่วย และสกุลเงิน', 'help.guide.language-region.goal': 'ให้ TREK ใช้ภาษาของคุณและนับแบบที่คุณคุ้นเคย', 'help.guide.language-region.step.1': 'เลือกภาษาของอินเทอร์เฟซใน ภาษาและภูมิภาค TREK จะเปลี่ยนทันทีบนทุกอุปกรณ์ที่คุณลงชื่อเข้าใช้', - 'help.guide.language-region.step.2': 'ด้านล่างนั้น เลือกรูปแบบเวลา สกุลเงินที่แสดง และหน่วยระยะทางและอุณหภูมิ', + 'help.guide.language-region.step.2': 'ด้านล่างนั้น เลือกรูปแบบเวลา วันเริ่มต้นสัปดาห์ในตัวเลือกวันที่ทั้งหมด สกุลเงินที่แสดง และหน่วยระยะทางและอุณหภูมิ', 'help.guide.language-region.result': 'วันที่ ระยะทาง และจำนวนเงินจะแสดงตามที่คุณคาดไว้ สกุลเงินของทริปเองยังแสดงข้างจำนวนเงินที่แปลงแล้ว', 'help.guide.language-region.tip.1': 'สกุลเงินที่แสดงใช้สำหรับยอดรวมข้ามทริป แต่ละทริปยังคงใช้สกุลเงินที่คุณกำหนดไว้', diff --git a/shared/src/i18n/th/settings.ts b/shared/src/i18n/th/settings.ts index bca9fe832..f7ad38029 100644 --- a/shared/src/i18n/th/settings.ts +++ b/shared/src/i18n/th/settings.ts @@ -79,6 +79,8 @@ const settings: TranslationStrings = { 'settings.temperature': "หน่วยอุณหภูมิ", 'settings.distance': "หน่วยระยะทาง", 'settings.timeFormat': "รูปแบบเวลา", + 'settings.weekStart': "สัปดาห์เริ่มต้นในวัน", + 'settings.weekStartHint': 'วันแรกของสัปดาห์ในตัวเลือกวันที่ทั้งหมด Vacay มีการตั้งค่าของตัวเอง', 'settings.bookingLabels': "ป้ายกำกับเส้นทางการจอง", 'settings.bookingLabelsHint': "แสดงชื่อสถานี/สนามบินบนแผนที่ เมื่อปิด จะแสดงเฉพาะไอคอนเท่านั้น", 'settings.mapPoiPill': "สำรวจสถานที่บนแผนที่", diff --git a/shared/src/i18n/tr/help.ts b/shared/src/i18n/tr/help.ts index 74dd6d3ba..00fd14ab3 100644 --- a/shared/src/i18n/tr/help.ts +++ b/shared/src/i18n/tr/help.ts @@ -1021,7 +1021,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Dil, birimler ve para birimi, haritanın ve rezervasyonların nasıl davrandığı ve TREK’in neyle açılacağı. Buradaki her değişiklik hemen uygulanır.', 'help.ctx.settings-display.bullet.1': - 'Language & region: arayüz dili, saat biçimi, görüntüleme para birimi ile mesafe ve sıcaklık birimleri.', + 'Language & region: arayüz dili, saat biçimi, haftanın ilk günü, görüntüleme para birimi ile mesafe ve sıcaklık birimleri.', 'help.ctx.settings-display.bullet.2': 'Travel & map: rezervasyon rotaları her zaman haritada, Yerleri keşfet hapı, konaklamadan rota optimizasyonu, bulanık rezervasyon kodları ve etiketli rezervasyon rotaları.', 'help.ctx.settings-display.bullet.3': @@ -1089,7 +1089,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Language & region altında arayüz dilini seçin. TREK oturum açtığınız her cihazda hemen geçiş yapar.', 'help.guide.language-region.step.2': - 'Altında saat biçimini, görüntüleme para birimini ile mesafe ve sıcaklık birimlerini seçin.', + 'Altında saat biçimini, tüm tarih seçicilerde haftanın hangi günle başlayacağını, görüntüleme para birimini ile mesafe ve sıcaklık birimlerini seçin.', 'help.guide.language-region.result': 'Tarihler, mesafeler ve para beklediğiniz gibi okunur; bir gezinin kendi para birimi dönüştürülen tutarların yanında görünmeye devam eder.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/tr/settings.ts b/shared/src/i18n/tr/settings.ts index 5431d6099..1c42a050f 100644 --- a/shared/src/i18n/tr/settings.ts +++ b/shared/src/i18n/tr/settings.ts @@ -77,6 +77,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Sıcaklık Birimi', 'settings.distance': 'Mesafe Birimi', 'settings.timeFormat': 'Saat Biçimi', + 'settings.weekStart': 'Hafta başlangıcı', + 'settings.weekStartHint': "Tüm tarih seçicilerde haftanın ilk günü. Vacay'in kendi ayarı vardır.", 'settings.bookingLabels': 'Rezervasyon rota etiketleri', 'settings.bookingLabelsHint': 'Haritada istasyon / havalimanı adlarını göster. Kapalıyken yalnızca simge görünür.', 'settings.blurBookingCodes': 'Rezervasyon Kodlarını Bulanıklaştır', diff --git a/shared/src/i18n/uk/help.ts b/shared/src/i18n/uk/help.ts index 5a81885ad..8d9e2e4f3 100644 --- a/shared/src/i18n/uk/help.ts +++ b/shared/src/i18n/uk/help.ts @@ -1005,7 +1005,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Мова, одиниці й валюта, як поводяться карта та бронювання і з чого відкривається TREK. Кожна зміна тут застосовується одразу.', 'help.ctx.settings-display.bullet.1': - 'Language & region: мова інтерфейсу, формат часу, валюта відображення, одиниці відстані й температури.', + 'Language & region: мова інтерфейсу, формат часу, перший день тижня, валюта відображення, одиниці відстані й температури.', 'help.ctx.settings-display.bullet.2': 'Travel & map: маршрути бронювань завжди на карті, кнопка Досліджуйте місця, оптимізація маршруту від житла, приховані коди бронювання та підписи маршрутів бронювань.', 'help.ctx.settings-display.bullet.3': @@ -1075,7 +1075,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Виберіть мову інтерфейсу в розділі Language & region. TREK перемикається одразу, на кожному пристрої, де ви входите.', 'help.guide.language-region.step.2': - 'Нижче виберіть формат часу, валюту відображення, одиниці відстані й температури.', + 'Нижче виберіть формат часу, день, з якого починається тиждень в усіх полях вибору дати, валюту відображення, одиниці відстані й температури.', 'help.guide.language-region.result': 'Дати, відстані й гроші читаються так, як ви очікуєте; власна валюта поїздки, як і раніше, показується поруч із перерахованими сумами.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/uk/settings.ts b/shared/src/i18n/uk/settings.ts index f7665827d..b7c0abc3d 100644 --- a/shared/src/i18n/uk/settings.ts +++ b/shared/src/i18n/uk/settings.ts @@ -78,6 +78,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Одиниця температури', 'settings.distance': 'Одиниця відстані', 'settings.timeFormat': 'Формат часу', + 'settings.weekStart': 'Тиждень починається з', + 'settings.weekStartHint': 'Перший день тижня в усіх виборах дати. Vacay має власне налаштування.', 'settings.blurBookingCodes': 'Приховати коди бронювання', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/vi/help.ts b/shared/src/i18n/vi/help.ts index 4436754c0..627d52842 100644 --- a/shared/src/i18n/vi/help.ts +++ b/shared/src/i18n/vi/help.ts @@ -1010,7 +1010,7 @@ const help: TranslationStrings = { 'help.ctx.settings-display.summary': 'Ngôn ngữ, đơn vị và tiền tệ, cách bản đồ và đặt chỗ hoạt động, và màn hình TREK mở lúc đầu. Mọi thay đổi ở đây có hiệu lực ngay.', 'help.ctx.settings-display.bullet.1': - '“Ngôn ngữ & khu vực”: ngôn ngữ giao diện, định dạng thời gian, tiền tệ hiển thị, đơn vị khoảng cách và nhiệt độ.', + '“Ngôn ngữ & khu vực”: ngôn ngữ giao diện, định dạng thời gian, ngày đầu tuần, tiền tệ hiển thị, đơn vị khoảng cách và nhiệt độ.', 'help.ctx.settings-display.bullet.2': '“Du lịch & bản đồ”: tuyến đường đặt chỗ luôn có trên bản đồ, nút khám phá địa điểm, tối ưu hóa tuyến đường từ chỗ ở của bạn, mã đặt chỗ được làm mờ và tuyến đường đặt chỗ có nhãn.', 'help.ctx.settings-display.bullet.3': @@ -1080,7 +1080,7 @@ const help: TranslationStrings = { 'help.guide.language-region.step.1': 'Chọn ngôn ngữ giao diện trong “Ngôn ngữ & khu vực”. TREK chuyển ngay, trên mọi thiết bị bạn đăng nhập.', 'help.guide.language-region.step.2': - 'Bên dưới, chọn định dạng thời gian, tiền tệ hiển thị, đơn vị khoảng cách và nhiệt độ.', + 'Bên dưới, chọn định dạng thời gian, ngày bắt đầu tuần trong mọi bộ chọn ngày, tiền tệ hiển thị, đơn vị khoảng cách và nhiệt độ.', 'help.guide.language-region.result': 'Ngày tháng, khoảng cách và tiền đọc đúng như bạn mong đợi; tiền tệ riêng của chuyến đi vẫn hiện bên cạnh số tiền đã quy đổi.', 'help.guide.language-region.tip.1': diff --git a/shared/src/i18n/vi/settings.ts b/shared/src/i18n/vi/settings.ts index 85234a0f2..c0a746386 100644 --- a/shared/src/i18n/vi/settings.ts +++ b/shared/src/i18n/vi/settings.ts @@ -78,6 +78,8 @@ const settings: TranslationStrings = { 'settings.temperature': 'Đơn vị nhiệt độ', 'settings.distance': 'Đơn vị khoảng cách', 'settings.timeFormat': 'Định dạng thời gian', + 'settings.weekStart': 'Tuần bắt đầu vào', + 'settings.weekStartHint': 'Ngày đầu tuần trong mọi bộ chọn ngày. Vacay có cài đặt riêng.', 'settings.bookingLabels': 'Nhãn lộ trình đặt chỗ', 'settings.bookingLabelsHint': 'Hiển thị tên ga/sân bay trên bản đồ. Khi tắt, chỉ có biểu tượng được hiển thị.', 'settings.mapPoiPill': 'Khám phá các địa điểm trên bản đồ', diff --git a/shared/src/i18n/zh-TW/help.ts b/shared/src/i18n/zh-TW/help.ts index 7cbd78b4d..f7e3617f4 100644 --- a/shared/src/i18n/zh-TW/help.ts +++ b/shared/src/i18n/zh-TW/help.ts @@ -853,7 +853,8 @@ const help: TranslationStrings = { 'help.ctx.settings-display.title': '顯示', 'help.ctx.settings-display.summary': '語言、單位和貨幣,地圖與預訂的行為方式,以及 TREK 開啟時的頁面。這裡的每項變更都立即生效。', - 'help.ctx.settings-display.bullet.1': '「Language & region」:介面語言、時間格式、顯示貨幣,以及距離和溫度單位。', + 'help.ctx.settings-display.bullet.1': + '「Language & region」:介面語言、時間格式、每週的第一天、顯示貨幣,以及距離和溫度單位。', 'help.ctx.settings-display.bullet.2': '「Travel & map」:訂票路線一律顯示在地圖上、探索地點的小按鈕、從住宿地點最佳化路線、模糊預訂代碼,以及為預訂路線加上標籤。', 'help.ctx.settings-display.bullet.3': '「啟動」:TREK 開啟時是進入儀表板還是進行中的旅行,以及旅行的哪個分頁先顯示。', @@ -912,7 +913,8 @@ const help: TranslationStrings = { 'help.guide.language-region.goal': '讓 TREK 說你的語言,按你的方式計數。', 'help.guide.language-region.step.1': '在「Language & region」中選擇介面語言。TREK 立即切換,在你登入的每台裝置上都一樣。', - 'help.guide.language-region.step.2': '在它下方選擇時間格式、顯示貨幣,以及距離和溫度單位。', + 'help.guide.language-region.step.2': + '在它下方選擇時間格式、所有日期選擇器中每週從哪一天開始、顯示貨幣,以及距離和溫度單位。', 'help.guide.language-region.result': '日期、距離和金額按你期望的方式顯示;旅行自己的貨幣仍然顯示在換算金額旁邊。', 'help.guide.language-region.tip.1': '顯示貨幣用於跨旅行的合計;每次旅行保留你為它設定的貨幣。', 'help.guide.language-region.tip.2': '語言還決定 Vacay 和日記裡的星期和月份名稱。', diff --git a/shared/src/i18n/zh-TW/settings.ts b/shared/src/i18n/zh-TW/settings.ts index 5d18ae35c..20f31249a 100644 --- a/shared/src/i18n/zh-TW/settings.ts +++ b/shared/src/i18n/zh-TW/settings.ts @@ -73,6 +73,8 @@ const settings: TranslationStrings = { 'settings.temperature': '溫度單位', 'settings.distance': '距離單位', 'settings.timeFormat': '時間格式', + 'settings.weekStart': '每週開始於', + 'settings.weekStartHint': '所有日期選擇器中每週的第一天。Vacay 有獨立的設定。', 'settings.blurBookingCodes': '模糊預訂程式碼', 'settings.aiAlwaysRetry': 'Always retry booking imports with AI', 'settings.aiAlwaysRetryHint': 'When a file cannot be read by the standard parser, automatically retry it with AI.', diff --git a/shared/src/i18n/zh/help.ts b/shared/src/i18n/zh/help.ts index fe06a7354..e14e86387 100644 --- a/shared/src/i18n/zh/help.ts +++ b/shared/src/i18n/zh/help.ts @@ -839,7 +839,8 @@ const help: TranslationStrings = { 'help.ctx.settings-display.title': '显示', 'help.ctx.settings-display.summary': '语言、单位和货币,地图与预订的行为方式,以及 TREK 打开时的页面。这里的每项更改都立即生效。', - 'help.ctx.settings-display.bullet.1': '“语言与地区”:界面语言、时间格式、显示货币,以及距离和温度单位。', + 'help.ctx.settings-display.bullet.1': + '“语言与地区”:界面语言、时间格式、每周的第一天、显示货币,以及距离和温度单位。', 'help.ctx.settings-display.bullet.2': '“旅行与地图”:预订路线始终显示在地图上、探索地点的小按钮、从住宿地优化路线、隐藏预订编号,以及给预订路线加标签。', 'help.ctx.settings-display.bullet.3': '“启动”:TREK 打开时是进入仪表盘还是进行中的旅行,以及旅行的哪个标签页先显示。', @@ -892,7 +893,8 @@ const help: TranslationStrings = { 'help.guide.language-region.title': '设置语言、单位和货币', 'help.guide.language-region.goal': '让 TREK 说你的语言,按你的方式计数。', 'help.guide.language-region.step.1': '在“语言与地区”中选择界面语言。TREK 立即切换,在你登录的每台设备上都一样。', - 'help.guide.language-region.step.2': '在它下方选择时间格式、显示货币,以及距离和温度单位。', + 'help.guide.language-region.step.2': + '在它下方选择时间格式、所有日期选择器中每周从哪一天开始、显示货币,以及距离和温度单位。', 'help.guide.language-region.result': '日期、距离和金额按你期望的方式显示;旅行自己的货币仍然显示在换算金额旁边。', 'help.guide.language-region.tip.1': '显示货币用于跨旅行的合计;每次旅行保留你给它设定的货币。', 'help.guide.language-region.tip.2': '语言还决定 Vacay 和日记里的星期和月份名称。', diff --git a/shared/src/i18n/zh/settings.ts b/shared/src/i18n/zh/settings.ts index dcd83b4e0..530f49ac4 100644 --- a/shared/src/i18n/zh/settings.ts +++ b/shared/src/i18n/zh/settings.ts @@ -73,6 +73,8 @@ const settings: TranslationStrings = { 'settings.temperature': '温度单位', 'settings.distance': '距离单位', 'settings.timeFormat': '时间格式', + 'settings.weekStart': '每周开始于', + 'settings.weekStartHint': '所有日期选择器中每周的第一天。Vacay 有单独的设置。', 'settings.blurBookingCodes': '隐藏预订编号', 'settings.aiAlwaysRetry': '始终用 AI 重试预订导入', 'settings.aiAlwaysRetryHint': '当标准解析器无法读取文件时,自动改用 AI 重试。', diff --git a/shared/src/settings/settings.schema.ts b/shared/src/settings/settings.schema.ts index 0e56a9d85..1fef1b9fc 100644 --- a/shared/src/settings/settings.schema.ts +++ b/shared/src/settings/settings.schema.ts @@ -20,3 +20,17 @@ export const settingsBulkRequestSchema = z.object({ settings: z.record(z.string(), z.unknown()), }); export type SettingsBulkRequest = z.infer; + +/** + * The first column of every date picker (#2029). Stored as the day's name, like + * the other regional settings ('24h', 'metric'): getUserSettings JSON-parses + * each row, so a digit string would come back as a number, a name comes back + * unchanged. Vacay keeps its own per-plan week_start (0/1) next to this. + */ +export const WEEK_START_VALUES = ['monday', 'sunday', 'saturday'] as const; +export type WeekStart = (typeof WEEK_START_VALUES)[number]; +export const weekStartSchema = z.enum(WEEK_START_VALUES); +/** What a user who never picked one gets, and what every picker did before the setting existed. */ +export const DEFAULT_WEEK_START: WeekStart = 'monday'; +/** Date#getDay() of each value, the number a calendar grid computes with. */ +export const WEEK_START_DAY: Record = { monday: 1, sunday: 0, saturday: 6 }; diff --git a/wiki/Admin-Panel-Overview.md b/wiki/Admin-Panel-Overview.md index 6c82a49da..63f41ef11 100644 --- a/wiki/Admin-Panel-Overview.md +++ b/wiki/Admin-Panel-Overview.md @@ -30,6 +30,8 @@ The Admin Panel is divided into tabs. Most tabs are always visible; a few appear ![Admin panel on the User Defaults tab, setting instance-wide defaults for colour mode, temperature unit, distance unit, time format, currency and blurred booking codes](assets/AdminUserDefaults.png) +The **Week starts on** default decides which day opens each row of every date picker for users who have not picked their own (Monday unless set). + ### Routing services On desktop and mobile, **User Defaults** includes optional **Own routing engine** and **Own Valhalla instance** fields in the map section. Changes save when you leave the field; **reset** restores the built-in default. diff --git a/wiki/Display-Settings.md b/wiki/Display-Settings.md index d316f03a1..026bdc497 100644 --- a/wiki/Display-Settings.md +++ b/wiki/Display-Settings.md @@ -8,7 +8,7 @@ The General tab (Settings → General) controls your locale preferences and a fe Open the user menu in the top navigation bar, select **Settings**, and stay on the **General** tab — it is the tab the page opens on. -The tab is split into three sections: **Startup** (where opening TREK lands), **Language & region** (currency, language, temperature, distance, time format) and **Travel & map** (booking route labels, always show booking routes, explore places on the map, blur booking codes, optimize route from accommodation). +The tab is split into three sections: **Startup** (where opening TREK lands), **Language & region** (currency, language, temperature, distance, time format, week start) and **Travel & map** (booking route labels, always show booking routes, explore places on the map, blur booking codes, optimize route from accommodation). > Color mode (Light / Dark / Auto) is **not** here — it lives on the **Appearance** tab. See [Appearance-Settings](Appearance-Settings). @@ -99,6 +99,14 @@ Affects all time displays throughout the app. | 24h | 14:30 | | 12h | 2:30 PM | +## Week starts on + +The first column of every calendar in TREK: trip dates, bookings, expenses, to-dos, journal entries and photo date ranges. Choose **Monday** (the default), **Sunday** or **Saturday**; the choices show the day names in your language, and so do the weekday headers of the calendars. + +An administrator can set the default for everyone under **Admin → User Defaults**; your own choice always wins. Vacay keeps its own **Week start** per plan, see [Vacay](Vacay). + +The poll deadline on the phone uses the browser's own date field, which follows the device's region rather than this setting. + ## Booking route labels Shows or hides station / airport names on the endpoint markers of booking routes on the map. When off, only the icon is shown. Set to **On** or **Off**. diff --git a/wiki/MCP-Tools-and-Resources.md b/wiki/MCP-Tools-and-Resources.md index d470e23e2..27ae8bcd0 100644 --- a/wiki/MCP-Tools-and-Resources.md +++ b/wiki/MCP-Tools-and-Resources.md @@ -218,7 +218,7 @@ Requires `settings:read` or `settings:write`. | Tool | Description | |---|---| -| `get_display_settings` | Read the user's units, time format, language, default currency and start page. Read this before rendering a temperature, a distance or a clock time. | +| `get_display_settings` | Read the user's units, time format, first day of the week, language, default currency and start page. Read this before rendering a temperature, a distance or a clock time. | | `update_display_settings` | Change one or more of those preferences. Only display preferences: API keys, map tokens and LLM settings are refused, whatever is passed. | ### Calendar feeds diff --git a/wiki/User-Settings.md b/wiki/User-Settings.md index 74a6450fd..bee043fbb 100644 --- a/wiki/User-Settings.md +++ b/wiki/User-Settings.md @@ -12,7 +12,7 @@ If your account requires MFA setup, TREK redirects you directly to the **Account | Tab | Purpose | Shown when | |-----|---------|------------| -| General | Start page and start tab, currency, language, temperature unit, distance unit, time format, booking route labels, always show booking routes, map POI pills, blur booking codes, and optimize route from accommodation | Always | +| General | Start page and start tab, currency, language, temperature unit, distance unit, time format, week start, booking route labels, always show booking routes, map POI pills, blur booking codes, and optimize route from accommodation | Always | | Appearance | Color mode, color scheme / accent, readability (transparency, reduce motion, density, text size), and which widgets appear on your dashboard | Always | | Map | Map provider (Leaflet, Mapbox GL, or MapLibre GL), tile presets, map style and Mapbox token, 3D buildings, high-quality mode | Always | | Notifications | Email, webhook, ntfy, and in-app notification preferences | Always | @@ -38,6 +38,7 @@ The General tab controls the following preferences, all saved immediately on cha - **Temperature unit** — Celsius (°C) or Fahrenheit (°F). - **Distance unit** — Metric (km) or Imperial (mi). - **Time format** — 24h (14:30) or 12h (2:30 PM). +- **Week starts on**: Monday (the default), Sunday or Saturday: the first column of every date picker. See [Display-Settings](Display-Settings#week-starts-on). **Travel & map** diff --git a/wiki/Vacay.md b/wiki/Vacay.md index 7ababd16d..b19a86d3b 100644 --- a/wiki/Vacay.md +++ b/wiki/Vacay.md @@ -60,7 +60,7 @@ Each toggle's icon in the toolbar is the marker it places, so you can see what a **Settings** (gear icon) let you configure: - **Block weekends** — prevents logging on weekend days. You choose which days count as the weekend. -- **Week start** — Monday or Sunday. +- **Week start** — Monday or Sunday. This one is per plan and applies to the Vacay calendar only; every other calendar in TREK follows **Week starts on** under Settings → General. - **Carry-over** — toggle as described above. - **Vacation year** — Calendar, Fiscal or Hire date, as described under Leave year above. Unlike the rest of this panel it is personal to you rather than to the plan. - **Company holidays** — enable a shared company holiday layer that any fused user can edit.