Skip to content

feat(settings): region, clock and units follow the browser's region - #443

Merged
joszz merged 1 commit into
mainfrom
feat/regional-formats
Oct 10, 2026
Merged

joszz merged 1 commit into
mainfrom
feat/regional-formats

Conversation

@joszz

@joszz joszz commented Oct 10, 2026

Copy link
Copy Markdown
Owner

Pull Request

Summary

Times across the app were a mix of AM/PM and 24-hour. English was formatted as en-US (12-hour clock, month-first dates) while Dutch got nl-NL. Several components also called toLocaleTimeString themselves, and the gateway's schedule times were shown exactly as sent. Now every date and time goes through one formatter, and the region, the clock and each unit follow the region the browser is in, with a manual override for each.

  • Detection (utils/region.ts): the browser's time zone decides the region first, so an English browser in the Netherlands gets 24-hour times, km and bar. A region named in the browser languages comes next, then the region the first language is most spoken in.
    • The zone table utils/timeZoneRegions.ts is generated by frontend/scripts/gen-time-zone-regions.mjs from the CLDR data in Node's ICU. It includes the current IANA names Firefox reports (Asia/Kolkata) next to the CLDR ones Chromium and Safari report (Asia/Calcutta).
  • Settings > Region and units (was Units): Region, Clock (Automatic / 24-hour / 12-hour) and an "Automatic" choice for every unit. Each automatic choice names what it stands for ("Automatic: Netherlands", "Automatic: 24-hour (14:05)"), so a wrong guess is easy to spot. These rows now put the select under its label at full width; side by side, long options were cut off.
  • One formatter (utils/format.ts): formatDate, formatTime, formatDateTime, formatHour and formatTimeOfDay (for a stored HH:mm).
    • Dates use the interface language in the region's order (en-NL writes 09/10/2026).
    • Times use the chosen clock, with no leading zero on 12 hours ("2:05 PM", not "02:05 PM").
    • Numbers stay in the interface language, so English keeps 12.3 wherever the browser is.
  • Now on the chosen clock: the header timestamps, trip list, trip log and its CSV export, climate schedules, the peak drive hour statistic, and the gateway's charging and battery-heating schedule times.
  • Climate schedule time picker: gains an AM/PM select on a 12-hour clock. It still stores HH:mm on the 24-hour clock.
  • Units per region (regionUnits): miles in the US, the UK and their territories; Fahrenheit per CLDR's weather list; psi in the US, UK, Australia, Canada, India and New Zealand; kPa in Japan; metric with bar everywhere else.

Behaviour notes

  • Existing installs keep the units they stored: earlier builds saved the metric defaults, so nothing switches on update. Region and clock are new and start on automatic, which gives the same 24-hour clock for Dutch installs.
  • "Automatic" is resolved on each device and is not synced, so a phone abroad can differ; every explicit choice still follows the account.
  • Push notifications keep their fixed 24-hour HH:mm, since the Worker does not know a device's clock.
  • The maintenance log now defaults its date to the local day. It used the UTC day, which is yesterday just after midnight in Europe.

Tests

  • test-setup.ts pins detectRegion to NL, since CI runs in UTC with jsdom's en-US. region.spec.ts tests the real detection through vi.importActual.
  • New: region.spec.ts, RegionalSettings.spec.ts, region unit tables in units.spec.ts, 12-hour cases for TimeOfDaySelect, the store and the formatters. Specs that pinned 02:05 PM for English now pin the 24-hour default.
  • Checked in the running demo with Playwright as an en-US browser in Amsterdam (only 24-hour times, km, bar) and in New York (only 12-hour times, mi, psi, AM/PM picker). The settings section has no overflow at 1440 and 390 px.

The zone table adds about 3.8 KB gzip to the entry bundle. Detection has to run before the first render, so it is not lazy.

Type of Change

  • Bug fix (mixed 12-hour and 24-hour times; maintenance date default one day off after midnight)
  • New feature
  • Refactor / cleanup
  • Documentation
  • Dependency update
  • Other

Related Issues

None.

Checklist

  • Tests added or updated
  • Linting passes (pnpm lint / dotnet build)
  • No secrets or personal data committed
  • Responsive on mobile
  • i18n keys added for any new UI strings
  • If unraid/garagestack.xml changed: copied to joszz/unraid-community-apps after merge (not changed)

🤖 Generated with Claude Code

Times were a mix of AM/PM and 24-hour: English was formatted as en-US,
and several components called toLocaleTimeString themselves. Every date
and time now goes through utils/format.ts, which writes dates in the
interface language in the region's order and times on one chosen clock.

The region is detected from the browser's time zone first (an en-US
browser in the Netherlands is common, its time zone is not), then from
its languages. Settings > Region and units gets Region, Clock and an
"Automatic" choice for every unit, each naming what it stands for.
Installs keep the units they stored; numbers stay in the interface
language.

Also: the gateway's charging and battery-heating schedule times follow
the clock, the climate schedule time picker gains AM/PM on a 12-hour
clock, and the maintenance log's default date is the local day instead
of the UTC one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@joszz
joszz enabled auto-merge October 10, 2026 13:04
@joszz
joszz merged commit ca82aa0 into main Oct 10, 2026
24 checks passed
@joszz
joszz deleted the feat/regional-formats branch October 10, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant